@@ -20,169 +20,55 @@ import (
2020 "math/big"
2121
2222 "github.com/microstack-tech/parallax/core/types"
23- "github.com/holiman/uint256 "
23+ "github.com/microstack-tech/parallax/params "
2424)
2525
2626const (
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
27+ // Target block spacing in seconds
28+ BlockTargetSpacingSeconds = uint64 (600 )
3829)
3930
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 )
31+ // CalcNakamotoDifficulty computes the next difficulty using Bitcoin’s rule:
32+ //
33+ // - Keep difficulty constant within each retarget interval
34+ // - On boundary: new = old * targetTimespan / actualTimespan
35+ // - Clamp actualTimespan into [minTimespan, maxTimespan]
36+ // - Ensure result >= 1
37+ func CalcNakamotoDifficulty (config * params.ChainConfig , parent * types.Header ) * big.Int {
38+ nextHeight := new (big.Int ).Add (parent .Number , big1 ).Uint64 ()
39+ var r uint64
40+
41+ if config .Ethash == nil {
42+ // If no ethash config is given, fall back to Parallax's original difficulty
43+ // adjustment scheme (which is basically Bitcoin's with a 10-minute target).
44+ r = 2016
6145 } else {
62- pDiff . Sub ( pDiff , adjust )
46+ r = config . Ethash . RetargetIntervalBlocks
6347 }
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)
6948
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 )
49+ if r == 0 || (nextHeight % r ) != 0 {
50+ return new (big.Int ).Set (parent .Difficulty )
7551 }
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))
9052
91- Where:
92- - pdiff = parent.difficulty
93- - ptime = parent.time
94- - time = block.timestamp
95- - num = block.number
96- */
53+ target := BlockTargetSpacingSeconds * r
54+ minT := target / 4
55+ maxT := target * 4
9756
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- 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)
57+ actual := parent .Time - parent .EpochStartTime
58+ if actual < minT {
59+ actual = minT
60+ } else if actual > maxT {
61+ actual = maxT
11862 }
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- }
13063
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- xNeg := x >= c
150- if xNeg {
151- // x is now _negative_ adjustment factor
152- x = x - c // - ( (t-p)/p -( 2 or 1) )
153- } else {
154- x = c - x // (2 or 1) - (t-p)/9
155- }
156- if x > 99 {
157- x = 99 // max(x, 99)
158- }
159- // parent_diff + (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99))
160- y := new (uint256.Int )
161- y .SetFromBig (parent .Difficulty ) // y: p_diff
162- pDiff := y .Clone () // pdiff: p_diff
163- z := new (uint256.Int ).SetUint64 (x ) // z : +-adj_factor (either pos or negative)
164- y .Rsh (y , difficultyBoundDivisor ) // y: p__diff / 2048
165- z .Mul (y , z ) // z: (p_diff / 2048 ) * (+- adj_factor)
64+ old := new (big.Int ).Set (parent .Difficulty )
65+ num := new (big.Int ).Mul (old , new (big.Int ).SetUint64 (target ))
66+ den := new (big.Int ).SetUint64 (actual )
67+ out := num .Div (num , den )
16668
167- if xNeg {
168- y .Sub (pDiff , z ) // y: parent_diff + parent_diff/2048 * adjustment_factor
169- } else {
170- y .Add (pDiff , z ) // y: parent_diff + parent_diff/2048 * adjustment_factor
171- }
172- // minimum difficulty can ever be (before exponential factor)
173- if y .LtUint64 (minimumDifficulty ) {
174- y .SetUint64 (minimumDifficulty )
175- }
176- // calculate a fake block number for the ice-age delay
177- // Specification: https://eips.ethereum.org/EIPS/eip-1234
178- pNum := parent .Number .Uint64 ()
179- if pNum >= bombDelayFromParent {
180- if fakeBlockNumber := pNum - bombDelayFromParent ; fakeBlockNumber >= 2 * expDiffPeriodUint {
181- z .SetOne ()
182- z .Lsh (z , uint (fakeBlockNumber / expDiffPeriodUint - 2 ))
183- y .Add (z , y )
184- }
185- }
186- return y .ToBig ()
69+ if out .Sign () <= 0 {
70+ out .SetUint64 (1 )
18771 }
72+
73+ return out
18874}
0 commit comments