diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index fa2d740e45..01d97a470e 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -287,7 +287,7 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent * // given the parent block's time and difficulty. // 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 { - next := new(big.Int).Add(parent.Number, common.Big1) + next := new(big.Int).Add(parent.Number, big1) switch { case config.IsMetropolis(next): 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. var ( expDiffPeriod = big.NewInt(100000) + big1 = big.NewInt(1) + big2 = big.NewInt(2) big9 = big.NewInt(9) big10 = big.NewInt(10) 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 { + // 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) - // adj_factor = max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99) - var x *big.Int + // holds intermediate values to make the algo easier to read & audit + x := new(big.Int) + y := new(big.Int) + + // (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 = big.NewInt(1) + x.Sub(big1, x) } else { - x = big.NewInt(2) + x.Sub(big2, x) } - z := new(big.Int).Sub(bigTime, bigParentTime) - z.Div(z, big9) - x.Sub(x, z) - - // max(1 - (block_timestamp - parent_timestamp) // 10, -99))) + // max((2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // 9, -99) if x.Cmp(bigMinus99) < 0 { x.Set(bigMinus99) } - // (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.Add(parent.Difficulty, x) @@ -335,19 +346,17 @@ func calcDifficultyMetropolis(time uint64, parent *types.Header) *big.Int { if x.Cmp(params.MinimumDifficulty) < 0 { x.Set(params.MinimumDifficulty) } - // 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) // the exponential factor, commonly referred to as "the bomb" // diff = diff + 2^(periodCount - 2) - if periodCount.Cmp(common.Big1) > 0 { - y.Sub(periodCount, common.Big2) - y.Exp(common.Big2, y, nil) + if periodCount.Cmp(big1) > 0 { + y.Sub(periodCount, big2) + y.Exp(big2, y, nil) x.Add(x, y) } - return x } @@ -368,12 +377,12 @@ func calcDifficultyHomestead(time uint64, parent *types.Header) *big.Int { x := new(big.Int) y := new(big.Int) - // 1 - (block_timestamp -parent_timestamp) // 10 + // 1 - (block_timestamp - parent_timestamp) // 10 x.Sub(bigTime, bigParentTime) 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 { x.Set(bigMinus99) } @@ -387,14 +396,14 @@ func calcDifficultyHomestead(time uint64, parent *types.Header) *big.Int { x.Set(params.MinimumDifficulty) } // 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) // the exponential factor, commonly referred to as "the bomb" // diff = diff + 2^(periodCount - 2) - if periodCount.Cmp(common.Big1) > 0 { - y.Sub(periodCount, common.Big2) - y.Exp(common.Big2, y, nil) + if periodCount.Cmp(big1) > 0 { + y.Sub(periodCount, big2) + y.Exp(big2, y, nil) x.Add(x, y) } return x @@ -421,12 +430,12 @@ func calcDifficultyFrontier(time uint64, parent *types.Header) *big.Int { 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) - if periodCount.Cmp(common.Big1) > 0 { + if periodCount.Cmp(big1) > 0 { // diff = diff + 2^(periodCount - 2) - expDiff := periodCount.Sub(periodCount, common.Big2) - expDiff.Exp(common.Big2, expDiff, nil) + expDiff := periodCount.Sub(periodCount, big2) + expDiff.Exp(big2, expDiff, nil) diff.Add(diff, expDiff) diff = math.BigMax(diff, params.MinimumDifficulty) } diff --git a/core/chain_makers.go b/core/chain_makers.go index 38a69d42a9..976a8114d3 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -218,6 +218,7 @@ func makeHeader(config *params.ChainConfig, parent *types.Block, state *state.St Number: parent.Number(), Time: new(big.Int).Sub(time, big.NewInt(10)), Difficulty: parent.Difficulty(), + UncleHash: parent.UncleHash(), }), GasLimit: CalcGasLimit(parent), GasUsed: new(big.Int),