eth, internal: extend the TraceCall API (#22245)

Adds an an optional parameter `overrides *map[common.Address]account` to the `eth_call` API in order for the caller to  can customize the state.
This commit is contained in:
gary rong
2021-04-21 15:21:22 +08:00
committed by GitHub
parent cc33398cef
commit dd9c3225cf
3 changed files with 226 additions and 21 deletions

View File

@ -161,6 +161,16 @@ type TraceConfig struct {
Reexec *uint64
}
// TraceCallConfig is the config for traceCall API. It holds one more
// field to override the state for tracing.
type TraceCallConfig struct {
*vm.LogConfig
Tracer *string
Timeout *string
Reexec *uint64
StateOverrides *ethapi.StateOverride
}
// StdTraceConfig holds extra parameters to standard-json trace functions.
type StdTraceConfig struct {
vm.LogConfig
@ -720,7 +730,7 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
// created during the execution of EVM if the given transaction was added on
// top of the provided block and returns them as a JSON object.
// You can provide -2 as a block number to trace on top of the pending block.
func (api *API) TraceCall(ctx context.Context, args ethapi.CallArgs, blockNrOrHash rpc.BlockNumberOrHash, config *TraceConfig) (interface{}, error) {
func (api *API) TraceCall(ctx context.Context, args ethapi.CallArgs, blockNrOrHash rpc.BlockNumberOrHash, config *TraceCallConfig) (interface{}, error) {
// Try to retrieve the specified block
var (
err error
@ -730,6 +740,8 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.CallArgs, blockNrOrHa
block, err = api.blockByHash(ctx, hash)
} else if number, ok := blockNrOrHash.Number(); ok {
block, err = api.blockByNumber(ctx, number)
} else {
return nil, errors.New("invalid arguments; neither block nor hash specified")
}
if err != nil {
return nil, err
@ -743,11 +755,26 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.CallArgs, blockNrOrHa
if err != nil {
return nil, err
}
// Apply the customized state rules if required.
if config != nil {
if err := config.StateOverrides.Apply(statedb); err != nil {
return nil, err
}
}
// Execute the trace
msg := args.ToMessage(api.backend.RPCGasCap())
vmctx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
return api.traceTx(ctx, msg, new(txTraceContext), vmctx, statedb, config)
var traceConfig *TraceConfig
if config != nil {
traceConfig = &TraceConfig{
LogConfig: config.LogConfig,
Tracer: config.Tracer,
Timeout: config.Timeout,
Reexec: config.Reexec,
}
}
return api.traceTx(ctx, msg, new(txTraceContext), vmctx, statedb, traceConfig)
}
// traceTx configures a new tracer according to the provided configuration, and
@ -797,7 +824,7 @@ func (api *API) traceTx(ctx context.Context, message core.Message, txctx *txTrac
result, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()))
if err != nil {
return nil, fmt.Errorf("tracing failed: %v", err)
return nil, fmt.Errorf("tracing failed: %w", err)
}
// Depending on the tracer type, format and return the output.