Skip to content

Commit 74e8218

Browse files
ceyonurpowerslideralarso16StephenButtolph
authored
feat(plugin/evm): ACP-226 - set expected block gas cost to 0 in Granite (#1127)
Signed-off-by: Tsvetan Dimitrov <tsvetan.dimitrov23@gmail.com> Co-authored-by: Tsvetan Dimitrov <tsvetan.dimitrov23@gmail.com> Co-authored-by: Austin Larson <78000745+alarso16@users.noreply.github.com> Co-authored-by: Stephen Buttolph <stephen@avalabs.org>
1 parent d254329 commit 74e8218

File tree

5 files changed

+89
-20
lines changed

5 files changed

+89
-20
lines changed

RELEASES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- Removed deprecated flags `coreth-admin-api-enabled`, `coreth-admin-api-dir`, `tx-regossip-frequency`, `tx-lookup-limit`. Use `admin-api-enabled`, `admin-api-dir`, `regossip-frequency`, `transaction-history` instead.
66
- Enabled RPC batch limits by default, and configurable with `batch-request-limit` and `batch-max-response-size`.
7+
- Implement ACP-226: Set expected block gas cost to 0 in Granite network upgrade, removing block gas cost requirements for block building.
78

89
## [v0.15.3](https://github.com/ava-labs/coreth/releases/tag/v0.15.3)
910

core/blockchain_ext_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,7 +1425,7 @@ func GenerateChainInvalidBlockFeeTest(t *testing.T, create createFunc) {
14251425
// Ensure that key1 has some funds in the genesis block.
14261426
genesisBalance := new(big.Int).Mul(big.NewInt(1000000), big.NewInt(params.Ether))
14271427
gspec := &Genesis{
1428-
Config: params.TestChainConfig,
1428+
Config: params.TestFortunaChainConfig,
14291429
Alloc: types.GenesisAlloc{addr1: {Balance: genesisBalance}},
14301430
}
14311431

@@ -1434,10 +1434,10 @@ func GenerateChainInvalidBlockFeeTest(t *testing.T, create createFunc) {
14341434
t.Cleanup(blockchain.Stop)
14351435

14361436
// This call generates a chain of 3 blocks.
1437-
signer := types.LatestSigner(params.TestChainConfig)
1437+
signer := types.LatestSigner(params.TestFortunaChainConfig)
14381438
_, _, _, err = GenerateChainWithGenesis(gspec, blockchain.engine, 3, ap4.TargetBlockRate-1, func(_ int, gen *BlockGen) {
14391439
tx := types.NewTx(&types.DynamicFeeTx{
1440-
ChainID: params.TestChainConfig.ChainID,
1440+
ChainID: params.TestFortunaChainConfig.ChainID,
14411441
Nonce: gen.TxNonce(addr1),
14421442
To: &addr2,
14431443
Gas: ethparams.TxGas,
@@ -1466,7 +1466,7 @@ func InsertChainInvalidBlockFeeTest(t *testing.T, create createFunc) {
14661466
// Ensure that key1 has some funds in the genesis block.
14671467
genesisBalance := new(big.Int).Mul(big.NewInt(1000000), big.NewInt(params.Ether))
14681468
gspec := &Genesis{
1469-
Config: params.TestChainConfig,
1469+
Config: params.TestFortunaChainConfig,
14701470
Alloc: types.GenesisAlloc{addr1: {Balance: genesisBalance}},
14711471
}
14721472

@@ -1475,11 +1475,11 @@ func InsertChainInvalidBlockFeeTest(t *testing.T, create createFunc) {
14751475
t.Cleanup(blockchain.Stop)
14761476

14771477
// This call generates a chain of 3 blocks.
1478-
signer := types.LatestSigner(params.TestChainConfig)
1478+
signer := types.LatestSigner(params.TestFortunaChainConfig)
14791479
eng := dummy.NewFakerWithMode(TestCallbacks, dummy.Mode{ModeSkipBlockFee: true, ModeSkipCoinbase: true})
14801480
_, chain, _, err := GenerateChainWithGenesis(gspec, eng, 3, ap4.TargetBlockRate-1, func(_ int, gen *BlockGen) {
14811481
tx := types.NewTx(&types.DynamicFeeTx{
1482-
ChainID: params.TestChainConfig.ChainID,
1482+
ChainID: params.TestFortunaChainConfig.ChainID,
14831483
Nonce: gen.TxNonce(addr1),
14841484
To: &addr2,
14851485
Gas: ethparams.TxGas,

eth/gasprice/gasprice_test.go

Lines changed: 70 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -381,13 +381,53 @@ func TestSuggestGasPricePreAP3(t *testing.T) {
381381
require.NoError(t, err)
382382
}
383383

384+
// NOTE: [Oracle.SuggestTipCap] does NOT simply return the "required" (minimum) tip.
385+
// The oracle computes a percentile of recent required tips (not observed on-chain tips)
386+
// within a time/blocks lookback window and applies a small floor (e.g., 1 wei in tests):
387+
//
388+
// suggested = max(floor, recent-required-percentile)
389+
//
390+
// After Granite, BlockGasCost is 0 and per-block required tips are 0, so the oracle
391+
// suggestion equals the floor (1 wei) in steady state, regardless of high on-chain tips.
392+
// The cases below exercise behavior across forks using the same percentile logic and floor.
384393
func TestSuggestTipCapMaxBlocksLookback(t *testing.T) {
394+
cases := []struct {
395+
chainConfig *params.ChainConfig
396+
expectedTip *big.Int
397+
}{
398+
// TODO: remove Fortuna case when we activate Granite
399+
{
400+
chainConfig: params.TestFortunaChainConfig,
401+
expectedTip: big.NewInt(3),
402+
},
403+
{
404+
chainConfig: params.TestChainConfig,
405+
expectedTip: big.NewInt(1),
406+
},
407+
}
408+
for _, c := range cases {
409+
applyGasPriceTest(t, suggestTipCapTest{
410+
chainConfig: c.chainConfig,
411+
numBlocks: 200,
412+
extDataGasUsage: common.Big0,
413+
genBlock: testGenBlock(t, 550, 80),
414+
expectedTip: c.expectedTip,
415+
}, defaultOracleConfig())
416+
}
417+
}
418+
419+
// Post-Granite, even very high observed tx tips should not affect SuggestTipCap, which
420+
// is computed from required tips. Since required tips are 0 in Granite, the returned
421+
// suggestion should be the floor (1 wei).
422+
func TestSuggestTipCapIgnoresObservedTipsPostGranite(t *testing.T) {
385423
applyGasPriceTest(t, suggestTipCapTest{
386-
chainConfig: params.TestChainConfig,
387-
numBlocks: 200,
424+
chainConfig: params.TestChainConfig, // Granite active in TestChainConfig
425+
numBlocks: 20,
388426
extDataGasUsage: common.Big0,
389-
genBlock: testGenBlock(t, 550, 80),
390-
expectedTip: big.NewInt(3),
427+
// Generate blocks with very high on-chain tips to ensure they wouldn't bias the result
428+
// if the oracle looked at observed tips. Expectation remains 1 wei.
429+
genBlock: testGenBlock(t, 100_000, 80),
430+
expectedTip: big.NewInt(1),
391431
}, defaultOracleConfig())
392432
}
393433

@@ -402,14 +442,30 @@ func TestSuggestTipCapMaxBlocksSecondsLookback(t *testing.T) {
402442
}
403443

404444
func TestSuggestTipCapIncludesExtraDataGas(t *testing.T) {
405-
applyGasPriceTest(t, suggestTipCapTest{
406-
chainConfig: params.TestChainConfig,
407-
numBlocks: 1000,
408-
extDataGasUsage: big.NewInt(acp176.MinMaxPerSecond - int64(ethparams.TxGas)),
409-
// The tip on the transaction is very large to pay the block gas cost.
410-
genBlock: testGenBlock(t, 100_000, 1),
411-
// The actual tip doesn't matter, we just want to ensure that the tip is
412-
// non-zero when almost all the gas is coming from the extDataGasUsage.
413-
expectedTip: big.NewInt(44_252),
414-
}, defaultOracleConfig())
445+
cases := []struct {
446+
chainConfig *params.ChainConfig
447+
expectedTip *big.Int
448+
}{
449+
// TODO: remove Fortuna case when we activate Granite
450+
{
451+
chainConfig: params.TestFortunaChainConfig,
452+
expectedTip: big.NewInt(44_252),
453+
},
454+
{
455+
chainConfig: params.TestChainConfig,
456+
expectedTip: big.NewInt(1),
457+
},
458+
}
459+
for _, c := range cases {
460+
applyGasPriceTest(t, suggestTipCapTest{
461+
chainConfig: c.chainConfig,
462+
numBlocks: 1000,
463+
extDataGasUsage: big.NewInt(acp176.MinMaxPerSecond - int64(ethparams.TxGas)),
464+
// The tip on the transaction is very large to pay the block gas cost.
465+
genBlock: testGenBlock(t, 100_000, 1),
466+
// The actual tip doesn't matter, we just want to ensure that the tip is
467+
// non-zero when almost all the gas is coming from the extDataGasUsage.
468+
expectedTip: c.expectedTip,
469+
}, defaultOracleConfig())
470+
}
415471
}

plugin/evm/customheader/block_gas_cost.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ var (
3232
// BlockGasCost calculates the required block gas cost based on the parent
3333
// header and the timestamp of the new block.
3434
// Prior to AP4, the returned block gas cost will be nil.
35+
// In Granite, the returned block gas cost will be 0.
3536
func BlockGasCost(
3637
config *extras.ChainConfig,
3738
parent *types.Header,
@@ -40,6 +41,9 @@ func BlockGasCost(
4041
if !config.IsApricotPhase4(timestamp) {
4142
return nil
4243
}
44+
if config.IsGranite(timestamp) {
45+
return big.NewInt(0)
46+
}
4347
step := uint64(ap4.BlockGasCostStep)
4448
if config.IsApricotPhase5(timestamp) {
4549
step = ap5.BlockGasCostStep

plugin/evm/customheader/block_gas_cost_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ func TestBlockGasCost(t *testing.T) {
6161
timestamp: 9,
6262
expected: big.NewInt(ap4.MinBlockGasCost + ap4.BlockGasCostStep*ap4.TargetBlockRate),
6363
},
64+
{
65+
name: "granite_returns_zero",
66+
upgrades: extras.TestGraniteChainConfig.NetworkUpgrades,
67+
parentTime: 10,
68+
parentCost: big.NewInt(ap4.MaxBlockGasCost),
69+
timestamp: 10 + ap4.TargetBlockRate + 1,
70+
expected: big.NewInt(0),
71+
},
6472
}
6573

6674
for _, test := range tests {

0 commit comments

Comments
 (0)