Skip to content

Commit

Permalink
internal/ethapi: add block override to estimateGas (#30695)
Browse files Browse the repository at this point in the history
Add block overrides to `eth_estimateGas` to align consistency with
`eth_call`.


#27800 (comment)

Fixes #28175

---------

Co-authored-by: Sina Mahmoodi <[email protected]>
  • Loading branch information
antonydenyer and s1na authored Dec 12, 2024
1 parent c1c2507 commit 88cbfab
Show file tree
Hide file tree
Showing 13 changed files with 545 additions and 375 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ profile.cov

# IdeaIDE
.idea
*.iml

# VS Code
.vscode
Expand Down
13 changes: 9 additions & 4 deletions eth/gasestimator/gasestimator.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ 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"
)
Expand All @@ -38,10 +39,11 @@ 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
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

ErrorRatio float64 // Allowed overestimation ratio for faster estimation termination
}
Expand Down Expand Up @@ -220,6 +222,9 @@ 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 {
opts.BlockOverrides.Apply(&evmContext)
}
// Lower the basefee to 0 to avoid breaking EVM
// invariants (basefee < feecap).
if call.GasPrice.Sign() == 0 {
Expand Down
5 changes: 3 additions & 2 deletions eth/tracers/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
"github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/internal/ethapi/override"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
Expand Down Expand Up @@ -163,8 +164,8 @@ type TraceConfig struct {
// field to override the state for tracing.
type TraceCallConfig struct {
TraceConfig
StateOverrides *ethapi.StateOverride
BlockOverrides *ethapi.BlockOverrides
StateOverrides *override.StateOverride
BlockOverrides *override.BlockOverrides
TxIndex *hexutil.Uint
}

Expand Down
35 changes: 18 additions & 17 deletions eth/tracers/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import (
"github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/internal/ethapi/override"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
)
Expand Down Expand Up @@ -454,7 +455,7 @@ func TestTraceCall(t *testing.T) {
Input: &hexutil.Bytes{0x43}, // blocknumber
},
config: &TraceCallConfig{
BlockOverrides: &ethapi.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))},
BlockOverrides: &override.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))},
},
expectErr: nil,
expect: ` {"gas":53018,"failed":false,"returnValue":"","structLogs":[
Expand Down Expand Up @@ -698,8 +699,8 @@ func TestTracingWithOverrides(t *testing.T) {
Value: (*hexutil.Big)(big.NewInt(1000)),
},
config: &TraceCallConfig{
StateOverrides: &ethapi.StateOverride{
randomAccounts[0].addr: ethapi.OverrideAccount{Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether)))},
StateOverrides: &override.StateOverride{
randomAccounts[0].addr: override.OverrideAccount{Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether)))},
},
},
want: `{"gas":21000,"failed":false,"returnValue":""}`,
Expand Down Expand Up @@ -740,8 +741,8 @@ func TestTracingWithOverrides(t *testing.T) {
},
config: &TraceCallConfig{
//Tracer: &tracer,
StateOverrides: &ethapi.StateOverride{
randomAccounts[2].addr: ethapi.OverrideAccount{
StateOverrides: &override.StateOverride{
randomAccounts[2].addr: override.OverrideAccount{
Code: newRPCBytes(common.Hex2Bytes("6080604052348015600f57600080fd5b506004361060285760003560e01c80638381f58a14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea2646970667358221220eab35ffa6ab2adfe380772a48b8ba78e82a1b820a18fcb6f59aa4efb20a5f60064736f6c63430007040033")),
StateDiff: newStates([]common.Hash{{}}, []common.Hash{common.BigToHash(big.NewInt(123))}),
},
Expand All @@ -757,7 +758,7 @@ func TestTracingWithOverrides(t *testing.T) {
Input: newRPCBytes(common.Hex2Bytes("4360005260206000f3")),
},
config: &TraceCallConfig{
BlockOverrides: &ethapi.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))},
BlockOverrides: &override.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))},
},
want: `{"gas":59537,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000001337"}`,
},
Expand All @@ -777,7 +778,7 @@ func TestTracingWithOverrides(t *testing.T) {
}, // blocknumber
},
config: &TraceCallConfig{
BlockOverrides: &ethapi.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))},
BlockOverrides: &override.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))},
},
want: `{"gas":72666,"failed":false,"returnValue":"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}`,
},
Expand Down Expand Up @@ -807,8 +808,8 @@ func TestTracingWithOverrides(t *testing.T) {
Data: newRPCBytes(common.Hex2Bytes("f8a8fd6d")), //
},
config: &TraceCallConfig{
StateOverrides: &ethapi.StateOverride{
randomAccounts[2].addr: ethapi.OverrideAccount{
StateOverrides: &override.StateOverride{
randomAccounts[2].addr: override.OverrideAccount{
Code: newRPCBytes(common.Hex2Bytes("6080604052348015600f57600080fd5b506004361060325760003560e01c806366e41cb7146037578063f8a8fd6d14603f575b600080fd5b603d6057565b005b60456062565b60405190815260200160405180910390f35b610539600090815580fd5b60006001600081905550306001600160a01b03166366e41cb76040518163ffffffff1660e01b8152600401600060405180830381600087803b15801560a657600080fd5b505af192505050801560b6575060015b60e9573d80801560e1576040519150601f19603f3d011682016040523d82523d6000602084013e60e6565b606091505b50505b506000549056fea26469706673582212205ce45de745a5308f713cb2f448589177ba5a442d1a2eff945afaa8915961b4d064736f6c634300080c0033")),
},
},
Expand All @@ -823,8 +824,8 @@ func TestTracingWithOverrides(t *testing.T) {
Data: newRPCBytes(common.Hex2Bytes("f8a8fd6d")), //
},
config: &TraceCallConfig{
StateOverrides: &ethapi.StateOverride{
randomAccounts[2].addr: ethapi.OverrideAccount{
StateOverrides: &override.StateOverride{
randomAccounts[2].addr: override.OverrideAccount{
Code: newRPCBytes(common.Hex2Bytes("6080604052348015600f57600080fd5b506004361060325760003560e01c806366e41cb7146037578063f8a8fd6d14603f575b600080fd5b603d6057565b005b60456062565b60405190815260200160405180910390f35b610539600090815580fd5b60006001600081905550306001600160a01b03166366e41cb76040518163ffffffff1660e01b8152600401600060405180830381600087803b15801560a657600080fd5b505af192505050801560b6575060015b60e9573d80801560e1576040519150601f19603f3d011682016040523d82523d6000602084013e60e6565b606091505b50505b506000549056fea26469706673582212205ce45de745a5308f713cb2f448589177ba5a442d1a2eff945afaa8915961b4d064736f6c634300080c0033")),
State: newStates([]common.Hash{{}}, []common.Hash{{}}),
},
Expand All @@ -841,8 +842,8 @@ func TestTracingWithOverrides(t *testing.T) {
Data: newRPCBytes(common.Hex2Bytes("f8a8fd6d")), //
},
config: &TraceCallConfig{
StateOverrides: &ethapi.StateOverride{
storageAccount: ethapi.OverrideAccount{
StateOverrides: &override.StateOverride{
storageAccount: override.OverrideAccount{
Code: newRPCBytes([]byte{
// SLOAD(3) + SLOAD(4) (which is 0x77)
byte(vm.PUSH1), 0x04,
Expand Down Expand Up @@ -876,8 +877,8 @@ func TestTracingWithOverrides(t *testing.T) {
Data: newRPCBytes(common.Hex2Bytes("f8a8fd6d")), //
},
config: &TraceCallConfig{
StateOverrides: &ethapi.StateOverride{
storageAccount: ethapi.OverrideAccount{
StateOverrides: &override.StateOverride{
storageAccount: override.OverrideAccount{
Code: newRPCBytes([]byte{
// SLOAD(3) + SLOAD(4) (which is now 0x11 + 0x00)
byte(vm.PUSH1), 0x04,
Expand Down Expand Up @@ -914,8 +915,8 @@ func TestTracingWithOverrides(t *testing.T) {
Data: newRPCBytes(common.Hex2Bytes("f8a8fd6d")), //
},
config: &TraceCallConfig{
StateOverrides: &ethapi.StateOverride{
storageAccount: ethapi.OverrideAccount{
StateOverrides: &override.StateOverride{
storageAccount: override.OverrideAccount{
Code: newRPCBytes([]byte{
// SLOAD(3) + SLOAD(4) (which is now 0x11 + 0x44)
byte(vm.PUSH1), 0x04,
Expand Down
4 changes: 2 additions & 2 deletions graphql/graphql.go
Original file line number Diff line number Diff line change
Expand Up @@ -1208,7 +1208,7 @@ func (b *Block) Call(ctx context.Context, args struct {
func (b *Block) EstimateGas(ctx context.Context, args struct {
Data ethapi.TransactionArgs
}) (hexutil.Uint64, error) {
return ethapi.DoEstimateGas(ctx, b.r.backend, args.Data, *b.numberOrHash, nil, b.r.backend.RPCGasCap())
return ethapi.DoEstimateGas(ctx, b.r.backend, args.Data, *b.numberOrHash, nil, nil, b.r.backend.RPCGasCap())
}

type Pending struct {
Expand Down Expand Up @@ -1272,7 +1272,7 @@ func (p *Pending) EstimateGas(ctx context.Context, args struct {
Data ethapi.TransactionArgs
}) (hexutil.Uint64, error) {
latestBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
return ethapi.DoEstimateGas(ctx, p.r.backend, args.Data, latestBlockNr, nil, p.r.backend.RPCGasCap())
return ethapi.DoEstimateGas(ctx, p.r.backend, args.Data, latestBlockNr, nil, nil, p.r.backend.RPCGasCap())
}

// Resolver is the top-level object in the GraphQL hierarchy.
Expand Down
Loading

0 comments on commit 88cbfab

Please sign in to comment.