mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-04-02 08:05:55 +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/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).
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue