Skip to content

Commit ff44323

Browse files
committed
internal/ethapi: add block overrides to eth_call
1 parent b4dcd1a commit ff44323

File tree

9 files changed

+529
-39
lines changed

9 files changed

+529
-39
lines changed

eth/api_backend.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,12 +240,15 @@ func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
240240
return nil
241241
}
242242

243-
func (b *EthAPIBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) {
243+
func (b *EthAPIBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, func() error, error) {
244244
if vmConfig == nil {
245245
vmConfig = b.eth.blockchain.GetVMConfig()
246246
}
247247
txContext := core.NewEVMTxContext(msg)
248248
context := core.NewEVMBlockContext(header, b.eth.BlockChain(), nil)
249+
if blockCtx != nil {
250+
context = *blockCtx
251+
}
249252
return vm.NewEVM(context, txContext, state, b.eth.blockchain.Config(), *vmConfig), state.Error, nil
250253
}
251254

eth/tracers/api.go

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -100,34 +100,10 @@ func NewAPI(backend Backend) *API {
100100
return &API{backend: backend}
101101
}
102102

103-
type chainContext struct {
104-
api *API
105-
ctx context.Context
106-
}
107-
108-
func (context *chainContext) Engine() consensus.Engine {
109-
return context.api.backend.Engine()
110-
}
111-
112-
func (context *chainContext) GetHeader(hash common.Hash, number uint64) *types.Header {
113-
header, err := context.api.backend.HeaderByNumber(context.ctx, rpc.BlockNumber(number))
114-
if err != nil {
115-
return nil
116-
}
117-
if header.Hash() == hash {
118-
return header
119-
}
120-
header, err = context.api.backend.HeaderByHash(context.ctx, hash)
121-
if err != nil {
122-
return nil
123-
}
124-
return header
125-
}
126-
127103
// chainContext constructs the context reader which is used by the evm for reading
128104
// the necessary chain context.
129105
func (api *API) chainContext(ctx context.Context) core.ChainContext {
130-
return &chainContext{api: api, ctx: ctx}
106+
return ethapi.NewChainContext(ctx, api.backend)
131107
}
132108

133109
// blockByNumber is the wrapper of the chain access function offered by the backend.

graphql/graphql.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,7 +1067,7 @@ func (c *CallResult) Status() Long {
10671067
func (b *Block) Call(ctx context.Context, args struct {
10681068
Data ethapi.TransactionArgs
10691069
}) (*CallResult, error) {
1070-
result, err := ethapi.DoCall(ctx, b.r.backend, args.Data, *b.numberOrHash, nil, b.r.backend.RPCEVMTimeout(), b.r.backend.RPCGasCap())
1070+
result, err := ethapi.DoCall(ctx, b.r.backend, args.Data, *b.numberOrHash, nil, nil, b.r.backend.RPCEVMTimeout(), b.r.backend.RPCGasCap())
10711071
if err != nil {
10721072
return nil, err
10731073
}
@@ -1131,7 +1131,7 @@ func (p *Pending) Call(ctx context.Context, args struct {
11311131
Data ethapi.TransactionArgs
11321132
}) (*CallResult, error) {
11331133
pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
1134-
result, err := ethapi.DoCall(ctx, p.r.backend, args.Data, pendingBlockNr, nil, p.r.backend.RPCEVMTimeout(), p.r.backend.RPCGasCap())
1134+
result, err := ethapi.DoCall(ctx, p.r.backend, args.Data, pendingBlockNr, nil, nil, p.r.backend.RPCEVMTimeout(), p.r.backend.RPCGasCap())
11351135
if err != nil {
11361136
return nil, err
11371137
}

internal/ethapi/api.go

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"github.com/ethereum/go-ethereum/common"
3434
"github.com/ethereum/go-ethereum/common/hexutil"
3535
"github.com/ethereum/go-ethereum/common/math"
36+
"github.com/ethereum/go-ethereum/consensus"
3637
"github.com/ethereum/go-ethereum/consensus/ethash"
3738
"github.com/ethereum/go-ethereum/consensus/misc"
3839
"github.com/ethereum/go-ethereum/core"
@@ -955,7 +956,39 @@ func (diff *BlockOverrides) Apply(blockCtx *vm.BlockContext) {
955956
}
956957
}
957958

958-
func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) {
959+
// ChainContextBackend provides methods required to implement ChainContext.
960+
type ChainContextBackend interface {
961+
Engine() consensus.Engine
962+
HeaderByNumber(context.Context, rpc.BlockNumber) (*types.Header, error)
963+
}
964+
965+
// ChainContext is an implementation of core.ChainContext. It's main use-case
966+
// is instantiating a vm.BlockContext without having access to the BlockChain object.
967+
type ChainContext struct {
968+
b ChainContextBackend
969+
ctx context.Context
970+
}
971+
972+
// NewChainContext creates a new ChainContext object.
973+
func NewChainContext(ctx context.Context, backend ChainContextBackend) *ChainContext {
974+
return &ChainContext{ctx: ctx, b: backend}
975+
}
976+
977+
func (context *ChainContext) Engine() consensus.Engine {
978+
return context.b.Engine()
979+
}
980+
981+
func (context *ChainContext) GetHeader(hash common.Hash, number uint64) *types.Header {
982+
// This method is called to get the hash for a block number when executing the BLOCKHASH
983+
// opcode. Hence no need to search for non-canonical blocks.
984+
header, err := context.b.HeaderByNumber(context.ctx, rpc.BlockNumber(number))
985+
if err != nil || header.Hash() != hash {
986+
return nil
987+
}
988+
return header
989+
}
990+
991+
func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) {
959992
defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now())
960993

961994
state, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
@@ -982,7 +1015,11 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash
9821015
if err != nil {
9831016
return nil, err
9841017
}
985-
evm, vmError, err := b.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true})
1018+
blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil)
1019+
if blockOverrides != nil {
1020+
blockOverrides.Apply(&blockCtx)
1021+
}
1022+
evm, vmError, err := b.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true}, &blockCtx)
9861023
if err != nil {
9871024
return nil, err
9881025
}
@@ -1040,14 +1077,18 @@ func (e *revertError) ErrorData() interface{} {
10401077
return e.reason
10411078
}
10421079

