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  }