为什么要调整挖矿难度?
为了维持出块时间为一个固定值
如果不调会有什么问题?
出块时间会越来越短
出块时间太短会有什么问题么?
系统的总算力越来越强,挖矿难度保持不变的话, 出块时间就会越来越短, 出块时间太短会导致过多的分叉。
两个节点同时挖到矿,会出现分叉,时间越短, 这种分叉就会成为常态,分叉过多 对于系统达成共识就越困难, 系统中的总算力越强,就越安全。 分叉越多 总算力就会被分散开, 因为每个节点根据网络分布不同,选择不同的分叉进行挖矿, 那么恶意节点就不需要 51%的算力就可以发动攻击了。 为了防止恶意攻击,就需要避免过多的分叉。就需要维持出块时间为一个固定范围。
比特币的挖矿算法
H(Block Header) <= target
SHA-256
Bitcoin 挖矿难度调节
比特币网络规定每 2016个区块更新一次挖矿难度。 这个大概多长时间呢?
(2016 * 10) / (24 * 60) = 14天 也就是 两个星期左右。
调整公式
target = target * (actual time / expect time)
expect time 就是期望的时间: 2016 * 10
actual time 系统中产生的的最近的2016个区块的实际时间
如果 actual time 比两个星期大, 后面的值就是一个大于1的一个数, target 就变大了,难度相当于减小了。
如果 actual time 比两个星期小, 后面的值就是一个小于1的一个数, target 就变小了, 难度相当于增加了。
实际的代码中调节是有界限的, 不论是增大还是减小都不会超过4倍。
例如 实际的时间 比8个星期还要长,那么就按照8个星期来计算, 这样增大为原来的4倍。
实际的时间 比半个星期还要短, 也就是不到半个星期 2016 区块就挖完了, 目标阈值就会取 半个星期。减少原来的 1/4。
在区块头中有个 nBits 域 4个字节,是 Target 经过编码得到的,诚实的矿工会检测这个nBits 来保证所有的矿工都按照调整后的难度来进行挖矿。
以太坊挖矿难度调整
调节总公式
区块难度D(H)调整的公式
参数说明:
D(H)本区块难度
P(H)Hd 父区块难度, 每个区块的难度都是父区块都难度基础之上进行调节
x * ϛ 用于自适应调节出块难度, 维持稳定的出块速度
ε 难度炸弹
基础部分为下界 D0 131072
自适应难度调整
x 是调整单位, ϛ 调整的系数
y 和父区块的uncle数有关,如果父区块包含了uncle 那么 y = 2 否则 y = 1
Hs 是本区块的时间戳, P(H)Hs 是父区块的时间戳,都是以秒为单位,并规定 Hs > P(H)Hs
父区块中包含了uncle时,难度会大一个单位,是因为包含了uncle时,新发行的货币量会变大,
这个时候就需要适当的提高挖矿难度以保持货币发行量的稳定。
调节的上界是 -99, 这个主要是为了防止黑客攻击或者一些其他不确定的情况。
我们仔细的看下这个公式, y无论取1 还是 2, 公式都是一个常数减去后面的值, 如果 y 比后面的值大, 减出来就是一个正数,说明难度要上调。 反之是下调。
这部分是稳定出块速度的最重要部分, 出块时间过短调大难度,出块时间过长调小难度。
我们举个例子
以父区块不带uncle为例:
出块时间在 1-8 秒之间,出块时间过短, 难度调大一个单位。
出块时间在 9-17秒之间, 出块时间可以接受, 保持不变。
出块时间在 18 -26秒之间,出块时间过长, 难度调小一个单位。
比26秒更长,就会下调更多的单位。
难度炸弹
为什么设置难度炸弹?
设置难度炸弹的原因是要降低迁移到Pos协议时,发生fork的风险,到时挖矿难度非常大,所以矿工有意愿迁移到Pos协议。
ε 是2的指数函数,每十万个区块扩大一倍,后期增长非常快,这就是难度炸弹的由来。
Hi‘ 有真正的block number 减去 3000000 得到,这样做的原因是低估来Pos协议开发的难度, 需要延长大概一年半的时间
15 * 3000000 / (24 * 3600) / 365 = 1.42年
EIP100: 也是在这个时间 以太坊的reward从 5ETH 降到了 3ETH