Skip to content

Commit 69a6d2a

Browse files
committed
upd diff adjustment from 45
1 parent 6045f50 commit 69a6d2a

File tree

1 file changed

+102
-41
lines changed

1 file changed

+102
-41
lines changed

client/consensus/ethash/difficulty.go

Lines changed: 102 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,17 @@ import (
2020
)
2121

2222
const (
23-
// Minimum difficulty level
24-
minimumDifficulty = 1000000
25-
// More aggressive difficulty adjustment for blocks before 45,000.
26-
// Note: from block 45,000 onward the divisor is set to 11.
27-
difficultyBoundDivisor = 512
23+
// Custom difficulty parameters (used for blocks before hardfork)
24+
minimumDifficulty = 1000000
25+
difficultyBoundDivisor = 512
26+
// R5 difficulty parameters (used for blocks >= hardfork)
27+
r5MinimumDifficulty = 1000000
28+
r5DifficultyBoundDivisor = 11
29+
// Hardfork block number
30+
hardForkBlock = 45000
31+
// Block time target (in seconds) for both calculations;
32+
// note: for R5 (post-hardfork) this replaces original target.
33+
targetBlockTime = 7
2834
)
2935

3036
func roundRat(r *big.Rat) *big.Int {
@@ -37,23 +43,32 @@ func roundRat(r *big.Rat) *big.Int {
3743
return quotient
3844
}
3945

46+
// CalcDifficultyFrontierU256 calculates the block difficulty using the Frontier rules.
47+
// For blocks with parent.Number >= hardForkBlock the calculation uses the R5 new formula
4048
func CalcDifficultyFrontierU256(time uint64, parent *types.Header) *big.Int {
41-
// Enforce the 3-second gap rule starting from block 45,000.
42-
if parent.Number.Uint64() >= 45000 && (time - parent.Time) < 3 {
43-
panic("block rejected: parent's time gap is less than 3 seconds")
44-
}
45-
46-
// Determine the divisor based on block number.
47-
divisor := difficultyBoundDivisor
48-
if parent.Number.Uint64() >= 45000 {
49-
divisor = 11
49+
// If past the hardfork block, use R5 difficulty calculation.
50+
if parent.Number.Uint64() >= hardForkBlock {
51+
pDiff, _ := uint256.FromBig(parent.Difficulty)
52+
adjust := pDiff.Clone()
53+
adjust.Rsh(adjust, r5DifficultyBoundDivisor)
54+
// With a 7-second target, add difficulty if block time is less than 7 sec.
55+
if time-parent.Time < targetBlockTime {
56+
pDiff.Add(pDiff, adjust)
57+
} else {
58+
pDiff.Sub(pDiff, adjust)
59+
}
60+
if pDiff.LtUint64(r5MinimumDifficulty) {
61+
pDiff.SetUint64(r5MinimumDifficulty)
62+
}
63+
return pDiff.ToBig()
5064
}
5165

66+
// Custom (pre-hardfork) calculation.
5267
pDiff, _ := uint256.FromBig(parent.Difficulty)
5368
adjust := pDiff.Clone()
54-
adjust.Rsh(adjust, uint(divisor))
69+
adjust.Rsh(adjust, difficultyBoundDivisor)
5570
diffSec := int64(time - parent.Time)
56-
x := new(big.Rat).SetFrac64(diffSec, 7)
71+
x := new(big.Rat).SetFrac64(diffSec, targetBlockTime)
5772

5873
cVal := int64(1)
5974
if parent.UncleHash != types.EmptyUncleHash {
@@ -88,23 +103,44 @@ func CalcDifficultyFrontierU256(time uint64, parent *types.Header) *big.Int {
88103
return newDiff
89104
}
90105

106+
// CalcDifficultyHomesteadU256 calculates the block difficulty using the Homestead rules.
107+
// For blocks with parent.Number >= hardForkBlock the calculation uses the R5 formula.
91108
func CalcDifficultyHomesteadU256(time uint64, parent *types.Header) *big.Int {
92-
// Enforce the 3-second gap rule starting from block 45,000.
93-
if parent.Number.Uint64() >= 45000 && (time - parent.Time) < 3 {
94-
panic("block rejected: parent's time gap is less than 3 seconds")
95-
}
96-
97-
// Determine the divisor based on block number.
98-
divisor := difficultyBoundDivisor
99-
if parent.Number.Uint64() >= 45000 {
100-
divisor = 11
109+
// R5 calculation for post-hardfork blocks.
110+
if parent.Number.Uint64() >= hardForkBlock {
111+
pDiff, _ := uint256.FromBig(parent.Difficulty)
112+
adjust := pDiff.Clone()
113+
adjust.Rsh(adjust, r5DifficultyBoundDivisor)
114+
// Replace the original divisor of 10 with our targetBlockTime (7 seconds)
115+
x := (time - parent.Time) / targetBlockTime
116+
neg := true
117+
if x == 0 {
118+
x = 1
119+
neg = false
120+
} else if x >= 100 {
121+
x = 99
122+
} else {
123+
x = x - 1
124+
}
125+
z := new(uint256.Int).SetUint64(x)
126+
adjust.Mul(adjust, z)
127+
if neg {
128+
pDiff.Sub(pDiff, adjust)
129+
} else {
130+
pDiff.Add(pDiff, adjust)
131+
}
132+
if pDiff.LtUint64(r5MinimumDifficulty) {
133+
pDiff.SetUint64(r5MinimumDifficulty)
134+
}
135+
return pDiff.ToBig()
101136
}
102137

138+
// Custom (pre-hardfork) calculation.
103139
pDiff, _ := uint256.FromBig(parent.Difficulty)
104140
adjust := pDiff.Clone()
105-
adjust.Rsh(adjust, uint(divisor))
141+
adjust.Rsh(adjust, difficultyBoundDivisor)
106142
diffSec := int64(time - parent.Time)
107-
x := new(big.Rat).SetFrac64(diffSec, 7)
143+
x := new(big.Rat).SetFrac64(diffSec, targetBlockTime)
108144

109145
oneRat := new(big.Rat).SetInt64(1)
110146
factor := new(big.Rat).Sub(x, oneRat)
@@ -135,42 +171,67 @@ func CalcDifficultyHomesteadU256(time uint64, parent *types.Header) *big.Int {
135171
if parent.Number.Uint64() < 300 {
136172
newDiff.Mul(newDiff, big.NewInt(3))
137173
newDiff.Div(newDiff, big.NewInt(2))
138-
}
174+
}
139175
return newDiff
140176
}
141177

178+
// MakeDifficultyCalculatorU256 returns a function to calculate difficulty.
179+
// For blocks with parent.Number >= hardForkBlock the returned function uses the R5 formula.
142180
func MakeDifficultyCalculatorU256() func(time uint64, parent *types.Header) *big.Int {
143181
return func(time uint64, parent *types.Header) *big.Int {
144-
// Enforce the 3-second gap rule starting from block 45,000.
145-
if parent.Number.Uint64() >= 45000 && (time - parent.Time) < 3 {
146-
panic("block rejected: parent's time gap is less than 3 seconds")
147-
}
148-
149-
// Determine the divisor based on block number.
150-
divisor := difficultyBoundDivisor
151-
if parent.Number.Uint64() >= 45000 {
152-
divisor = 11
182+
// R5 calculation for post-hardfork blocks.
183+
if parent.Number.Uint64() >= hardForkBlock {
184+
x := (time - parent.Time) / targetBlockTime
185+
c := uint64(1)
186+
if parent.UncleHash != types.EmptyUncleHash {
187+
c = 2
188+
}
189+
xNeg := x >= c
190+
if xNeg {
191+
x = x - c
192+
} else {
193+
x = c - x
194+
}
195+
if x > 99 {
196+
x = 99
197+
}
198+
y := new(uint256.Int)
199+
y.SetFromBig(parent.Difficulty)
200+
pDiff := y.Clone()
201+
z := new(uint256.Int).SetUint64(x)
202+
y.Rsh(y, r5DifficultyBoundDivisor)
203+
z.Mul(y, z)
204+
if xNeg {
205+
y.Sub(pDiff, z)
206+
} else {
207+
y.Add(pDiff, z)
208+
}
209+
if y.LtUint64(r5MinimumDifficulty) {
210+
y.SetUint64(r5MinimumDifficulty)
211+
}
212+
return y.ToBig()
153213
}
154214

215+
// Custom (pre-hardfork) calculation.
155216
diffSec := int64(time - parent.Time)
156-
x := new(big.Rat).SetFrac64(diffSec, 7)
217+
xRat := new(big.Rat).SetFrac64(diffSec, targetBlockTime)
157218

158219
cVal := int64(1)
159220
if parent.UncleHash != types.EmptyUncleHash {
160221
cVal = 2
161222
}
162223
cRat := new(big.Rat).SetInt64(cVal)
163224

164-
delta := new(big.Rat).Sub(new(big.Rat).Quo(x, cRat), big.NewRat(1, 1))
225+
delta := new(big.Rat).Sub(new(big.Rat).Quo(xRat, cRat), big.NewRat(1, 1))
165226

166227
y := new(uint256.Int)
167228
y.SetFromBig(parent.Difficulty)
168-
y.Rsh(y, uint(divisor))
229+
y.Rsh(y, difficultyBoundDivisor)
169230

170231
prod := new(big.Rat).Mul(new(big.Rat).SetInt(y.ToBig()), delta)
171232
adjAmount := roundRat(prod)
172233

173-
if x.Cmp(cRat) >= 0 {
234+
if xRat.Cmp(cRat) >= 0 {
174235
newDiff := new(big.Int).Sub(parent.Difficulty, adjAmount)
175236
if newDiff.Cmp(big.NewInt(minimumDifficulty)) < 0 {
176237
newDiff.SetUint64(minimumDifficulty)

0 commit comments

Comments
 (0)