主页 > imtoken浏览器可以下载 > 北京大学《区块链技术与应用》系列课程学习笔记肖震老师[19]以太坊-难度调整
北京大学《区块链技术与应用》系列课程学习笔记肖震老师[19]以太坊-难度调整
目录
一、以太坊的难度调整原理
为了将区块生成时间保持在十分钟左右,比特币每2016个区块调整一次挖矿难度。 在以太坊中,可以对每个区块调整挖矿难度,调整方法相对复杂。 修改了几个版本,以太坊黄皮书和实际代码有一些出入。 这里遵循以代码为标准进行学习的原则。
1.难度调整公式
图1-1
这是难度调整的公式,其中H指的是当前区块,Hi是这个区块的序号,D(H)是这个区块当前的难度,那么难度调整公式有两部分,最大括号第一部分叫做基础部分,目的是让出块时间保持在十五秒左右,后面跟着的是第二部分,也叫难度炸弹,主要是过渡到权益证明,以太币Fang 希望逐步将共识机制从工作量证明转移到权益证明。
图 1-2
图 1-3
这部分难度炸弹的价值呈指数增长。 以太坊刚刚上线时,区块数量比较少以太坊出块时间,难度炸弹计算出来的值很小,基本可以忽略不计,所以难度调整主要由基础部分(系统中的区块生成时间)来决定。 随着区块数越来越大,难度炸弹的威力开始显现。 最初的设计思路是,当难度炸弹的威力开始发挥出来的时候,以太坊可以从工作量证明切换到权益证明(挖矿越来越难,大家都打算切换到权益证明). 但实际情况:基于权益证明的共识机制还有很多问题需要解决,远没有原先想象的那么顺利,所以切换到权益证明的时间再次推迟,再次。 没有其他方法可以达成共识。
还担心大家不想转,现在想转都转不过来了。 这种情况在 2017 年 4 月和 5 月开始变得明显,区块生成时间逐渐开始增加,从 15 秒增加到 30 秒左右。 , 如果不采取任何措施,它将继续增长。 当以太坊最终决定计算难度炸弹时,会将区块数回滚300万个区块,即真实区块数减去300万计算出一个假区块数,再计算难度炸弹。 为股权证明的上限争取一些时间。
图 1-4
难度炸弹的作用如图1-4所示。 可以看到在早期基本可以忽略不计,难度的调整基本都是根据系统中的出块时间来调整的。 在大约 370 万个区块时,难度炸弹的威力开始呈指数级上升。 在上面的峰值(也就是以太坊决定回调难度炸弹的时候),减少了三百万个区块。 再来看看难度炸弹的数值 刚刚掉下来,后面看起来是一条平直的直线,其实是在增长,只是因为峰顶太高,看不出来。
2. 以太坊发展的四个阶段
以太坊的发展分为四个阶段,Frontier、Homestead、Metropolis、Serenity。 大都会分为两个阶段,拜占庭和君士坦丁堡。 我们在拜占庭阶段,难度炸弹的回调是在拜占庭阶段进行的,如图2-1所示。 EIP(以太坊改进提案)、BIP(比特币改进提案)。
图2-1
以太坊系统在难度回调的同时将区块奖励从 5ETH 降低到 3ETH(如果不调整,对回调前的矿工不公平),必须维持系统受益的总供应量。 如果供应稳定以太坊出块时间,挖矿变得更容易,区块奖励应该相应减少。 在比特币中,区块奖励每隔一段时间就会减半。 这种做法在以太坊中不存在。 5ETH减为3ETH是一次性的,不代表以后会定期进行。
3.代码实现
1.拜占庭阶段挖矿难度调整代码
输入是父块的时间戳和父块的难度,计算出当前挖出的块的难度。代码中的BigTime是当前块的时间戳,bigParentTime是父块的时间戳
//calcDifficultyByzantium is the difficulty adjustment algorithm.It returns
//the difficulty that a new block should have when created at time given the
//parent block's time and difficulty.The calculation uses the Byzantium rules.
func calcDifficultyByzantium(time-uint64,parent *types.Header) *big.Int {
//https://github.com/ ethereum/EIPs/issues/100.
//algorithm:
//diff = (parent_diff +
// (parent_diff [ 2048*
// max((2 if len(parent.uncles) else 1) - ((timestamp -parent.timestamp)// 9),-99))
// ) + 2^(periodCount - 2)
bigTime := new(big.Int).Setuint64(time)
bigParentTime := new(big.Int).Set(parent.Time)
× := new(big.Int)
y := new(big.Int)
2.计算基础部分的难度调整
//(2 if len(parent_uncles) else 1) - (timestamp - parent_timestamp) //9
x.Sub(bigTime,bigParentTime)
x.Div(x,big9)
if parent.UncleHash == types.EmptyUncleHash {
x.Sub(big1,x)
} else {
x.Sub(big2,x)
}
//max((2-if-len(parent_uncles) else 1) - (timestamp - -parent_timestamp)//9, -99)
if x.cmp(bigMinus99) < 0 {
x.Set(bigMinus99)
}
//parent_diff + (parent_diff / 2848 *,
//max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp)// 9),-99))
y.Div(parent.Difficulty, params.DifficultyBoundDivisor)
x.Mul(y,x)
x.Add(parent.Difficulty, x)
//minimum difficulty can ever be (before exponential factor)
if x Cmp(params.MinimumDifficulty) < 0 {
x.Set(params.MinimumDifficulty)
}
注意:DifficultyBoundDivisor = big.NewInt(2048),minimumDifficulty = big.NewInt(131072)。
第一行是用父块的时间戳减去当前时间戳计算出块时间,然后第二行除以9向下取整。 判断是否有叔块,如果有则2减去前一个数x,没有则1减去前一个数x,然后与负数99比较,向下调整有一个限度,不能小于-99,接下来计算的是难度调整,父块的难度除以这个DifficultyBoundDivisor其实就是2048,再乘以之前计算的系数,加上父块的难度Go,基础部分的难度调整是有下限的,再小的难度也不能低于那个D0,MinimumDifficulty就是D0=131072。
3.难度炸弹的计算
//calculate a fake block number for the ice age delay:
// https : /lgithub.com/ ethereum/EIPs/pull/669
// fake_block_number = min(0,block.number - 3000000
fakeBlockNumber := new(big.Int)
if parent.Number.Cmp(big2999999) >= 0 {
fakeBlockNumber = fakeBlockNumber.Sub(parent.Number , big2999999)}
//for the exponential factor
periodCount := fakeBlockNumber
periodCount.Div(periodCount,expDiffPeriod)
//the exponential factor, commonly referred to as "the bomb"
//diff = diff + 2^(periodCount - 2)
if periodCount.Cmp(big1) > 0 {
y.Sub(periodCount,big2)
y.Exp( big2,y,nil)
x.Add(x,y)
}
注意:expDiffPeriod = big.NewInt(100000)。
四、以太坊实际统计 1、以太坊难度统计
从曲线的这一部分看,它看起来像一个指数形状。 顶峰的位置是以太坊决定回滚难度炸弹,回滚300万个区块,所以挖矿难度立马下降。 目前以太坊的挖矿难度基本区域稳定。
图 4-1
2.出块时间统计
不考虑个体波动,一般情况下,出块时间稳定在15s左右。 说明在以太坊早期,挖矿难度的调整主要是基于稳定出块时间,达到了预期的效果。 同样在2017年年中,出块时间明显增加,就是这个难度炸弹的效果。
图 4-2
3.两个街区
对于以太坊来说,最长合法链其实应该叫做最难合法链,也就是总难度最高的合法链。 每个区块的难度反映了挖出这个区块所需的工作量,总难度最高。 ,即挖出这条链上所有区块所需的总工作量是最大的。 一般来说,挖出后面的区块需要的工作量比较大。
图 4-3