什么是调整挖矿难度?
挖矿就是不断尝试nonce,使整个block header中的哈希值小于等于给定的目标阈值 target。H(block header) <= target。
target越小,挖矿难度越大。调整挖矿难度,就是调整目标空间在整个输出空间中所占的比例。比特币中的hash算法是SHA-256,整个输出空间是2^256个可能取值。通俗的说,调整目标空间占整个输出空间的比例,就是哈希值前面要多少个0,但不是完全准确。
挖矿难度 difficulty与目标阈值 target成反比。difficulty = difficulty_1_target(挖矿难度位1时所对应的阈值) / target(当前的目标阈值)。difficulty最小就是1,此时的target是非常大的数。
为什么调整挖矿难度?
系统总算力越来越强,如果难度不变,出块时间将会越来越短。一个区块传播给大多数节点所需要的时间大约是几十秒,如果出块时间缩短,如几秒钟一个,那么会很容易出现分叉。分叉过多,系统不易达成共识,威胁系统安全性。
假设大部分算力掌握在诚实的人手里。系统中总算力越强,安全性越好,因为要发动51%攻击所需要的算力也就越大。但是如果出现过多分叉,系统中的总算力就会被分散,恶意节点集中算力扩展自己的分叉,很快就可以成为最长链,此时可能不再需要51%算力才能发动攻击,攻击成本大大降低。
如何调整挖矿难度?
每2016个区块调一下阈值 target。(2016*10min)/(60min*24h)= 14天。也就是每14天调整一下阈值 target。
target = target *(actual time / expected time)
difficulty = difficulty *(expected time / actual time)
其中actual time就是指的系统中产生的最近的2016个区块实际花费的时间 time spent mining the last 2016 blocks。expected time就是指的2016*10min,也就是14天。
如果最近2016个区块产生的时间超过14天,说明平均每一个区块的出块时间超过10min,这时候挖矿难度应该降低。如果实际时间小于14天,说明出块太快,这时候应该提高挖矿难度。实际代码中,上调或下调都有4倍的限制。比如实际时间非常长,超过8周,那么算的时候也按照8周来算,最多增大4倍。相反如果实际时间很短,不到半周,那么算的时候按照半周来算,最小也是1/4。
如何让所有矿工同时调整目标阈值?
计算target的方法是写在比特币系统的代码中,每挖到2016个区块,会自动进行调整,代码开源。如果有的恶意节点故意不调,那么发布的区块,诚实矿工不会认同。block header中不直接存储target,因为它是256位的,nBits域在header中只有4位,可以认为是target的压缩编码。如果有恶意矿工不调难度,那么在检查区块合法性(nBits域)就不会通过。
系统实际情况举例:(截止到18年,图片来源于视频)
这张图显示的是09-18年比特币系统中总算力的情况。没有流行之前很长一段时间没有明显增长,后面几年增长较快,呈现指数级的增长。但是即使在这段期间,算力也不是单调递增,中间有波动,但是总体是增长很快的。
这个是09-18年挖矿难度的变化情况。与算力增长几乎同步,通过调整挖矿难度,使得出块时间保持稳定。
这个图显示的是10-18年每天的出块时间。总的来说出块时间稳定在10分钟上下震动,说明难度调整达到了预期目的。