|  | 
|  | 1 | +// Copyright 2020 The go-ethereum Authors | 
|  | 2 | +// This file is part of the go-ethereum library. | 
|  | 3 | +// | 
|  | 4 | +// The go-ethereum library is free software: you can redistribute it and/or modify | 
|  | 5 | +// it under the terms of the GNU Lesser General Public License as published by | 
|  | 6 | +// the Free Software Foundation, either version 3 of the License, or | 
|  | 7 | +// (at your option) any later version. | 
|  | 8 | +// | 
|  | 9 | +// The go-ethereum library is distributed in the hope that it will be useful, | 
|  | 10 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 11 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
|  | 12 | +// GNU Lesser General Public License for more details. | 
|  | 13 | +// | 
|  | 14 | +// You should have received a copy of the GNU Lesser General Public License | 
|  | 15 | +// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
|  | 16 | + | 
|  | 17 | +package ethash | 
|  | 18 | + | 
|  | 19 | +import ( | 
|  | 20 | +	"math/big" | 
|  | 21 | + | 
|  | 22 | +	"github.com/ethereum/go-ethereum/core/types" | 
|  | 23 | +	"github.com/holiman/uint256" | 
|  | 24 | +) | 
|  | 25 | + | 
|  | 26 | +const ( | 
|  | 27 | +	// frontierDurationLimit is for Frontier: | 
|  | 28 | +	// The decision boundary on the blocktime duration used to determine | 
|  | 29 | +	// whether difficulty should go up or down. | 
|  | 30 | +	frontierDurationLimit = 13 | 
|  | 31 | +	// minimumDifficulty The minimum that the difficulty may ever be. | 
|  | 32 | +	minimumDifficulty = 131072 | 
|  | 33 | +	// expDiffPeriod is the exponential difficulty period | 
|  | 34 | +	expDiffPeriodUint = 100000 | 
|  | 35 | +	// difficultyBoundDivisorBitShift is the bound divisor of the difficulty (2048), | 
|  | 36 | +	// This constant is the right-shifts to use for the division. | 
|  | 37 | +	difficultyBoundDivisor = 11 | 
|  | 38 | +) | 
|  | 39 | + | 
|  | 40 | +// CalcDifficultyFrontierU256 is the difficulty adjustment algorithm. It returns the | 
|  | 41 | +// difficulty that a new block should have when created at time given the parent | 
|  | 42 | +// block's time and difficulty. The calculation uses the Frontier rules. | 
|  | 43 | +func CalcDifficultyFrontierU256(time uint64, parent *types.Header) *big.Int { | 
|  | 44 | +	/* | 
|  | 45 | +		Algorithm | 
|  | 46 | +		block_diff = pdiff + pdiff / 2048 * (1 if time - ptime < 13 else -1) + int(2^((num // 100000) - 2)) | 
|  | 47 | +
 | 
|  | 48 | +		Where: | 
|  | 49 | +		- pdiff  = parent.difficulty | 
|  | 50 | +		- ptime = parent.time | 
|  | 51 | +		- time = block.timestamp | 
|  | 52 | +		- num = block.number | 
|  | 53 | +	*/ | 
|  | 54 | + | 
|  | 55 | +	pDiff := uint256.NewInt() | 
|  | 56 | +	pDiff.SetFromBig(parent.Difficulty) // pDiff: pdiff | 
|  | 57 | +	adjust := pDiff.Clone() | 
|  | 58 | +	adjust.Rsh(adjust, difficultyBoundDivisor) // adjust: pDiff / 2048 | 
|  | 59 | + | 
|  | 60 | +	if time-parent.Time < frontierDurationLimit { | 
|  | 61 | +		pDiff.Add(pDiff, adjust) | 
|  | 62 | +	} else { | 
|  | 63 | +		pDiff.Sub(pDiff, adjust) | 
|  | 64 | +	} | 
|  | 65 | +	if pDiff.LtUint64(minimumDifficulty) { | 
|  | 66 | +		pDiff.SetUint64(minimumDifficulty) | 
|  | 67 | +	} | 
|  | 68 | +	// 'pdiff' now contains: | 
|  | 69 | +	// pdiff + pdiff / 2048 * (1 if time - ptime < 13 else -1) | 
|  | 70 | + | 
|  | 71 | +	if periodCount := (parent.Number.Uint64() + 1) / expDiffPeriodUint; periodCount > 1 { | 
|  | 72 | +		// diff = diff + 2^(periodCount - 2) | 
|  | 73 | +		expDiff := adjust.SetOne() | 
|  | 74 | +		expDiff.Lsh(expDiff, uint(periodCount-2)) // expdiff: 2 ^ (periodCount -2) | 
|  | 75 | +		pDiff.Add(pDiff, expDiff) | 
|  | 76 | +	} | 
|  | 77 | +	return pDiff.ToBig() | 
|  | 78 | +} | 
|  | 79 | + | 
|  | 80 | +// CalcDifficultyHomesteadU256 is the difficulty adjustment algorithm. It returns | 
|  | 81 | +// the difficulty that a new block should have when created at time given the | 
|  | 82 | +// parent block's time and difficulty. The calculation uses the Homestead rules. | 
|  | 83 | +func CalcDifficultyHomesteadU256(time uint64, parent *types.Header) *big.Int { | 
|  | 84 | +	/* | 
|  | 85 | +		https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md | 
|  | 86 | +		Algorithm: | 
|  | 87 | +		block_diff = pdiff + pdiff / 2048 * max(1 - (time - ptime) / 10, -99) + 2 ^ int((num / 100000) - 2)) | 
|  | 88 | +
 | 
|  | 89 | +		Our modification, to use unsigned ints: | 
|  | 90 | +		block_diff = pdiff - pdiff / 2048 * max((time - ptime) / 10 - 1, 99) + 2 ^ int((num / 100000) - 2)) | 
|  | 91 | +
 | 
|  | 92 | +		Where: | 
|  | 93 | +		- pdiff  = parent.difficulty | 
|  | 94 | +		- ptime = parent.time | 
|  | 95 | +		- time = block.timestamp | 
|  | 96 | +		- num = block.number | 
|  | 97 | +	*/ | 
|  | 98 | + | 
|  | 99 | +	pDiff := uint256.NewInt() | 
|  | 100 | +	pDiff.SetFromBig(parent.Difficulty) // pDiff: pdiff | 
|  | 101 | +	adjust := pDiff.Clone() | 
|  | 102 | +	adjust.Rsh(adjust, difficultyBoundDivisor) // adjust: pDiff / 2048 | 
|  | 103 | + | 
|  | 104 | +	x := (time - parent.Time) / 10 // (time - ptime) / 10) | 
|  | 105 | +	var neg = true | 
|  | 106 | +	if x == 0 { | 
|  | 107 | +		x = 1 | 
|  | 108 | +		neg = false | 
|  | 109 | +	} else if x >= 100 { | 
|  | 110 | +		x = 99 | 
|  | 111 | +	} else { | 
|  | 112 | +		x = x - 1 | 
|  | 113 | +	} | 
|  | 114 | +	z := new(uint256.Int).SetUint64(x) | 
|  | 115 | +	adjust.Mul(adjust, z) // adjust: (pdiff / 2048) * max((time - ptime) / 10 - 1, 99) | 
|  | 116 | +	if neg { | 
|  | 117 | +		pDiff.Sub(pDiff, adjust) // pdiff - pdiff / 2048 * max((time - ptime) / 10 - 1, 99) | 
|  | 118 | +	} else { | 
|  | 119 | +		pDiff.Add(pDiff, adjust) // pdiff + pdiff / 2048 * max((time - ptime) / 10 - 1, 99) | 
|  | 120 | +	} | 
|  | 121 | +	if pDiff.LtUint64(minimumDifficulty) { | 
|  | 122 | +		pDiff.SetUint64(minimumDifficulty) | 
|  | 123 | +	} | 
|  | 124 | +	// for the exponential factor, a.k.a "the bomb" | 
|  | 125 | +	// diff = diff + 2^(periodCount - 2) | 
|  | 126 | +	if periodCount := (1 + parent.Number.Uint64()) / expDiffPeriodUint; periodCount > 1 { | 
|  | 127 | +		expFactor := adjust.Lsh(adjust.SetOne(), uint(periodCount-2)) | 
|  | 128 | +		pDiff.Add(pDiff, expFactor) | 
|  | 129 | +	} | 
|  | 130 | +	return pDiff.ToBig() | 
|  | 131 | +} | 
|  | 132 | + | 
|  | 133 | +// MakeDifficultyCalculatorU256 creates a difficultyCalculator with the given bomb-delay. | 
|  | 134 | +// the difficulty is calculated with Byzantium rules, which differs from Homestead in | 
|  | 135 | +// how uncles affect the calculation | 
|  | 136 | +func MakeDifficultyCalculatorU256(bombDelay *big.Int) func(time uint64, parent *types.Header) *big.Int { | 
|  | 137 | +	// Note, the calculations below looks at the parent number, which is 1 below | 
|  | 138 | +	// the block number. Thus we remove one from the delay given | 
|  | 139 | +	bombDelayFromParent := bombDelay.Uint64() - 1 | 
|  | 140 | +	return func(time uint64, parent *types.Header) *big.Int { | 
|  | 141 | +		/* | 
|  | 142 | +			https://github.com/ethereum/EIPs/issues/100 | 
|  | 143 | +			pDiff = parent.difficulty | 
|  | 144 | +			BLOCK_DIFF_FACTOR = 9 | 
|  | 145 | +			a = pDiff + (pDiff // BLOCK_DIFF_FACTOR) * adj_factor | 
|  | 146 | +			b = min(parent.difficulty, MIN_DIFF) | 
|  | 147 | +			child_diff = max(a,b ) | 
|  | 148 | +		*/ | 
|  | 149 | +		x := (time - parent.Time) / 9 // (block_timestamp - parent_timestamp) // 9 | 
|  | 150 | +		c := uint64(1)                // if parent.unclehash == emptyUncleHashHash | 
|  | 151 | +		if parent.UncleHash != types.EmptyUncleHash { | 
|  | 152 | +			c = 2 | 
|  | 153 | +		} | 
|  | 154 | +		xNeg := x >= c | 
|  | 155 | +		if xNeg { | 
|  | 156 | +			// x is now _negative_ adjustment factor | 
|  | 157 | +			x = x - c // - ( (t-p)/p -( 2 or 1) ) | 
|  | 158 | +		} else { | 
|  | 159 | +			x = c - x // (2 or 1) - (t-p)/9 | 
|  | 160 | +		} | 
|  | 161 | +		if x > 99 { | 
|  | 162 | +			x = 99 // max(x, 99) | 
|  | 163 | +		} | 
|  | 164 | +		// parent_diff + (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)) | 
|  | 165 | +		y := new(uint256.Int) | 
|  | 166 | +		y.SetFromBig(parent.Difficulty)    // y: p_diff | 
|  | 167 | +		pDiff := y.Clone()                 // pdiff: p_diff | 
|  | 168 | +		z := new(uint256.Int).SetUint64(x) //z : +-adj_factor (either pos or negative) | 
|  | 169 | +		y.Rsh(y, difficultyBoundDivisor)   // y: p__diff / 2048 | 
|  | 170 | +		z.Mul(y, z)                        // z: (p_diff / 2048 ) * (+- adj_factor) | 
|  | 171 | + | 
|  | 172 | +		if xNeg { | 
|  | 173 | +			y.Sub(pDiff, z) // y: parent_diff + parent_diff/2048 * adjustment_factor | 
|  | 174 | +		} else { | 
|  | 175 | +			y.Add(pDiff, z) // y: parent_diff + parent_diff/2048 * adjustment_factor | 
|  | 176 | +		} | 
|  | 177 | +		// minimum difficulty can ever be (before exponential factor) | 
|  | 178 | +		if y.LtUint64(minimumDifficulty) { | 
|  | 179 | +			y.SetUint64(minimumDifficulty) | 
|  | 180 | +		} | 
|  | 181 | +		// calculate a fake block number for the ice-age delay | 
|  | 182 | +		// Specification: https://eips.ethereum.org/EIPS/eip-1234 | 
|  | 183 | +		var pNum = parent.Number.Uint64() | 
|  | 184 | +		if pNum >= bombDelayFromParent { | 
|  | 185 | +			if fakeBlockNumber := pNum - bombDelayFromParent; fakeBlockNumber >= 2*expDiffPeriodUint { | 
|  | 186 | +				z.SetOne() | 
|  | 187 | +				z.Lsh(z, uint(fakeBlockNumber/expDiffPeriodUint-2)) | 
|  | 188 | +				y.Add(z, y) | 
|  | 189 | +			} | 
|  | 190 | +		} | 
|  | 191 | +		return y.ToBig() | 
|  | 192 | +	} | 
|  | 193 | +} | 
0 commit comments