github.com/phillinzzz/newBsc@v1.1.6/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/phillinzzz/newBsc/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  }