1080+
type callConfig struct {
1081+
BlockOverrides *BlockOverrides
1082+
}
1083+
10431084
// Call executes the given transaction on the state for the given block number.
10441085
//
10451086
// Additionally, the caller can specify a batch of contract for fields overriding.
10461087
//
10471088
// Note, this function doesn't make and changes in the state/blockchain and is
10481089
// useful to execute and retrieve values.
1049-
func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride) (hexutil.Bytes, error) {
1050-
result, err := DoCall(ctx, s.b, args, blockNrOrHash, overrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap())
1090+
func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides) (hexutil.Bytes, error) {
1091+
result, err := DoCall(ctx, s.b, args, blockNrOrHash, overrides, blockOverrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap())
10511092
if err != nil {
10521093
return nil, err
10531094
}
@@ -1132,7 +1173,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
11321173
executable := func(gas uint64) (bool, *core.ExecutionResult, error) {
11331174
args.Gas = (*hexutil.Uint64)(&gas)
11341175

1135-
result, err := DoCall(ctx, b, args, blockNrOrHash, nil, 0, gasCap)
1176+
result, err := DoCall(ctx, b, args, blockNrOrHash, nil, nil, 0, gasCap)
11361177
if err != nil {
11371178
if errors.Is(err, core.ErrIntrinsicGas) {
11381179
return true, nil, nil // Special case, raise gas limit
@@ -1474,7 +1515,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
14741515
// Apply the transaction with the access list tracer
14751516
tracer := logger.NewAccessListTracer(accessList, args.from(), to, precompiles)
14761517
config := vm.Config{Tracer: tracer, NoBaseFee: true}
1477-
vmenv, _, err := b.GetEVM(ctx, msg, statedb, header, &config)
1518+
vmenv, _, err := b.GetEVM(ctx, msg, statedb, header, &config, nil)
14781519
if err != nil {
14791520
return nil, 0, nil, err
14801521
}

0 commit comments

Comments
 (0)