最近对区块链的底层的一些算法以及机制做了一定的了解与研究,今天我们来看看比特币的底层激励机制也就是挖矿所形成的矿池所存在的一些攻击手法,希望大家能有所收获
对于区块链的相关技术有所了解的同学对于挖矿也一定不会陌生,这是工作量证明的共识机制的核心,大家一起求解一个密码学问题以获取可用的区块头,从而产生新的区块,早期的时候你直接用自己电脑都可以参与挖矿,然而随着比特币价值的增长,参与人数越来越多,大规模的GPU并行挖矿提供了大量的算力,之后定制化的ASIC设备进一步与普通计算机拉开了差距,于是挖矿的难度也随着算力的增长急剧攀升,到现在你想拿普通计算机挖矿是没啥指望了。
现在想靠挖矿赚钱基本只能购买矿机来作为挖矿设备,说起来定制的ASIC芯片刚出现时确实是引起了不小的恐慌,毕竟这玩意性能相较于普通机器太恐怖了,它的运算速度相比你的电脑快了近一百万倍,这很容易导致算力集中化,那样区块的出块权岂不是被一家掌握想怎么玩就怎么玩,这种情况可能也是中本聪设计比特币时所没有料到的,所幸之后矿机设备迅速普及并广泛分布在世界各地,算起来作为主要矿机生产商的比特大陆也是挺厉害的,这种模式应该说也进一步刺激了比特币价格的上扬
当然了,矿机如此普遍之后,你的策略如果还是自己挖矿去获取区块奖励,那么你想把本钱收回来可能都很困难,所以矿池也成了目前挖矿势力的主流,大家相当于在一个节点下挖矿,矿池按照贡献将区块奖励分发给大家,这样大家的收入就会较为稳定,也比自己单打独斗要强得多,这种由矿池垄断算力的情况有利也有弊,其中心化的性质饱受诟病,比特币在设计的时候可能也没预料到会出现这样的局面
此外现在加密货币市场也算是百花齐放,有些货币采用特殊的挖矿的加密算法以对抗ASIC设备,比如门罗币等,因为针对这种算法的ASIC设备较难设计而且速度提升也没这么大,所以购买这种设备的动力不足,还有一些则采用不同的共识算法如POS和DPOS等,这就不需要挖矿来产生区块了,这方面的内容有兴趣可以自行了解,下面进入正题
大家都去加入矿池去挖矿了,矿池肯定也要采取措施来保障自己的利益,对于一些不怀好意的矿工肯定也不能让他轻易地破坏矿池的运作是吧
首先我们来看看矿池是如何分发收益的,目前市场上存在很多的结算模式,我们介绍几种主流的方式
这是一种比较直接的奖励机制,它使用当前矿池发现的上一个区块到下一个区块被发现作为一个周期,统计在这之间每个矿工所提交的share,然后计算每个矿工所占的份额,即百分比,然后发放区块奖励
其实这样就很容易导致一种情况,随着一个周期时间的增长你在这个矿池所提交的share会变得越来越不值钱,因为什么时候能挖到块是不确定的,而如果在一个周期的一开始就挖到了块,哪怕你只提交了几个share也能获取比在之后提交几百个share更多的收益,看得出来这种模式并不健康
这种模式是早期比特币矿池采用的奖励机制,但是这种模式容易导致矿工采用一种跳池(Pool hopping)的策略来获取更多收益,这个我们后面再叙述,所以这种模式目前基本被弃用了
在这种模式下,矿池将按照矿工所提交的share即刻支付费用,矿池会根据你的算力在矿池的占比,并估算矿池的算力每天所能取得的收入来给你分配收益,一般每个sahre的费用是固定的,这样的话矿工每天所能取得的收入就比较稳定了,不过这样的话矿池就得承担一定的风险,所以就需要对矿工收取更高的手续费,这也算是稳定所需要付出的代价吧
PPLNS与PPS很类似,但是它取的是区块发现前提交的N个share来分发奖励,N是固定了,但是什么时候发现区块并不确定,所以总share大于N就得舍弃一部分,小于N又得重复计算一部分,这样的好处是避免了Proportional中share不断的贬值情况,于是也就能防范跳池的矿工
这种方法是在Proportional的基础上进行了改进,初衷是想对抗跳池的策略,它按矿工提交的share计算积分,而每个share所值的积分随着时间的增长而不断提高,这算是对于Proportional中时间较长的周期的最后一个share的奖励过低的一部分补偿,但是这种方法并没有完全消除Proportional的影响,发现的两个区块间隔较短的时候,每个share依然非常值钱,理论上来讲还是存在跳池的可能
这种方法是对Slush’s Method的进一步改进,它也是对share进行积分,越后面的share获得的积分也越多,但是积分的增长方式不同,这里是以指数级增长,所以随时间的推移每个share所取得的回报也呈现指数级的下降,这就遏制了前面提交的share的价值
当然了,具体的算法设计要更加精巧,最终计算得到的奖励的期望在采取跳池策略与否的情况下是相同的,所以可以完全避免跳池策略的攻击
除了这些方法还有很多的奖励分发模式,比如MPPS,SMPPS,ESMPPS等,这里就不一一介绍了,有兴趣的可以自行了解
有些矿工可能会想既然大家都是在一起计算挖矿,当我挖到块的时候我把它扣留下来不提交给矿池,而是自己将它广播出去,这样岂不是可以独吞区块奖励
需要指出的是虽然这个想法很危险,但是却没有可行性,因为我们挖矿的时候其实是在计算符合要求的区块头,在这个区块头中就包含了这个区块的区块奖励的收益地址,当这个区块被确认后获得区块奖励的只有区块头中的那个地址,当矿池把挖矿任务分发下来的时候已经写好了区块奖励的接收地址,所以哪怕你私自广播出去也是没有任何收益的,如果你在计算时篡改这一地址那就变成你的个人挖矿了,跟矿池就没有关系了,所以这条路目前是走不通的
之所以说目前走不通是因为这种由大矿池垄断算力的生态已经引发了许多人的担忧,有人就提出修改挖矿算法使得修改区块头中的收益地址变得可能,这样矿池手下的矿工可能都会选择私自广播区块,从而使得矿池瓦解,当然了,我感觉也只是想想,毕竟牵扯太多
发现独吞区块奖励不可行之后,又有些矿工会想既然最后分配收益的发时候是按照大家的计算量来分配,那么我不进行计算然后随便提交一个值过去是否也可以蒙混过关呢,这样伪造算力岂不是可以省一大笔钱
这个想法依然很危险,但是却也没什么可行性,在这里我们需要知道的是矿池分发任务时不是让你直接计算满足挖矿要求的区块hash,它们往往会设置一个较低难度的目标,比如符合要求的区块头的hash要满足前16位为0的话,矿池给你的任务可能只需要计算得到的hash满足前10位为0即可提交作为一个share,一般矿池那边也会做一个验证,因为这个任务的难度系数比较低,所以基本上可以保证你可以经常提交share,这也为后面对你的提交记录进行分析从而发现扣块攻击提供了帮助,具体的我们后面再谈
至于说这样低难度的任务如何满足计算符合要求的区块头的需要就是一个概率问题了,矿池设立这个目标就是为了保证大家都在进行运算并积极提交share,只要大家都在计算那么就有概率碰到一个满足要求的块,比如这次你完成任务提交的是一个hash前10位为0的块,下次挖到的可能是一个hash前12位为0的,一直挖下去总能碰到满足需求的区块头
托管矿池应该算是目前的主流,即一个矿池有一个中心服务器,对其下属的所有矿机进行协调与管理,同时这个服务器一般也会与一个或多个完全节点进行同步,这样就可以帮助下属的矿工完成对区块的验证,从而缓解矿机的压力,毕竟一个完整的区块副本还是很大的,这样矿工们也可以投入更多的算力获取更多的利润
因为托管矿池的管理员存在作弊的可能,尤其是那些大矿池,如果有那个意愿他们是可以控制区块的走向,所以后面又出现了p2p 矿池
如它的名字所示这种矿池没有中心服务器,取而代之的是一个名为份额链的类似于区块链的系统,矿工们在这条链上进行挖矿,这条链的难度远低于比特币,基本上30秒一个块,大家在这里计算并由该份额链统计share,当份额链有一个区块头的hash满足比特币的难度需求时,这个区块就算是挖矿成功的结果了,并将被广播出去,然后份额链将对区块奖励按照统计的share进行分发,其实就是使用一个区块链系统实现了一个中心服务器
不过这种矿池相比托管矿池要复杂的多,效率也相对比较低下,所以现在也在慢慢淡出市场,毕竟资本总是逐利的
下面我们就来看看矿池主要会面临哪些威胁
这个其实在前面我们已经提到过几次了,对于Proportional的奖励模式,如果有矿池的运气不太好很长时间都没有挖到区块,在这个矿池里的矿工的share就开始不断贬值,相当于算力越来越不值钱,这时候一些矿工就可以选择将其算力转到另一个刚挖到区块的矿池下去挖矿,因为这时候时间刚开始计算,每个share的价值比较高,相当于算力也比较值钱,如果一段时间没有挖到,他也可以选择再次跳池,一直去寻找share价值比较高的地方,至于前面所耗费的算力能值多少钱就不用太关心了
采用这种策略在统计学上来讲最终获得的收益肯定是要比你一直待在一个池里不动的收益要来得多的,不过随着现在矿池的收益分发策略的改变这种攻击策略已经不可行了
下面要说的就是区块截留攻击(Block withholding),其实它应该算是一种类型的挖矿策略,即挖到区块后是在手上保留一段时间还是直接丢弃,这种策略会有不同的人出于不同的目的来采用,只不过都不是什么好事,下面我们就来分析可能的各种情况
在这种情况下矿工或矿池挖到区块后并不会立刻将其广播出去,而是将其在手上留存一段时间
对于矿工而言,他可以将手上的算力均摊到各个矿池里,一旦他在某个矿池里挖到了区块,他就将区块给扣留下来,然后将手头的算力集中到这个矿池进行挖矿,累积share,然后提交区块以获取更多的利益,当然这样的话有可能别人在这段时间里也挖到了区块并将其公布,所以还是有一定的风险,但是最终从统计学的角度来看使用这种策略还是会提高收益
对于矿池而言情况则要复杂一些,矿池在获取到有效区块后他也可以选择保留区块,接下来他可以将手上的算力之间投入下一波的区块挖掘,一定程度上也算是抢得了先机,然后对于挖到的区块他将马上同步给手下的节点,并不广播给全节点
然后矿池可以对网络情况进行监控,一旦发现有新的区块头的出现,立刻让手上的节点广播己方的区块,使其他矿池失去该区块的奖励,其实这样的风险还是有点大,除非该矿池算力足够大,总能处于优势地位,而且也要考虑网络传播效率的影响,一般而言选择保留一段时间广播区块即可
矿池采用这种策略进行挖矿在短期会使自己的收入降低,但是这样也会打压其他池的收入,甚至损失更多,其他的诚实的矿工也可能会倒戈到自私挖矿的矿池里以获取更多收入,这样就会壮大自私池的算力,进一步加剧这种现象,并让自私池所持有的算力持续增加,甚至跨过50%的红线,这样的后果是非常严重的
不过因为多方面的原因目前这种攻击还是很少见,目前来看主要还是理论研究上多一点,在理想模型下一个最开始仅有33%算力的矿池逐步采取这种策略是可以逐步提升自己的算力水平到50%
下面我们来看看挖到区块后不直接丢弃它的情况,如你所见,这是一种破坏性的攻击,它也可以分为多种情况
0x1.矿工的恶意破坏
在这种情况下矿工在矿池内挖到区块后并不公布而是直接丢弃,但是share依然正常提交,这样的话相当于该矿工没有为矿池创造任何收益,但一直在参与其他诚实的矿工挖矿结果的分红,这种行为显然是损人不利己的,一般也没人会使用,这里仅仅作为一种可能性
0x2.一个攻击矿池
上面我们讨论的恶意的矿工是给自己打工的,这里我们要介绍的恶意矿工是给其他矿池打工的,这里为了简单我们假设有两个矿池A和B,其中A对B派遣恶意矿工进行攻击
这个模型还是比较简单,我们不妨设总算力为1,A池使用x算力渗透进B区块进行攻击,显然这x算力就属于躺着不干活的算力了,那么此时我们的总算力其实是1-x
然后我们分别设A与B拥有的算力为Ma和Mb,这样的话B出块的概率即为Pb = (Mb-x)/(1-x),于是A从B处拿到区块奖励
Pb * x/Mb
而A矿池自己诚实挖矿还可以拿到一部分区块奖励
(Ma-x)/(1-x)
所以A矿池获得的总收益即为
Q=Pbx/Mb + (Ma-x)/(1-x) = (Mb Ma - x^2)/(Mb(1-x))
这是在A矿池实施攻击后获取的收益,理论上讲A矿池通过选取适当的x进行攻击是可以使收益较未实施攻击前有所增加的,不过当时提出这个思路的时候选取的未实施攻击前的收益被简单表示为了Ma,也就是A矿池的算力,最近又看了一篇论文表示这种假设很不严谨,事实上随着攻击的进行系统的算力下降了,变成了1-x,在这种算力下整个系统额度出块速度也将下降,这意味着在进行攻击与否的两种不同情况下运行相同的时间挖到的块的数目是不同的,而比特币的难度调整周期是2016个区块,接近两周的时间,这是一个很长的跨度,时间差将带来很多损失,想要回本就得维持攻击到难度改变之后,然而想保持攻击这么长时间不被发现是一件很困难的事,在重新计算后发现单纯对B进行区块截留攻击是一个吃亏的行为,这也在某方面解释了这种攻击得到确认的报告还说非常少见,主要就是14年Eligius矿池确认过一次这种攻击,损失了300个比特币,这里的损失是指损失了被丢弃的本应得到的挖矿奖励,这可能是综合了其他的攻击手法亦或是就是一场报复性攻击
0x3.两个矿池互相攻击
这种情况就比较复杂了,可能是一个矿池发现自己被攻击后对攻击矿池进行的以其人之道还治其人之身的反击,也可能是两池本来就心怀不轨互相开撕
简单起见我们还是假设两个矿池A与B,它们都对对方进行了区块截留攻击,而这场战争一旦开始,除非双方同时收手,否则将很容易陷入囚徒困境当中,很有意思,下面我们要来讲讲博弈论了
囚徒困境我想大家应该都听说过,这里举一个简单的例子
现在警方逮捕了甲和乙两名嫌犯,他们是团伙作案,但因为没有充分的证据进行指控,于是将他们分开审讯
如果两人都认罪的话那么就各判五年,如果两人都不认罪那么将因证据不足而仅判半年,但是一旦出现其中一方认罪而另一方不认罪,则认罪的一方即刻释放而另一方将被判十年
这是一个非常经典的囚徒困境场景,在此处假设双方都是利己的,不关心对方死活,那么就要完全为自己的利益着想,那么假想你来做选择的话
1.对方不认罪,那么我认罪就可以直接释放,好的,选择背叛
2.对方认罪,那么如果我不认罪就要被判十年,不行,我也只能认罪,好的,还是选择背叛
如果双方都进行这样的思考,那么这场博弈最终的结果将是双方互相背叛,结果各判五年,也就是这场博弈所达到的纳什均衡,虽然团体的最优解应该是守口如瓶以获取各半年的刑期,这也正是困境之所在
同样的情况其实也出现在这里两个矿池的博弈中
两个矿池要选择攻击与否的策略,如果两个矿池都不攻击,则此时收益不受影响,如果一个矿池攻击另一个不攻击,则攻击矿池收益增加,受害矿池收益减少,两个矿池都攻击,则收益减少,但没有受害时减少的多,这时我们依然假设双方都是采用利己策略,按照上面的分析,在不知道对方选择的情况下,二者极有可能将选择相互攻击,从而陷入囚徒困境的纳什均衡
上面的博弈只是个简单的分析,这种两池间的互相攻击情况是较为复杂的,在二者算力不同与相同的情况下二者需要投入的算力的比例以及最终收益也是不同的,也就是说达到的纳什均衡的平衡点是不一样的,篇幅以及水平所限这里就不展开来说了,有意愿深究的可以自行去了解
而且在理论上这种攻击的困境是无法避免的,只有当双方中一方的算力在总算力中占比超过80%才能在这种博弈中取得收益,也就是可以避免攻击,当然,这种情况几乎是不会发生的
另外在这种攻击模式下其实还有一点需要注意,就是要防范间谍矿工的诞生,A矿池派出矿工渗透进B矿池,B矿池攻击A矿池的时候如果不进行检查有可能将A矿池派来的矿工又给派了回去,这样这些矿工就成了间谍,这样A矿池自然乐见其成,被B派来的A矿工将在A手下诚实的工作,提交区块,B矿池血亏,所以要进行防范矿池就需要有自己的亲兵,也就是验证过的忠诚的矿工,这对一般的矿池而言其实不是什么问题,它们手下都有大量的矿机,,用以出租或出售等,当然了,具体的规模一般人也无从得知
0x4.如何检测
这种攻击其实是很难检测的,目前而言常用的做法也只是针对矿工提交的share来计算其算力,与他实际发现的区块数进行对照查看是否存在问题,不过这种方法效果确实很有限,因为有可能对方确实就是运气不好,而且攻击方往往会对攻击的矿工进行拆分,使用许多账号来挖矿,这样对应的算力更加小了,不确定性因素更大,除非统计的周期足够长,否则很难发现攻击的具体来源,只能这样被动的挨打
0x5.如何防范
目前提出的较可能的区块截留攻击的解决方案是更改挖矿算法使得矿工无法验证得到的share是否是符合比特币要求的区块解,这样也就无法选择丢弃了,下面是一种可能的方式
每个Block额外添加三个字段——SecretSeed,ExtraHash和SecretHash
其中ExtraHash = hash(SecretSeed)
ExtraHash是block header的一部分,也将参与blockhash的运算
SecretHash = hash(BlockHash + SecretSeed)
之前一个有效的block需要满足BlockHash前32n位为0,现在还需要满足BlockHash前32位为0,同时满足SecretHash的前n位为0
因为矿工并不知道SecretSeed,所以无法计算SecretHash,也将无法验证区块是否满足要求,只能在找到满足要求的BlockHash后就提交share,由矿池来完成区块的验证
在上面的文章里我们探讨了一下针对矿池的攻击手法,还是挺有意思的,其实大多数的攻击都是针对托管矿池的,说起来貌似P2P矿池还是比较安全的,前提是P2P的节点要做好安全防范,不然被攻击者渗透进去修改了代码可能会导致下属的算力也被盗用,另外性能上的差距也是一大阻碍,还是有点可惜的
另外在区块截留攻击的背后其实还有很多内容可以去挖掘,文中只是谈了谈简单的攻击模型,有兴趣的同学完全可以继续深入
最后我想说除了write up外确实很少写这么长的文章,其中逻辑可能有表述不清的地方以及可能会有一些纰漏,希望大佬们多多指教,有问题欢迎与我联系
The Miner's Dilemma
Analysis of Bitcoin Pooled Mining Reward Systems
区块链中的自私挖掘研究与分析
关于比特币中 BWH 攻击的一个注记
POW共识算法中的博弈困境分析与优化