mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-18 10:50:44 +00:00
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:
parent
fc43170cdd
commit
14a26d9ccc
3 changed files with 46 additions and 28 deletions
|
|
@ -27,7 +27,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"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/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
@ -38,11 +37,12 @@ import (
|
||||||
// these together, it would be excessively hard to test. Splitting the parts out
|
// these together, it would be excessively hard to test. Splitting the parts out
|
||||||
// allows testing without needing a proper live chain.
|
// allows testing without needing a proper live chain.
|
||||||
type Options struct {
|
type Options struct {
|
||||||
Config *params.ChainConfig // Chain configuration for hard fork selection
|
Config *params.ChainConfig // Chain configuration for hard fork selection
|
||||||
Chain core.ChainContext // Chain context to access past block hashes
|
Chain core.ChainContext // Chain context to access past block hashes
|
||||||
Header *types.Header // Header defining the block context to execute in
|
Header *types.Header // Header defining the block context to execute in
|
||||||
State *state.StateDB // Pre-state on top of which to estimate the gas
|
State *state.StateDB // Pre-state on top of which to estimate the gas
|
||||||
BlockOverrides *override.BlockOverrides // Block overrides to apply during the estimation
|
|
||||||
|
BlobBaseFee *big.Int // BlobBaseFee optionally overrides the blob base fee in the execution context.
|
||||||
|
|
||||||
ErrorRatio float64 // Allowed overestimation ratio for faster estimation termination
|
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
|
// Cap the maximum gas allowance according to EIP-7825 if the estimation targets Osaka
|
||||||
if hi > params.MaxTxGas {
|
if hi > params.MaxTxGas {
|
||||||
blockNumber, blockTime := opts.Header.Number, opts.Header.Time
|
if opts.Config.IsOsaka(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) {
|
|
||||||
hi = params.MaxTxGas
|
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)
|
evmContext = core.NewEVMBlockContext(opts.Header, opts.Chain, nil)
|
||||||
dirtyState = opts.State.Copy()
|
dirtyState = opts.State.Copy()
|
||||||
)
|
)
|
||||||
if opts.BlockOverrides != nil {
|
if opts.BlobBaseFee != nil {
|
||||||
if err := opts.BlockOverrides.Apply(&evmContext); err != nil {
|
evmContext.BlobBaseFee = new(big.Int).Set(opts.BlobBaseFee)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Lower the basefee to 0 to avoid breaking EVM
|
// Lower the basefee to 0 to avoid breaking EVM
|
||||||
// invariants (basefee < feecap).
|
// invariants (basefee < feecap).
|
||||||
|
|
|
||||||
|
|
@ -897,6 +897,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
|
||||||
if err := blockOverrides.Apply(&blockCtx); err != nil {
|
if err := blockOverrides.Apply(&blockCtx); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
header = blockOverrides.MakeHeader(header)
|
||||||
}
|
}
|
||||||
rules := b.ChainConfig().Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time)
|
rules := b.ChainConfig().Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time)
|
||||||
precompiles := vm.ActivePrecompiledContracts(rules)
|
precompiles := vm.ActivePrecompiledContracts(rules)
|
||||||
|
|
@ -904,13 +905,17 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
// Construct the gas estimator option from the user input
|
// 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{
|
opts := &gasestimator.Options{
|
||||||
Config: b.ChainConfig(),
|
Config: b.ChainConfig(),
|
||||||
Chain: NewChainContext(ctx, b),
|
Chain: NewChainContext(ctx, b),
|
||||||
Header: header,
|
Header: header,
|
||||||
BlockOverrides: blockOverrides,
|
State: state,
|
||||||
State: state,
|
BlobBaseFee: blobBaseFee,
|
||||||
ErrorRatio: estimateGasErrorRatio,
|
ErrorRatio: estimateGasErrorRatio,
|
||||||
}
|
}
|
||||||
// Set any required transaction default, but make sure the gas cap itself is not messed with
|
// 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.
|
// if it was not specified in the original argument list.
|
||||||
|
|
|
||||||
|
|
@ -780,6 +780,17 @@ func TestEstimateGas(t *testing.T) {
|
||||||
expectErr: core.ErrInsufficientFunds,
|
expectErr: core.ErrInsufficientFunds,
|
||||||
want: 21000,
|
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
|
// empty create
|
||||||
{
|
{
|
||||||
blockNumber: rpc.LatestBlockNumber,
|
blockNumber: rpc.LatestBlockNumber,
|
||||||
|
|
@ -861,6 +872,19 @@ func TestEstimateGas(t *testing.T) {
|
||||||
},
|
},
|
||||||
want: 21000,
|
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
|
// // SPDX-License-Identifier: GPL-3.0
|
||||||
//pragma solidity >=0.8.2 <0.9.0;
|
//pragma solidity >=0.8.2 <0.9.0;
|
||||||
//
|
//
|
||||||
|
|
@ -1014,7 +1038,7 @@ func TestCall(t *testing.T) {
|
||||||
Balance: big.NewInt(params.Ether),
|
Balance: big.NewInt(params.Ether),
|
||||||
Nonce: 1,
|
Nonce: 1,
|
||||||
Storage: map[common.Hash]common.Hash{
|
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)),
|
Balance: (*hexutil.Big)(big.NewInt(1000000000000000000)),
|
||||||
Nonce: &nonce,
|
Nonce: &nonce,
|
||||||
State: map[common.Hash]common.Hash{
|
State: map[common.Hash]common.Hash{
|
||||||
common.Hash{}: common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000002a"),
|
{}: common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000002a"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue