gitlab.com/aquachain/aquachain@v1.17.16-rc3.0.20221018032414-e3ddf1e1c055/consensus/aquahash/eth_difficulty.go (about) 1 // Copyright 2018 The aquachain Authors 2 // This file is part of the aquachain library. 3 // 4 // The aquachain 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 aquachain 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 aquachain library. If not, see <http://www.gnu.org/licenses/>. 16 17 package aquahash 18 19 import ( 20 "math/big" 21 22 "gitlab.com/aquachain/aquachain/common/math" 23 "gitlab.com/aquachain/aquachain/core/types" 24 "gitlab.com/aquachain/aquachain/params" 25 ) 26 27 // Ethash proof-of-work protocol constants. 28 var ( 29 EthFrontierBlockReward = big.NewInt(5e+18) // Block reward in wei for successfully mining a block 30 EthByzantiumBlockReward = big.NewInt(3e+18) // Block reward in wei for successfully mining a block upward from Byzantium 31 big9 = big.NewInt(9) 32 big2999999 = big.NewInt(2999999) 33 ) 34 35 // CalcDifficulty is the difficulty adjustment algorithm. It returns 36 // the difficulty that a new block should have when created at time 37 // given the parent block's time and difficulty. 38 func EthCalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Header) *big.Int { 39 next := new(big.Int).Add(parent.Number, big1) 40 switch { 41 case config.IsByzantium(next): 42 return ethcalcDifficultyByzantium(time, parent) 43 case config.IsHomestead(next): 44 return ethcalcDifficultyHomestead(time, parent) 45 default: 46 return ethcalcDifficultyFrontier(time, parent) 47 } 48 } 49 50 // calcDifficultyByzantium is the difficulty adjustment algorithm. It returns 51 // the difficulty that a new block should have when created at time given the 52 // parent block's time and difficulty. The calculation uses the Byzantium rules. 53 func ethcalcDifficultyByzantium(time uint64, parent *types.Header) *big.Int { 54 // https://github.com/ethereum/EIPs/issues/100. 55 // algorithm: 56 // diff = (parent_diff + 57 // (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)) 58 // ) + 2^(periodCount - 2) 59 60 bigTime := new(big.Int).SetUint64(time) 61 bigParentTime := new(big.Int).Set(parent.Time) 62 63 // holds intermediate values to make the algo easier to read & audit 64 x := new(big.Int) 65 y := new(big.Int) 66 67 // (2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // 9 68 x.Sub(bigTime, bigParentTime) 69 x.Div(x, big9) 70 if parent.UncleHash == types.EmptyUncleHash { 71 x.Sub(big1, x) 72 } else { 73 x.Sub(big2, x) 74 } 75 // max((2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // 9, -99) 76 if x.Cmp(bigMinus99) < 0 { 77 x.Set(bigMinus99) 78 } 79 // parent_diff + (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)) 80 y.Div(parent.Difficulty, params.DifficultyBoundDivisor) 81 x.Mul(y, x) 82 x.Add(parent.Difficulty, x) 83 84 // minimum difficulty can ever be (before exponential factor) 85 if x.Cmp(params.MinimumDifficultyEth) < 0 { 86 x.Set(params.MinimumDifficultyEth) 87 } 88 // calculate a fake block number for the ice-age delay: 89 // https://github.com/ethereum/EIPs/pull/669 90 // fake_block_number = max(0, block.number - 3_000_000) 91 fakeBlockNumber := new(big.Int) 92 if parent.Number.Cmp(big2999999) >= 0 { 93 fakeBlockNumber = fakeBlockNumber.Sub(parent.Number, big2999999) // Note, parent is 1 less than the actual block number 94 } 95 // for the exponential factor 96 periodCount := fakeBlockNumber 97 periodCount.Div(periodCount, expDiffPeriod) 98 99 // the exponential factor, commonly referred to as "the bomb" 100 // diff = diff + 2^(periodCount - 2) 101 if periodCount.Cmp(big1) > 0 { 102 y.Sub(periodCount, big2) 103 y.Exp(big2, y, nil) 104 x.Add(x, y) 105 } 106 return x 107 } 108 109 // calcDifficultyHomestead is the difficulty adjustment algorithm. It returns 110 // the difficulty that a new block should have when created at time given the 111 // parent block's time and difficulty. The calculation uses the Homestead rules. 112 func ethcalcDifficultyHomestead(time uint64, parent *types.Header) *big.Int { 113 // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md 114 // algorithm: 115 // diff = (parent_diff + 116 // (parent_diff / 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99)) 117 // ) + 2^(periodCount - 2) 118 119 bigTime := new(big.Int).SetUint64(time) 120 bigParentTime := new(big.Int).Set(parent.Time) 121 122 // holds intermediate values to make the algo easier to read & audit 123 x := new(big.Int) 124 y := new(big.Int) 125 126 // 1 - (block_timestamp - parent_timestamp) // 10 127 x.Sub(bigTime, bigParentTime) 128 x.Div(x, big10) 129 x.Sub(big1, x) 130 131 // max(1 - (block_timestamp - parent_timestamp) // 10, -99) 132 if x.Cmp(bigMinus99) < 0 { 133 x.Set(bigMinus99) 134 } 135 // (parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99)) 136 y.Div(parent.Difficulty, params.DifficultyBoundDivisor) 137 x.Mul(y, x) 138 x.Add(parent.Difficulty, x) 139 140 // minimum difficulty can ever be (before exponential factor) 141 if x.Cmp(params.MinimumDifficultyEth) < 0 { 142 x.Set(params.MinimumDifficultyEth) 143 } 144 // for the exponential factor 145 periodCount := new(big.Int).Add(parent.Number, big1) 146 periodCount.Div(periodCount, expDiffPeriod) 147 148 // the exponential factor, commonly referred to as "the bomb" 149 // diff = diff + 2^(periodCount - 2) 150 if periodCount.Cmp(big1) > 0 { 151 y.Sub(periodCount, big2) 152 y.Exp(big2, y, nil) 153 x.Add(x, y) 154 } 155 return x 156 } 157 158 var ethnetDurationLimit = big.NewInt(13) 159 160 // calcDifficultyFrontier is the difficulty adjustment algorithm. It returns the 161 // difficulty that a new block should have when created at time given the parent 162 // block's time and difficulty. The calculation uses the Frontier rules. 163 func ethcalcDifficultyFrontier(time uint64, parent *types.Header) *big.Int { 164 diff := new(big.Int) 165 adjust := new(big.Int).Div(parent.Difficulty, params.DifficultyBoundDivisor) 166 bigTime := new(big.Int) 167 bigParentTime := new(big.Int) 168 169 bigTime.SetUint64(time) 170 bigParentTime.Set(parent.Time) 171 172 if bigTime.Sub(bigTime, bigParentTime).Cmp(ethnetDurationLimit) < 0 { 173 diff.Add(parent.Difficulty, adjust) 174 } else { 175 diff.Sub(parent.Difficulty, adjust) 176 } 177 if diff.Cmp(params.MinimumDifficultyEth) < 0 { 178 diff.Set(params.MinimumDifficultyEth) 179 } 180 181 periodCount := new(big.Int).Add(parent.Number, big1) 182 periodCount.Div(periodCount, expDiffPeriod) 183 if periodCount.Cmp(big1) > 0 { 184 // diff = diff + 2^(periodCount - 2) 185 expDiff := periodCount.Sub(periodCount, big2) 186 expDiff.Exp(big2, expDiff, nil) 187 diff.Add(diff, expDiff) 188 diff = math.BigMax(diff, params.MinimumDifficultyEth) 189 } 190 return diff 191 } 192 193 // AccumulateRewards credits the coinbase of the given block with the mining 194 // reward. The total reward consists of the static block reward and rewards for 195 // included uncles. The coinbase of each uncle block is also rewarded. 196 func ethReward(config *params.ChainConfig, header *types.Header) *big.Int { 197 // Select the correct block reward based on chain progression 198 blockReward := EthFrontierBlockReward 199 if config.IsByzantium(header.Number) { 200 blockReward = EthByzantiumBlockReward 201 } 202 return blockReward 203 }