github.com/DxChainNetwork/dxc@v0.8.1-0.20220824085222-1162e304b6e7/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/DxChainNetwork/dxc/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.FromBig(parent.Difficulty) // pDiff: pdiff 56 adjust := pDiff.Clone() 57 adjust.Rsh(adjust, difficultyBoundDivisor) // adjust: pDiff / 2048 58 59 if time-parent.Time < frontierDurationLimit { 60 pDiff.Add(pDiff, adjust) 61 } else { 62 pDiff.Sub(pDiff, adjust) 63 } 64 if pDiff.LtUint64(minimumDifficulty) { 65 pDiff.SetUint64(minimumDifficulty) 66 } 67 // 'pdiff' now contains: 68 // pdiff + pdiff / 2048 * (1 if time - ptime < 13 else -1) 69 70 if periodCount := (parent.Number.Uint64() + 1) / expDiffPeriodUint; periodCount > 1 { 71 // diff = diff + 2^(periodCount - 2) 72 expDiff := adjust.SetOne() 73 expDiff.Lsh(expDiff, uint(periodCount-2)) // expdiff: 2 ^ (periodCount -2) 74 pDiff.Add(pDiff, expDiff) 75 } 76 return pDiff.ToBig() 77 } 78 79 // CalcDifficultyHomesteadU256 is the difficulty adjustment algorithm. It returns 80 // the difficulty that a new block should have when created at time given the 81 // parent block's time and difficulty. The calculation uses the Homestead rules. 82 func CalcDifficultyHomesteadU256(time uint64, parent *types.Header) *big.Int { 83 /* 84 https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md 85 Algorithm: 86 block_diff = pdiff + pdiff / 2048 * max(1 - (time - ptime) / 10, -99) + 2 ^ int((num / 100000) - 2)) 87 88 Our modification, to use unsigned ints: 89 block_diff = pdiff - pdiff / 2048 * max((time - ptime) / 10 - 1, 99) + 2 ^ int((num / 100000) - 2)) 90 91 Where: 92 - pdiff = parent.difficulty 93 - ptime = parent.time 94 - time = block.timestamp 95 - num = block.number 96 */ 97 98 pDiff, _ := uint256.FromBig(parent.Difficulty) // pDiff: pdiff 99 adjust := pDiff.Clone() 100 adjust.Rsh(adjust, difficultyBoundDivisor) // adjust: pDiff / 2048 101 102 x := (time - parent.Time) / 10 // (time - ptime) / 10) 103 var neg = true 104 if x == 0 { 105 x = 1 106 neg = false 107 } else if x >= 100 { 108 x = 99 109 } else { 110 x = x - 1 111 } 112 z := new(uint256.Int).SetUint64(x) 113 adjust.Mul(adjust, z) // adjust: (pdiff / 2048) * max((time - ptime) / 10 - 1, 99) 114 if neg { 115 pDiff.Sub(pDiff, adjust) // pdiff - pdiff / 2048 * max((time - ptime) / 10 - 1, 99) 116 } else { 117 pDiff.Add(pDiff, adjust) // pdiff + pdiff / 2048 * max((time - ptime) / 10 - 1, 99) 118 } 119 if pDiff.LtUint64(minimumDifficulty) { 120 pDiff.SetUint64(minimumDifficulty) 121 } 122 // for the exponential factor, a.k.a "the bomb" 123 // diff = diff + 2^(periodCount - 2) 124 if periodCount := (1 + parent.Number.Uint64()) / expDiffPeriodUint; periodCount > 1 { 125 expFactor := adjust.Lsh(adjust.SetOne(), uint(periodCount-2)) 126 pDiff.Add(pDiff, expFactor) 127 } 128 return pDiff.ToBig() 129 } 130 131 // MakeDifficultyCalculatorU256 creates a difficultyCalculator with the given bomb-delay. 132 // the difficulty is calculated with Byzantium rules, which differs from Homestead in 133 // how uncles affect the calculation 134 func MakeDifficultyCalculatorU256(bombDelay *big.Int) func(time uint64, parent *types.Header) *big.Int { 135 // Note, the calculations below looks at the parent number, which is 1 below 136 // the block number. Thus we remove one from the delay given 137 bombDelayFromParent := bombDelay.Uint64() - 1 138 return func(time uint64, parent *types.Header) *big.Int { 139 /* 140 https://github.com/ethereum/EIPs/issues/100 141 pDiff = parent.difficulty 142 BLOCK_DIFF_FACTOR = 9 143 a = pDiff + (pDiff // BLOCK_DIFF_FACTOR) * adj_factor 144 b = min(parent.difficulty, MIN_DIFF) 145 child_diff = max(a,b ) 146 */ 147 x := (time - parent.Time) / 9 // (block_timestamp - parent_timestamp) // 9 148 c := uint64(1) // if parent.unclehash == emptyUncleHashHash 149 if parent.UncleHash != types.EmptyUncleHash { 150 c = 2 151 } 152 xNeg := x >= c 153 if xNeg { 154 // x is now _negative_ adjustment factor 155 x = x - c // - ( (t-p)/p -( 2 or 1) ) 156 } else { 157 x = c - x // (2 or 1) - (t-p)/9 158 } 159 if x > 99 { 160 x = 99 // max(x, 99) 161 } 162 // parent_diff + (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)) 163 y := new(uint256.Int) 164 y.SetFromBig(parent.Difficulty) // y: p_diff 165 pDiff := y.Clone() // pdiff: p_diff 166 z := new(uint256.Int).SetUint64(x) //z : +-adj_factor (either pos or negative) 167 y.Rsh(y, difficultyBoundDivisor) // y: p__diff / 2048 168 z.Mul(y, z) // z: (p_diff / 2048 ) * (+- adj_factor) 169 170 if xNeg { 171 y.Sub(pDiff, z) // y: parent_diff + parent_diff/2048 * adjustment_factor 172 } else { 173 y.Add(pDiff, z) // y: parent_diff + parent_diff/2048 * adjustment_factor 174 } 175 // minimum difficulty can ever be (before exponential factor) 176 if y.LtUint64(minimumDifficulty) { 177 y.SetUint64(minimumDifficulty) 178 } 179 // calculate a fake block number for the ice-age delay 180 // Specification: https://eips.ethereum.org/EIPS/eip-1234 181 var pNum = parent.Number.Uint64() 182 if pNum >= bombDelayFromParent { 183 if fakeBlockNumber := pNum - bombDelayFromParent; fakeBlockNumber >= 2*expDiffPeriodUint { 184 z.SetOne() 185 z.Lsh(z, uint(fakeBlockNumber/expDiffPeriodUint-2)) 186 y.Add(z, y) 187 } 188 } 189 return y.ToBig() 190 } 191 }