consensus, core: EIP 100 polishes, fix chain maker diff
This PR polishes the EIP 100 difficulty adjustment algorithm to match the same mechanisms as the Homestead was implemented to keep the code uniform. It also avoids a few memory allocs by reusing big1 and big2, pulling it out of the common package and into ethash. The commit also fixes chain maker to forward the uncle hash when creating a simulated chain (it wasn't needed until now so we just skipped a copy there).
This commit is contained in:
parent
c4d28aee9b
commit
8c313eed26
@ -287,7 +287,7 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent *
|
|||||||
// given the parent block's time and difficulty.
|
// given the parent block's time and difficulty.
|
||||||
// TODO (karalabe): Move the chain maker into this package and make this private!
|
// TODO (karalabe): Move the chain maker into this package and make this private!
|
||||||
func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Header) *big.Int {
|
func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Header) *big.Int {
|
||||||
next := new(big.Int).Add(parent.Number, common.Big1)
|
next := new(big.Int).Add(parent.Number, big1)
|
||||||
switch {
|
switch {
|
||||||
case config.IsMetropolis(next):
|
case config.IsMetropolis(next):
|
||||||
return calcDifficultyMetropolis(time, parent)
|
return calcDifficultyMetropolis(time, parent)
|
||||||
@ -301,33 +301,44 @@ func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Heade
|
|||||||
// Some weird constants to avoid constant memory allocs for them.
|
// Some weird constants to avoid constant memory allocs for them.
|
||||||
var (
|
var (
|
||||||
expDiffPeriod = big.NewInt(100000)
|
expDiffPeriod = big.NewInt(100000)
|
||||||
|
big1 = big.NewInt(1)
|
||||||
|
big2 = big.NewInt(2)
|
||||||
big9 = big.NewInt(9)
|
big9 = big.NewInt(9)
|
||||||
big10 = big.NewInt(10)
|
big10 = big.NewInt(10)
|
||||||
bigMinus99 = big.NewInt(-99)
|
bigMinus99 = big.NewInt(-99)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// calcDifficultyMetropolis 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 Metropolis rules.
|
||||||
func calcDifficultyMetropolis(time uint64, parent *types.Header) *big.Int {
|
func calcDifficultyMetropolis(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)
|
bigTime := new(big.Int).SetUint64(time)
|
||||||
bigParentTime := new(big.Int).Set(parent.Time)
|
bigParentTime := new(big.Int).Set(parent.Time)
|
||||||
|
|
||||||
// adj_factor = max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)
|
// holds intermediate values to make the algo easier to read & audit
|
||||||
var x *big.Int
|
x := new(big.Int)
|
||||||
if parent.UncleHash == types.EmptyUncleHash {
|
y := new(big.Int)
|
||||||
x = big.NewInt(1)
|
|
||||||
} else {
|
|
||||||
x = big.NewInt(2)
|
|
||||||
}
|
|
||||||
z := new(big.Int).Sub(bigTime, bigParentTime)
|
|
||||||
z.Div(z, big9)
|
|
||||||
x.Sub(x, z)
|
|
||||||
|
|
||||||
// max(1 - (block_timestamp - parent_timestamp) // 10, -99)))
|
// (2 if len(parent_uncles) else 1) - (block_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) - (block_timestamp - parent_timestamp) // 9, -99)
|
||||||
if x.Cmp(bigMinus99) < 0 {
|
if x.Cmp(bigMinus99) < 0 {
|
||||||
x.Set(bigMinus99)
|
x.Set(bigMinus99)
|
||||||
}
|
}
|
||||||
|
|
||||||
// (parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99))
|
// (parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99))
|
||||||
y := new(big.Int).Div(parent.Difficulty, params.DifficultyBoundDivisor)
|
y.Div(parent.Difficulty, params.DifficultyBoundDivisor)
|
||||||
x.Mul(y, x)
|
x.Mul(y, x)
|
||||||
x.Add(parent.Difficulty, x)
|
x.Add(parent.Difficulty, x)
|
||||||
|
|
||||||
@ -335,19 +346,17 @@ func calcDifficultyMetropolis(time uint64, parent *types.Header) *big.Int {
|
|||||||
if x.Cmp(params.MinimumDifficulty) < 0 {
|
if x.Cmp(params.MinimumDifficulty) < 0 {
|
||||||
x.Set(params.MinimumDifficulty)
|
x.Set(params.MinimumDifficulty)
|
||||||
}
|
}
|
||||||
|
|
||||||
// for the exponential factor
|
// for the exponential factor
|
||||||
periodCount := new(big.Int).Add(parent.Number, common.Big1)
|
periodCount := new(big.Int).Add(parent.Number, big1)
|
||||||
periodCount.Div(periodCount, expDiffPeriod)
|
periodCount.Div(periodCount, expDiffPeriod)
|
||||||
|
|
||||||
// the exponential factor, commonly referred to as "the bomb"
|
// the exponential factor, commonly referred to as "the bomb"
|
||||||
// diff = diff + 2^(periodCount - 2)
|
// diff = diff + 2^(periodCount - 2)
|
||||||
if periodCount.Cmp(common.Big1) > 0 {
|
if periodCount.Cmp(big1) > 0 {
|
||||||
y.Sub(periodCount, common.Big2)
|
y.Sub(periodCount, big2)
|
||||||
y.Exp(common.Big2, y, nil)
|
y.Exp(big2, y, nil)
|
||||||
x.Add(x, y)
|
x.Add(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,12 +377,12 @@ func calcDifficultyHomestead(time uint64, parent *types.Header) *big.Int {
|
|||||||
x := new(big.Int)
|
x := new(big.Int)
|
||||||
y := new(big.Int)
|
y := new(big.Int)
|
||||||
|
|
||||||
// 1 - (block_timestamp -parent_timestamp) // 10
|
// 1 - (block_timestamp - parent_timestamp) // 10
|
||||||
x.Sub(bigTime, bigParentTime)
|
x.Sub(bigTime, bigParentTime)
|
||||||
x.Div(x, big10)
|
x.Div(x, big10)
|
||||||
x.Sub(common.Big1, x)
|
x.Sub(big1, x)
|
||||||
|
|
||||||
// max(1 - (block_timestamp - parent_timestamp) // 10, -99)))
|
// max(1 - (block_timestamp - parent_timestamp) // 10, -99)
|
||||||
if x.Cmp(bigMinus99) < 0 {
|
if x.Cmp(bigMinus99) < 0 {
|
||||||
x.Set(bigMinus99)
|
x.Set(bigMinus99)
|
||||||
}
|
}
|
||||||
@ -387,14 +396,14 @@ func calcDifficultyHomestead(time uint64, parent *types.Header) *big.Int {
|
|||||||
x.Set(params.MinimumDifficulty)
|
x.Set(params.MinimumDifficulty)
|
||||||
}
|
}
|
||||||
// for the exponential factor
|
// for the exponential factor
|
||||||
periodCount := new(big.Int).Add(parent.Number, common.Big1)
|
periodCount := new(big.Int).Add(parent.Number, big1)
|
||||||
periodCount.Div(periodCount, expDiffPeriod)
|
periodCount.Div(periodCount, expDiffPeriod)
|
||||||
|
|
||||||
// the exponential factor, commonly referred to as "the bomb"
|
// the exponential factor, commonly referred to as "the bomb"
|
||||||
// diff = diff + 2^(periodCount - 2)
|
// diff = diff + 2^(periodCount - 2)
|
||||||
if periodCount.Cmp(common.Big1) > 0 {
|
if periodCount.Cmp(big1) > 0 {
|
||||||
y.Sub(periodCount, common.Big2)
|
y.Sub(periodCount, big2)
|
||||||
y.Exp(common.Big2, y, nil)
|
y.Exp(big2, y, nil)
|
||||||
x.Add(x, y)
|
x.Add(x, y)
|
||||||
}
|
}
|
||||||
return x
|
return x
|
||||||
@ -421,12 +430,12 @@ func calcDifficultyFrontier(time uint64, parent *types.Header) *big.Int {
|
|||||||
diff.Set(params.MinimumDifficulty)
|
diff.Set(params.MinimumDifficulty)
|
||||||
}
|
}
|
||||||
|
|
||||||
periodCount := new(big.Int).Add(parent.Number, common.Big1)
|
periodCount := new(big.Int).Add(parent.Number, big1)
|
||||||
periodCount.Div(periodCount, expDiffPeriod)
|
periodCount.Div(periodCount, expDiffPeriod)
|
||||||
if periodCount.Cmp(common.Big1) > 0 {
|
if periodCount.Cmp(big1) > 0 {
|
||||||
// diff = diff + 2^(periodCount - 2)
|
// diff = diff + 2^(periodCount - 2)
|
||||||
expDiff := periodCount.Sub(periodCount, common.Big2)
|
expDiff := periodCount.Sub(periodCount, big2)
|
||||||
expDiff.Exp(common.Big2, expDiff, nil)
|
expDiff.Exp(big2, expDiff, nil)
|
||||||
diff.Add(diff, expDiff)
|
diff.Add(diff, expDiff)
|
||||||
diff = math.BigMax(diff, params.MinimumDifficulty)
|
diff = math.BigMax(diff, params.MinimumDifficulty)
|
||||||
}
|
}
|
||||||
|
@ -218,6 +218,7 @@ func makeHeader(config *params.ChainConfig, parent *types.Block, state *state.St
|
|||||||
Number: parent.Number(),
|
Number: parent.Number(),
|
||||||
Time: new(big.Int).Sub(time, big.NewInt(10)),
|
Time: new(big.Int).Sub(time, big.NewInt(10)),
|
||||||
Difficulty: parent.Difficulty(),
|
Difficulty: parent.Difficulty(),
|
||||||
|
UncleHash: parent.UncleHash(),
|
||||||
}),
|
}),
|
||||||
GasLimit: CalcGasLimit(parent),
|
GasLimit: CalcGasLimit(parent),
|
||||||
GasUsed: new(big.Int),
|
GasUsed: new(big.Int),
|
||||||
|
Loading…
Reference in New Issue
Block a user