github.com/cryptotooltop/go-ethereum@v0.0.0-20231103184714-151d1922f3e5/consensus/ethash/difficulty.go (about) 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/holiman/uint256" 23 24 "github.com/scroll-tech/go-ethereum/core/types" 25 ) 26 27 const ( 28 // frontierDurationLimit is for Frontier: 29 // The decision boundary on the blocktime duration used to determine 30 // whether difficulty should go up or down. 31 frontierDurationLimit = 13 32 // minimumDifficulty The minimum that the difficulty may ever be. 33 minimumDifficulty = 131072 34 // expDiffPeriod is the exponential difficulty period 35 expDiffPeriodUint = 100000 36 // difficultyBoundDivisorBitShift is the bound divisor of the difficulty (2048), 37 // This constant is the right-shifts to use for the division. 38 difficultyBoundDivisor = 11 39 ) 40 41 // CalcDifficultyFrontierU256 is the difficulty adjustment algorithm. It returns the 42 // difficulty that a new block should have when created at time given the parent 43 // block's time and difficulty. The calculation uses the Frontier rules. 44 func CalcDifficultyFrontierU256(time uint64, parent *types.Header) *big.Int { 45 /* 46 Algorithm 47 block_diff = pdiff + pdiff / 2048 * (1 if time - ptime < 13 else -1) + int(2^((num // 100000) - 2)) 48 49 Where: 50 - pdiff = parent.difficulty 51 - ptime = parent.time 52 - time = block.timestamp 53 - num = block.number 54 */ 55 56 pDiff, _ := uint256.FromBig(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.FromBig(parent.Difficulty) // pDiff: pdiff 100 adjust := pDiff.Clone() 101 adjust.Rsh(adjust, difficultyBoundDivisor) // adjust: pDiff / 2048 102 103 x := (time - parent.Time) / 10 // (time - ptime) / 10) 104 var neg = true 105 if x == 0 { 106 x = 1 107 neg = false 108 } else if x >= 100 { 109 x = 99 110 } else { 111 x = x - 1 112 } 113 z := new(uint256.Int).SetUint64(x) 114 adjust.Mul(adjust, z) // adjust: (pdiff / 2048) * max((time - ptime) / 10 - 1, 99) 115 if neg { 116 pDiff.Sub(pDiff, adjust) // pdiff - pdiff / 2048 * max((time - ptime) / 10 - 1, 99) 117 } else { 118 pDiff.Add(pDiff, adjust) // pdiff + pdiff / 2048 * max((time - ptime) / 10 - 1, 99) 119 } 120 if pDiff.LtUint64(minimumDifficulty) { 121 pDiff.SetUint64(minimumDifficulty) 122 } 123 // for the exponential factor, a.k.a "the bomb" 124 // diff = diff + 2^(periodCount - 2) 125 if periodCount := (1 + parent.Number.Uint64()) / expDiffPeriodUint; periodCount > 1 { 126 expFactor := adjust.Lsh(adjust.SetOne(), uint(periodCount-2)) 127 pDiff.Add(pDiff, expFactor) 128 } 129 return pDiff.ToBig() 130 } 131 132 // MakeDifficultyCalculatorU256 creates a difficultyCalculator with the given bomb-delay. 133 // the difficulty is calculated with Byzantium rules, which differs from Homestead in 134 // how uncles affect the calculation 135 func MakeDifficultyCalculatorU256(bombDelay *big.Int) func(time uint64, parent *types.Header) *big.Int { 136 // Note, the calculations below looks at the parent number, which is 1 below 137 // the block number. Thus we remove one from the delay given 138 bombDelayFromParent := bombDelay.Uint64() - 1 139 return func(time uint64, parent *types.Header) *big.Int { 140 /* 141 https://github.com/ethereum/EIPs/issues/100 142 pDiff = parent.difficulty 143 BLOCK_DIFF_FACTOR = 9 144 a = pDiff + (pDiff // BLOCK_DIFF_FACTOR) * adj_factor 145 b = min(parent.difficulty, MIN_DIFF) 146 child_diff = max(a,b ) 147 */ 148 x := (time - parent.Time) / 9 // (block_timestamp - parent_timestamp) // 9 149 c := uint64(1) // if parent.unclehash == emptyUncleHashHash 150 if parent.UncleHash != types.EmptyUncleHash { 151 c = 2 152 } 153 xNeg := x >= c 154 if xNeg { 155 // x is now _negative_ adjustment factor 156 x = x - c // - ( (t-p)/p -( 2 or 1) ) 157 } else { 158 x = c - x // (2 or 1) - (t-p)/9 159 } 160 if x > 99 { 161 x = 99 // max(x, 99) 162 } 163 // parent_diff + (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)) 164 y := new(uint256.Int) 165 y.SetFromBig(parent.Difficulty) // y: p_diff 166 pDiff := y.Clone() // pdiff: p_diff 167 z := new(uint256.Int).SetUint64(x) //z : +-adj_factor (either pos or negative) 168 y.Rsh(y, difficultyBoundDivisor) // y: p__diff / 2048 169 z.Mul(y, z) // z: (p_diff / 2048 ) * (+- adj_factor) 170 171 if xNeg { 172 y.Sub(pDiff, z) // y: parent_diff + parent_diff/2048 * adjustment_factor 173 } else { 174 y.Add(pDiff, z) // y: parent_diff + parent_diff/2048 * adjustment_factor 175 } 176 // minimum difficulty can ever be (before exponential factor) 177 if y.LtUint64(minimumDifficulty) { 178 y.SetUint64(minimumDifficulty) 179 } 180 // calculate a fake block number for the ice-age delay 181 // Specification: https://eips.ethereum.org/EIPS/eip-1234 182 var pNum = parent.Number.Uint64() 183 if pNum >= bombDelayFromParent { 184 if fakeBlockNumber := pNum - bombDelayFromParent; fakeBlockNumber >= 2*expDiffPeriodUint { 185 z.SetOne() 186 z.Lsh(z, uint(fakeBlockNumber/expDiffPeriodUint-2)) 187 y.Add(z, y) 188 } 189 } 190 return y.ToBig() 191 } 192 }