difficulty.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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. package ethash
  17. import (
  18. "math/big"
  19. "github.com/ethereum/go-ethereum/core/types"
  20. "github.com/holiman/uint256"
  21. )
  22. const (
  23. // frontierDurationLimit is for Frontier:
  24. // The decision boundary on the blocktime duration used to determine
  25. // whether difficulty should go up or down.
  26. frontierDurationLimit = 13
  27. // minimumDifficulty The minimum that the difficulty may ever be.
  28. minimumDifficulty = 131072
  29. // expDiffPeriod is the exponential difficulty period
  30. expDiffPeriodUint = 100000
  31. // difficultyBoundDivisorBitShift is the bound divisor of the difficulty (2048),
  32. // This constant is the right-shifts to use for the division.
  33. difficultyBoundDivisor = 11
  34. )
  35. // CalcDifficultyFrontierU256 is the difficulty adjustment algorithm. It returns the
  36. // difficulty that a new block should have when created at time given the parent
  37. // block's time and difficulty. The calculation uses the Frontier rules.
  38. func CalcDifficultyFrontierU256(time uint64, parent *types.Header) *big.Int {
  39. /*
  40. Algorithm
  41. block_diff = pdiff + pdiff / 2048 * (1 if time - ptime < 13 else -1) + int(2^((num // 100000) - 2))
  42. Where:
  43. - pdiff = parent.difficulty
  44. - ptime = parent.time
  45. - time = block.timestamp
  46. - num = block.number
  47. */
  48. pDiff := uint256.NewInt()
  49. pDiff.SetFromBig(parent.Difficulty) // pDiff: pdiff
  50. adjust := pDiff.Clone()
  51. adjust.Rsh(adjust, difficultyBoundDivisor) // adjust: pDiff / 2048
  52. if time-parent.Time < frontierDurationLimit {
  53. pDiff.Add(pDiff, adjust)
  54. } else {
  55. pDiff.Sub(pDiff, adjust)
  56. }
  57. if pDiff.LtUint64(minimumDifficulty) {
  58. pDiff.SetUint64(minimumDifficulty)
  59. }
  60. // 'pdiff' now contains:
  61. // pdiff + pdiff / 2048 * (1 if time - ptime < 13 else -1)
  62. if periodCount := (parent.Number.Uint64() + 1) / expDiffPeriodUint; periodCount > 1 {
  63. // diff = diff + 2^(periodCount - 2)
  64. expDiff := adjust.SetOne()
  65. expDiff.Lsh(expDiff, uint(periodCount-2)) // expdiff: 2 ^ (periodCount -2)
  66. pDiff.Add(pDiff, expDiff)
  67. }
  68. return pDiff.ToBig()
  69. }
  70. // CalcDifficultyHomesteadU256 is the difficulty adjustment algorithm. It returns
  71. // the difficulty that a new block should have when created at time given the
  72. // parent block's time and difficulty. The calculation uses the Homestead rules.
  73. func CalcDifficultyHomesteadU256(time uint64, parent *types.Header) *big.Int {
  74. /*
  75. https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md
  76. Algorithm:
  77. block_diff = pdiff + pdiff / 2048 * max(1 - (time - ptime) / 10, -99) + 2 ^ int((num / 100000) - 2))
  78. Our modification, to use unsigned ints:
  79. block_diff = pdiff - pdiff / 2048 * max((time - ptime) / 10 - 1, 99) + 2 ^ int((num / 100000) - 2))
  80. Where:
  81. - pdiff = parent.difficulty
  82. - ptime = parent.time
  83. - time = block.timestamp
  84. - num = block.number
  85. */
  86. pDiff := uint256.NewInt()
  87. pDiff.SetFromBig(parent.Difficulty) // pDiff: pdiff
  88. adjust := pDiff.Clone()
  89. adjust.Rsh(adjust, difficultyBoundDivisor) // adjust: pDiff / 2048
  90. x := (time - parent.Time) / 10 // (time - ptime) / 10)
  91. var neg = true
  92. if x == 0 {
  93. x = 1
  94. neg = false
  95. } else if x >= 100 {
  96. x = 99
  97. } else {
  98. x = x - 1
  99. }
  100. z := new(uint256.Int).SetUint64(x)
  101. adjust.Mul(adjust, z) // adjust: (pdiff / 2048) * max((time - ptime) / 10 - 1, 99)
  102. if neg {
  103. pDiff.Sub(pDiff, adjust) // pdiff - pdiff / 2048 * max((time - ptime) / 10 - 1, 99)
  104. } else {
  105. pDiff.Add(pDiff, adjust) // pdiff + pdiff / 2048 * max((time - ptime) / 10 - 1, 99)
  106. }
  107. if pDiff.LtUint64(minimumDifficulty) {
  108. pDiff.SetUint64(minimumDifficulty)
  109. }
  110. // for the exponential factor, a.k.a "the bomb"
  111. // diff = diff + 2^(periodCount - 2)
  112. if periodCount := (1 + parent.Number.Uint64()) / expDiffPeriodUint; periodCount > 1 {
  113. expFactor := adjust.Lsh(adjust.SetOne(), uint(periodCount-2))
  114. pDiff.Add(pDiff, expFactor)
  115. }
  116. return pDiff.ToBig()
  117. }
  118. // MakeDifficultyCalculatorU256 creates a difficultyCalculator with the given bomb-delay.
  119. // the difficulty is calculated with Byzantium rules, which differs from Homestead in
  120. // how uncles affect the calculation
  121. func MakeDifficultyCalculatorU256(bombDelay *big.Int) func(time uint64, parent *types.Header) *big.Int {
  122. // Note, the calculations below looks at the parent number, which is 1 below
  123. // the block number. Thus we remove one from the delay given
  124. bombDelayFromParent := bombDelay.Uint64() - 1
  125. return func(time uint64, parent *types.Header) *big.Int {
  126. /*
  127. https://github.com/ethereum/EIPs/issues/100
  128. pDiff = parent.difficulty
  129. BLOCK_DIFF_FACTOR = 9
  130. a = pDiff + (pDiff // BLOCK_DIFF_FACTOR) * adj_factor
  131. b = min(parent.difficulty, MIN_DIFF)
  132. child_diff = max(a,b )
  133. */
  134. x := (time - parent.Time) / 9 // (block_timestamp - parent_timestamp) // 9
  135. c := uint64(1) // if parent.unclehash == emptyUncleHashHash
  136. if parent.UncleHash != types.EmptyUncleHash {
  137. c = 2
  138. }
  139. xNeg := x >= c
  140. if xNeg {
  141. // x is now _negative_ adjustment factor
  142. x = x - c // - ( (t-p)/p -( 2 or 1) )
  143. } else {
  144. x = c - x // (2 or 1) - (t-p)/9
  145. }
  146. if x > 99 {
  147. x = 99 // max(x, 99)
  148. }
  149. // parent_diff + (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99))
  150. y := new(uint256.Int)
  151. y.SetFromBig(parent.Difficulty) // y: p_diff
  152. pDiff := y.Clone() // pdiff: p_diff
  153. z := new(uint256.Int).SetUint64(x) //z : +-adj_factor (either pos or negative)
  154. y.Rsh(y, difficultyBoundDivisor) // y: p__diff / 2048
  155. z.Mul(y, z) // z: (p_diff / 2048 ) * (+- adj_factor)
  156. if xNeg {
  157. y.Sub(pDiff, z) // y: parent_diff + parent_diff/2048 * adjustment_factor
  158. } else {
  159. y.Add(pDiff, z) // y: parent_diff + parent_diff/2048 * adjustment_factor
  160. }
  161. // minimum difficulty can ever be (before exponential factor)
  162. if y.LtUint64(minimumDifficulty) {
  163. y.SetUint64(minimumDifficulty)
  164. }
  165. // calculate a fake block number for the ice-age delay
  166. // Specification: https://eips.ethereum.org/EIPS/eip-1234
  167. var pNum = parent.Number.Uint64()
  168. if pNum >= bombDelayFromParent {
  169. if fakeBlockNumber := pNum - bombDelayFromParent; fakeBlockNumber >= 2*expDiffPeriodUint {
  170. z.SetOne()
  171. z.Lsh(z, uint(fakeBlockNumber/expDiffPeriodUint-2))
  172. y.Add(z, y)
  173. }
  174. }
  175. return y.ToBig()
  176. }
  177. }