Skip to content

Commit 804335f

Browse files
committed
Change FeeConfig.TargetBlockRate to be a time.Duration
1 parent 88182c1 commit 804335f

24 files changed

+94
-69
lines changed

commontype/fee_config.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package commontype
66
import (
77
"fmt"
88
"math/big"
9+
"time"
910

1011
"github.com/ava-labs/subnet-evm/utils"
1112
"github.com/ethereum/go-ethereum/common"
@@ -23,9 +24,9 @@ type FeeConfig struct {
2324
// GasLimit sets the max amount of gas consumed per block.
2425
GasLimit *big.Int `json:"gasLimit,omitempty"`
2526

26-
// TargetBlockRate sets the target rate of block production in seconds.
27-
// A target of 2 will target producing a block every 2 seconds.
28-
TargetBlockRate uint64 `json:"targetBlockRate,omitempty"`
27+
// TargetBlockRate sets the target rate of block production as a duration string.
28+
// A target of 2s will target producing a block every 2 seconds.
29+
TargetBlockRate time.Duration `json:"targetBlockRate,omitempty"`
2930

3031
// The minimum base fee sets a lower bound on the EIP-1559 base fee of a block.
3132
// Since the block's base fee sets the minimum gas price for any transaction included in that block, this effectively sets a minimum
@@ -48,7 +49,7 @@ type FeeConfig struct {
4849
MaxBlockGasCost *big.Int `json:"maxBlockGasCost,omitempty"`
4950
// BlockGasCostStep determines how much to increase/decrease the block gas cost depending on the amount of time elapsed since the previous block.
5051
// If the block is produced at the target rate, the block gas cost will stay the same as the block gas cost for the parent block.
51-
// If it is produced faster/slower, the block gas cost will be increased/decreased by the step value for each second faster/slower than the target
52+
// If it is produced faster/slower, the block gas cost will be increased/decreased by the step value for each nanosecond faster/slower than the target
5253
// block rate accordingly.
5354
// Note: if the BlockGasCostStep is set to a very large number, it effectively requires block production to go no faster than the TargetBlockRate.
5455
//
@@ -82,7 +83,7 @@ func (f *FeeConfig) Verify() error {
8283
case f.GasLimit.Cmp(common.Big0) != 1:
8384
return fmt.Errorf("gasLimit = %d cannot be less than or equal to 0", f.GasLimit)
8485
case f.TargetBlockRate <= 0:
85-
return fmt.Errorf("targetBlockRate = %d cannot be less than or equal to 0", f.TargetBlockRate)
86+
return fmt.Errorf("targetBlockRate = %s cannot be less than or equal to 0", f.TargetBlockRate)
8687
case f.MinBaseFee.Cmp(common.Big0) == -1:
8788
return fmt.Errorf("minBaseFee = %d cannot be less than 0", f.MinBaseFee)
8889
case f.TargetGas.Cmp(common.Big0) != 1:
@@ -120,7 +121,7 @@ func (f *FeeConfig) checkByteLens() error {
120121
if isBiggerThanHashLen(f.GasLimit) {
121122
return fmt.Errorf("gasLimit exceeds %d bytes", common.HashLength)
122123
}
123-
if isBiggerThanHashLen(new(big.Int).SetUint64(f.TargetBlockRate)) {
124+
if isBiggerThanHashLen(new(big.Int).SetUint64(uint64(f.TargetBlockRate.Seconds()))) {
124125
return fmt.Errorf("targetBlockRate exceeds %d bytes", common.HashLength)
125126
}
126127
if isBiggerThanHashLen(f.MinBaseFee) {

commontype/fee_config_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package commontype
66
import (
77
"math/big"
88
"testing"
9+
"time"
910

1011
"github.com/stretchr/testify/require"
1112
)
@@ -20,7 +21,7 @@ func TestVerify(t *testing.T) {
2021
name: "nil gasLimit in FeeConfig",
2122
config: &FeeConfig{
2223
// GasLimit: big.NewInt(8_000_000)
23-
TargetBlockRate: 2, // in seconds
24+
TargetBlockRate: 2 * time.Second,
2425

2526
MinBaseFee: big.NewInt(25_000_000_000),
2627
TargetGas: big.NewInt(15_000_000),
@@ -40,7 +41,7 @@ func TestVerify(t *testing.T) {
4041
{
4142
name: "invalid TargetBlockRate in FeeConfig",
4243
config: func() *FeeConfig { c := ValidTestFeeConfig; c.TargetBlockRate = 0; return &c }(),
43-
expectedError: "targetBlockRate = 0 cannot be less than or equal to 0",
44+
expectedError: "targetBlockRate = 0s cannot be less than or equal to 0",
4445
},
4546
{
4647
name: "invalid MinBaseFee in FeeConfig",
@@ -109,7 +110,7 @@ func TestEqual(t *testing.T) {
109110
a: &ValidTestFeeConfig,
110111
b: &FeeConfig{
111112
GasLimit: big.NewInt(8_000_000),
112-
TargetBlockRate: 2, // in seconds
113+
TargetBlockRate: 2 * time.Second,
113114

114115
MinBaseFee: big.NewInt(25_000_000_000),
115116
TargetGas: big.NewInt(15_000_000),

commontype/test_fee_config.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33

44
package commontype
55

6-
import "math/big"
6+
import (
7+
"math/big"
8+
"time"
9+
)
710

811
var ValidTestFeeConfig = FeeConfig{
912
GasLimit: big.NewInt(8_000_000),
10-
TargetBlockRate: 2, // in seconds
13+
TargetBlockRate: 2 * time.Second,
1114

1215
MinBaseFee: big.NewInt(25_000_000_000),
1316
TargetGas: big.NewInt(15_000_000),

consensus/dummy/consensus.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ func (eng *DummyEngine) verifyHeaderGasFields(config *params.ChainConfig, header
184184
feeConfig.MaxBlockGasCost,
185185
feeConfig.BlockGasCostStep,
186186
parent.BlockGasCost,
187-
parent.Time, header.Time,
187+
time.Unix(int64(parent.Time), 0),
188+
time.Unix(int64(header.Time), 0),
188189
)
189190
if header.BlockGasCost == nil {
190191
return errBlockGasCostNil
@@ -379,7 +380,8 @@ func (eng *DummyEngine) Finalize(chain consensus.ChainHeaderReader, block *types
379380
feeConfig.MaxBlockGasCost,
380381
feeConfig.BlockGasCostStep,
381382
parent.BlockGasCost,
382-
parent.Time, block.Time(),
383+
time.Unix(int64(parent.Time), 0),
384+
time.Unix(int64(block.Time()), 0),
383385
)
384386
// Verify the BlockGasCost set in the header matches the calculated value.
385387
if blockBlockGasCost := block.BlockGasCost(); blockBlockGasCost == nil || !blockBlockGasCost.IsUint64() || blockBlockGasCost.Cmp(blockGasCost) != 0 {
@@ -416,7 +418,8 @@ func (eng *DummyEngine) FinalizeAndAssemble(chain consensus.ChainHeaderReader, h
416418
feeConfig.MaxBlockGasCost,
417419
feeConfig.BlockGasCostStep,
418420
parent.BlockGasCost,
419-
parent.Time, header.Time,
421+
time.Unix(int64(parent.Time), 0),
422+
time.Unix(int64(header.Time), 0),
420423
)
421424
// Verify that this block covers the block fee.
422425
if err := eng.verifyBlockFee(

consensus/dummy/consensus_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
package dummy
55

66
import (
7-
"math"
87
"math/big"
98
"testing"
9+
"time"
1010

1111
"github.com/ava-labs/subnet-evm/core/types"
1212
"github.com/ava-labs/subnet-evm/params"
@@ -96,8 +96,8 @@ func TestVerifyBlockFee(t *testing.T) {
9696
"tx only base fee after large time window": {
9797
baseFee: big.NewInt(100),
9898
parentBlockGasCost: big.NewInt(100_000),
99-
parentTime: 0,
100-
currentTime: math.MaxUint64,
99+
parentTime: 0, // 1970
100+
currentTime: uint64(time.Date(2025, 0, 0, 0, 0, 0, 0, time.UTC).Unix()),
101101
txs: []*types.Transaction{
102102
types.NewTransaction(0, common.HexToAddress("7ef5a6135f1fd6a02593eedc869c6d41d934aef8"), big.NewInt(0), 100, big.NewInt(100), nil),
103103
},
@@ -125,7 +125,8 @@ func TestVerifyBlockFee(t *testing.T) {
125125
params.DefaultFeeConfig.MaxBlockGasCost,
126126
testBlockGasCostStep,
127127
test.parentBlockGasCost,
128-
test.parentTime, test.currentTime,
128+
time.Unix(int64(test.parentTime), 0),
129+
time.Unix(int64(test.currentTime), 0),
129130
)
130131
engine := NewFaker()
131132
if err := engine.verifyBlockFee(test.baseFee, blockGasCost, test.txs, test.receipts); err != nil {

consensus/dummy/dynamic_fees.go

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"encoding/binary"
88
"fmt"
99
"math/big"
10+
"time"
1011

1112
"github.com/ava-labs/avalanchego/utils/wrappers"
1213
"github.com/ava-labs/subnet-evm/commontype"
@@ -203,31 +204,38 @@ func updateLongWindow(window []byte, start uint64, gasConsumed uint64) {
203204
// calcBlockGasCost calculates the required block gas cost. If [parentTime]
204205
// > [currentTime], the timeElapsed will be treated as 0.
205206
func calcBlockGasCost(
206-
targetBlockRate uint64,
207+
targetBlockRate time.Duration,
207208
minBlockGasCost *big.Int,
208209
maxBlockGasCost *big.Int,
209-
blockGasCostStep *big.Int,
210+
blockGasCostStep *big.Int, // per second
210211
parentBlockGasCost *big.Int,
211-
parentTime, currentTime uint64,
212+
parentTime, currentTime time.Time,
212213
) *big.Int {
213214
// Handle Subnet EVM boundary by returning the minimum value as the boundary.
214215
if parentBlockGasCost == nil {
215216
return new(big.Int).Set(minBlockGasCost)
216217
}
217218

219+
blockGasCostStepPerSec, _ := blockGasCostStep.Float64()
220+
blockGasCostStepPerNS := blockGasCostStepPerSec / float64(time.Second)
221+
218222
// Treat an invalid parent/current time combination as 0 elapsed time.
219-
var timeElapsed uint64
220-
if parentTime <= currentTime {
221-
timeElapsed = currentTime - parentTime
223+
var timeElapsed time.Duration
224+
if parentTime.Before(currentTime) {
225+
timeElapsed = currentTime.Sub(parentTime)
222226
}
223227

224228
var blockGasCost *big.Int
225229
if timeElapsed < targetBlockRate {
226-
blockGasCostDelta := new(big.Int).Mul(blockGasCostStep, new(big.Int).SetUint64(targetBlockRate-timeElapsed))
227-
blockGasCost = new(big.Int).Add(parentBlockGasCost, blockGasCostDelta)
230+
timeDiff := targetBlockRate - timeElapsed
231+
blockGasCostDelta := blockGasCostStepPerNS * float64(timeDiff)
232+
bigBlockGasCostDelta := new(big.Int).SetUint64(uint64(blockGasCostDelta))
233+
blockGasCost = new(big.Int).Add(parentBlockGasCost, bigBlockGasCostDelta)
228234
} else {
229-
blockGasCostDelta := new(big.Int).Mul(blockGasCostStep, new(big.Int).SetUint64(timeElapsed-targetBlockRate))
230-
blockGasCost = new(big.Int).Sub(parentBlockGasCost, blockGasCostDelta)
235+
timeDiff := timeElapsed - targetBlockRate
236+
blockGasCostDelta := blockGasCostStepPerNS * float64(timeDiff)
237+
bigBlockGasCostDelta := new(big.Int).SetUint64(uint64(blockGasCostDelta))
238+
blockGasCost = new(big.Int).Sub(parentBlockGasCost, bigBlockGasCostDelta)
231239
}
232240

233241
blockGasCost = selectBigWithinBounds(minBlockGasCost, blockGasCost, maxBlockGasCost)

consensus/dummy/dynamic_fees_test.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"encoding/binary"
88
"math/big"
99
"testing"
10+
"time"
1011

1112
"github.com/ava-labs/subnet-evm/commontype"
1213
"github.com/ava-labs/subnet-evm/core/types"
@@ -217,7 +218,7 @@ func testDynamicFeesStaysWithinRange(t *testing.T, test test) {
217218
for index, block := range blocks[1:] {
218219
testFeeConfig := commontype.FeeConfig{
219220
GasLimit: big.NewInt(8_000_000),
220-
TargetBlockRate: 2, // in seconds
221+
TargetBlockRate: 2 * time.Second,
221222

222223
MinBaseFee: test.minFee,
223224
TargetGas: big.NewInt(15_000_000),
@@ -430,15 +431,16 @@ func TestCalcBlockGasCost(t *testing.T) {
430431

431432
for name, test := range tests {
432433
t.Run(name, func(t *testing.T) {
433-
assert.Zero(t, test.expected.Cmp(calcBlockGasCost(
434+
got := calcBlockGasCost(
434435
params.DefaultFeeConfig.TargetBlockRate,
435436
params.DefaultFeeConfig.MinBlockGasCost,
436437
params.DefaultFeeConfig.MaxBlockGasCost,
437438
testBlockGasCostStep,
438439
test.parentBlockGasCost,
439-
test.parentTime,
440-
test.currentTime,
441-
)))
440+
time.Unix(int64(test.parentTime), 0),
441+
time.Unix(int64(test.currentTime), 0),
442+
)
443+
assert.Equal(t, test.expected.String(), got.String())
442444
})
443445
}
444446
}
@@ -457,7 +459,7 @@ func TestCalcBaseFeeRegression(t *testing.T) {
457459

458460
testFeeConfig := commontype.FeeConfig{
459461
GasLimit: big.NewInt(8_000_000),
460-
TargetBlockRate: 2, // in seconds
462+
TargetBlockRate: 2 * time.Second,
461463

462464
MinBaseFee: big.NewInt(1 * params.GWei),
463465
TargetGas: big.NewInt(15_000_000),

core/test_blockchain.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1511,7 +1511,7 @@ func TestStatefulPrecompiles(t *testing.T, create func(db ethdb.Database, gspec
15111511
}
15121512
testFeeConfig := commontype.FeeConfig{
15131513
GasLimit: big.NewInt(11_000_000),
1514-
TargetBlockRate: 5, // in seconds
1514+
TargetBlockRate: 5 * time.Second,
15151515

15161516
MinBaseFee: big.NewInt(28_000_000_000),
15171517
TargetGas: big.NewInt(18_000_000),

core/txpool/legacypool/legacypool_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ var (
6464

6565
testFeeConfig = commontype.FeeConfig{
6666
GasLimit: big.NewInt(8_000_000),
67-
TargetBlockRate: 2, // in seconds
67+
TargetBlockRate: 2 * time.Second,
6868

6969
MinBaseFee: big.NewInt(25_000_000_000),
7070
TargetGas: big.NewInt(15_000_000),

params/config_extra.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"errors"
99
"fmt"
1010
"math/big"
11+
"time"
1112

1213
"github.com/ava-labs/avalanchego/snow"
1314
"github.com/ava-labs/avalanchego/utils/wrappers"
@@ -36,7 +37,7 @@ var (
3637

3738
DefaultFeeConfig = commontype.FeeConfig{
3839
GasLimit: big.NewInt(8_000_000),
39-
TargetBlockRate: 2, // in seconds
40+
TargetBlockRate: 2 * time.Second,
4041

4142
MinBaseFee: big.NewInt(25_000_000_000),
4243
TargetGas: big.NewInt(15_000_000),

params/config_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ func TestChainConfigMarshalWithUpgrades(t *testing.T) {
292292
"chainId": 1,
293293
"feeConfig": {
294294
"gasLimit": 8000000,
295-
"targetBlockRate": 2,
295+
"targetBlockRate": 2e+09,
296296
"minBaseFee": 25000000000,
297297
"targetGas": 15000000,
298298
"baseFeeChangeDenominator": 36,

plugin/evm/vm_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2426,7 +2426,7 @@ func TestFeeManagerChangeFee(t *testing.T) {
24262426
// set a lower fee config now
24272427
testLowFeeConfig := commontype.FeeConfig{
24282428
GasLimit: big.NewInt(8_000_000),
2429-
TargetBlockRate: 5, // in seconds
2429+
TargetBlockRate: 5 * time.Second,
24302430

24312431
MinBaseFee: big.NewInt(5_000_000_000),
24322432
TargetGas: big.NewInt(18_000_000),

precompile/contracts/feemanager/config_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package feemanager
66
import (
77
"math/big"
88
"testing"
9+
"time"
910

1011
"github.com/ava-labs/subnet-evm/commontype"
1112
"github.com/ava-labs/subnet-evm/precompile/allowlist"
@@ -18,7 +19,7 @@ import (
1819

1920
var validFeeConfig = commontype.FeeConfig{
2021
GasLimit: big.NewInt(8_000_000),
21-
TargetBlockRate: 2, // in seconds
22+
TargetBlockRate: 2 * time.Second,
2223

2324
MinBaseFee: big.NewInt(25_000_000_000),
2425
TargetGas: big.NewInt(15_000_000),

precompile/contracts/feemanager/contract.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"errors"
99
"fmt"
1010
"math/big"
11+
"time"
1112

1213
"github.com/ava-labs/subnet-evm/accounts/abi"
1314
"github.com/ava-labs/subnet-evm/commontype"
@@ -89,7 +90,7 @@ func GetStoredFeeConfig(stateDB contract.StateDB) commontype.FeeConfig {
8990
case gasLimitKey:
9091
feeConfig.GasLimit = new(big.Int).Set(val.Big())
9192
case targetBlockRateKey:
92-
feeConfig.TargetBlockRate = val.Big().Uint64()
93+
feeConfig.TargetBlockRate = time.Duration(val.Big().Uint64()) * time.Second
9394
case minBaseFeeKey:
9495
feeConfig.MinBaseFee = new(big.Int).Set(val.Big())
9596
case targetGasKey:
@@ -128,7 +129,7 @@ func StoreFeeConfig(stateDB contract.StateDB, feeConfig commontype.FeeConfig, bl
128129
case gasLimitKey:
129130
input = common.BigToHash(feeConfig.GasLimit)
130131
case targetBlockRateKey:
131-
input = common.BigToHash(new(big.Int).SetUint64(feeConfig.TargetBlockRate))
132+
input = common.BigToHash(new(big.Int).SetUint64(uint64(feeConfig.TargetBlockRate.Seconds())))
132133
case minBaseFeeKey:
133134
input = common.BigToHash(feeConfig.MinBaseFee)
134135
case targetGasKey:
@@ -160,7 +161,7 @@ func StoreFeeConfig(stateDB contract.StateDB, feeConfig commontype.FeeConfig, bl
160161
func PackSetFeeConfig(input commontype.FeeConfig) ([]byte, error) {
161162
inputStruct := FeeConfigABIStruct{
162163
GasLimit: input.GasLimit,
163-
TargetBlockRate: new(big.Int).SetUint64(input.TargetBlockRate),
164+
TargetBlockRate: new(big.Int).SetUint64(uint64(input.TargetBlockRate.Seconds())),
164165
MinBaseFee: input.MinBaseFee,
165166
TargetGas: input.TargetGas,
166167
BaseFeeChangeDenominator: input.BaseFeeChangeDenominator,
@@ -190,7 +191,7 @@ func UnpackSetFeeConfigInput(input []byte, useStrictMode bool) (commontype.FeeCo
190191

191192
result := commontype.FeeConfig{
192193
GasLimit: inputStruct.GasLimit,
193-
TargetBlockRate: inputStruct.TargetBlockRate.Uint64(),
194+
TargetBlockRate: time.Duration(inputStruct.TargetBlockRate.Uint64()) * time.Second,
194195
MinBaseFee: inputStruct.MinBaseFee,
195196
TargetGas: inputStruct.TargetGas,
196197
BaseFeeChangeDenominator: inputStruct.BaseFeeChangeDenominator,
@@ -268,7 +269,7 @@ func PackGetFeeConfig() ([]byte, error) {
268269
func PackGetFeeConfigOutput(output commontype.FeeConfig) ([]byte, error) {
269270
outputStruct := FeeConfigABIStruct{
270271
GasLimit: output.GasLimit,
271-
TargetBlockRate: new(big.Int).SetUint64(output.TargetBlockRate),
272+
TargetBlockRate: new(big.Int).SetUint64(uint64(output.TargetBlockRate.Seconds())),
272273
MinBaseFee: output.MinBaseFee,
273274
TargetGas: output.TargetGas,
274275
BaseFeeChangeDenominator: output.BaseFeeChangeDenominator,
@@ -303,7 +304,7 @@ func UnpackGetFeeConfigOutput(output []byte, skipLenCheck bool) (commontype.FeeC
303304

304305
result := commontype.FeeConfig{
305306
GasLimit: outputStruct.GasLimit,
306-
TargetBlockRate: outputStruct.TargetBlockRate.Uint64(),
307+
TargetBlockRate: time.Duration(outputStruct.TargetBlockRate.Uint64()) * time.Second,
307308
MinBaseFee: outputStruct.MinBaseFee,
308309
TargetGas: outputStruct.TargetGas,
309310
BaseFeeChangeDenominator: outputStruct.BaseFeeChangeDenominator,

0 commit comments

Comments
 (0)