eth/gasestimator: fix block overrides in estimate gas (#34081)

Block overrides were to a great extent ignored by the gasestimator. This PR
fixes that.
This commit is contained in:
Daniel Liu 2026-04-02 02:32:17 +08:00 committed by GitHub
parent fc43170cdd
commit 14a26d9ccc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 46 additions and 28 deletions

View file

@ -27,7 +27,6 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/internal/ethapi/override"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
)
@ -38,11 +37,12 @@ import (
// these together, it would be excessively hard to test. Splitting the parts out
// allows testing without needing a proper live chain.
type Options struct {
Config *params.ChainConfig // Chain configuration for hard fork selection
Chain core.ChainContext // Chain context to access past block hashes
Header *types.Header // Header defining the block context to execute in
State *state.StateDB // Pre-state on top of which to estimate the gas
BlockOverrides *override.BlockOverrides // Block overrides to apply during the estimation
Config *params.ChainConfig // Chain configuration for hard fork selection
Chain core.ChainContext // Chain context to access past block hashes
Header *types.Header // Header defining the block context to execute in
State *state.StateDB // Pre-state on top of which to estimate the gas
BlobBaseFee *big.Int // BlobBaseFee optionally overrides the blob base fee in the execution context.
ErrorRatio float64 // Allowed overestimation ratio for faster estimation termination
}
@ -64,16 +64,7 @@ func Estimate(ctx context.Context, call *core.Message, opts *Options, gasCap uin
// Cap the maximum gas allowance according to EIP-7825 if the estimation targets Osaka
if hi > params.MaxTxGas {
blockNumber, blockTime := opts.Header.Number, opts.Header.Time
if opts.BlockOverrides != nil {
if opts.BlockOverrides.Number != nil {
blockNumber = opts.BlockOverrides.Number.ToInt()
}
if opts.BlockOverrides.Time != nil {
blockTime = uint64(*opts.BlockOverrides.Time)
}
}
if opts.Config.IsOsaka(blockNumber, blockTime) {
if opts.Config.IsOsaka(opts.Header.Number, opts.Header.Time) {
hi = params.MaxTxGas
}
}
@ -241,10 +232,8 @@ func run(ctx context.Context, call *core.Message, opts *Options) (*core.Executio
evmContext = core.NewEVMBlockContext(opts.Header, opts.Chain, nil)
dirtyState = opts.State.Copy()
)
if opts.BlockOverrides != nil {
if err := opts.BlockOverrides.Apply(&evmContext); err != nil {
return nil, err
}
if opts.BlobBaseFee != nil {
evmContext.BlobBaseFee = new(big.Int).Set(opts.BlobBaseFee)
}
// Lower the basefee to 0 to avoid breaking EVM
// invariants (basefee < feecap).

View file

@ -897,6 +897,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
if err := blockOverrides.Apply(&blockCtx); err != nil {
return 0, err
}
header = blockOverrides.MakeHeader(header)
}
rules := b.ChainConfig().Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time)
precompiles := vm.ActivePrecompiledContracts(rules)
@ -904,13 +905,17 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
return 0, err
}
// Construct the gas estimator option from the user input
var blobBaseFee *big.Int
if blockOverrides != nil && blockOverrides.BlobBaseFee != nil {
blobBaseFee = blockOverrides.BlobBaseFee.ToInt()
}
opts := &gasestimator.Options{
Config: b.ChainConfig(),
Chain: NewChainContext(ctx, b),
Header: header,
BlockOverrides: blockOverrides,
State: state,
ErrorRatio: estimateGasErrorRatio,
Config: b.ChainConfig(),
Chain: NewChainContext(ctx, b),
Header: header,
State: state,
BlobBaseFee: blobBaseFee,
ErrorRatio: estimateGasErrorRatio,
}
// Set any required transaction default, but make sure the gas cap itself is not messed with
// if it was not specified in the original argument list.

View file

@ -780,6 +780,17 @@ func TestEstimateGas(t *testing.T) {
expectErr: core.ErrInsufficientFunds,
want: 21000,
},
// block override gas limit should bound estimation search space.
{
blockNumber: rpc.LatestBlockNumber,
call: TransactionArgs{
From: &accounts[0].addr,
Input: hex2Bytes("6080604052348015600f57600080fd5b50483a1015601c57600080fd5b60003a111560315760004811603057600080fd5b5b603f80603e6000396000f3fe6080604052600080fdfea264697066735822122060729c2cee02b10748fae5200f1c9da4661963354973d9154c13a8e9ce9dee1564736f6c63430008130033"),
Gas: func() *hexutil.Uint64 { v := hexutil.Uint64(0); return &v }(),
},
blockOverrides: override.BlockOverrides{GasLimit: func() *hexutil.Uint64 { v := hexutil.Uint64(50000); return &v }()},
expectErr: errors.New("gas required exceeds allowance (50000)"),
},
// empty create
{
blockNumber: rpc.LatestBlockNumber,
@ -861,6 +872,19 @@ func TestEstimateGas(t *testing.T) {
},
want: 21000,
},
// blob base fee block override should be applied during estimation.
{
blockNumber: rpc.LatestBlockNumber,
call: TransactionArgs{
From: &accounts[0].addr,
To: &accounts[1].addr,
Value: (*hexutil.Big)(big.NewInt(1)),
BlobHashes: []common.Hash{{0x01, 0x22}},
BlobFeeCap: (*hexutil.Big)(big.NewInt(1)),
},
blockOverrides: override.BlockOverrides{BlobBaseFee: (*hexutil.Big)(big.NewInt(2))},
expectErr: core.ErrBlobFeeCapTooLow,
},
// // SPDX-License-Identifier: GPL-3.0
//pragma solidity >=0.8.2 <0.9.0;
//
@ -1014,7 +1038,7 @@ func TestCall(t *testing.T) {
Balance: big.NewInt(params.Ether),
Nonce: 1,
Storage: map[common.Hash]common.Hash{
common.Hash{}: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001"),
{}: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001"),
},
},
},
@ -3795,7 +3819,7 @@ func TestCreateAccessListWithStateOverrides(t *testing.T) {
Balance: (*hexutil.Big)(big.NewInt(1000000000000000000)),
Nonce: &nonce,
State: map[common.Hash]common.Hash{
common.Hash{}: common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000002a"),
{}: common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000002a"),
},
},
}