mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-02-26 07:37:20 +00:00
eth/tracers: fix precompile move feat for debug_traceCall (#31348)
`debug_traceCall` was ignoring the override `movePrecompileToAddress`. Now it is at feature-parity with eth_call.
This commit is contained in:
parent
d85f796356
commit
40ad6bedf6
2 changed files with 58 additions and 11 deletions
|
|
@ -279,7 +279,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
|
|||
TxIndex: i,
|
||||
TxHash: tx.Hash(),
|
||||
}
|
||||
res, err := api.traceTx(ctx, tx, msg, txctx, blockCtx, task.statedb, config)
|
||||
res, err := api.traceTx(ctx, tx, msg, txctx, blockCtx, task.statedb, config, nil)
|
||||
if err != nil {
|
||||
task.results[i] = &txTraceResult{TxHash: tx.Hash(), Error: err.Error()}
|
||||
log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err)
|
||||
|
|
@ -632,7 +632,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
|
|||
TxIndex: i,
|
||||
TxHash: tx.Hash(),
|
||||
}
|
||||
res, err := api.traceTx(ctx, tx, msg, txctx, blockCtx, statedb, config)
|
||||
res, err := api.traceTx(ctx, tx, msg, txctx, blockCtx, statedb, config, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -676,7 +676,7 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
|
|||
// concurrent use.
|
||||
// See: https://github.com/ethereum/go-ethereum/issues/29114
|
||||
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
||||
res, err := api.traceTx(ctx, txs[task.index], msg, txctx, blockCtx, task.statedb, config)
|
||||
res, err := api.traceTx(ctx, txs[task.index], msg, txctx, blockCtx, task.statedb, config, nil)
|
||||
if err != nil {
|
||||
results[task.index] = &txTraceResult{TxHash: txs[task.index].Hash(), Error: err.Error()}
|
||||
continue
|
||||
|
|
@ -894,7 +894,7 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
|
|||
TxIndex: int(index),
|
||||
TxHash: hash,
|
||||
}
|
||||
return api.traceTx(ctx, tx, msg, txctx, vmctx, statedb, config)
|
||||
return api.traceTx(ctx, tx, msg, txctx, vmctx, statedb, config, nil)
|
||||
}
|
||||
|
||||
// TraceCall lets you trace a given eth_call. It collects the structured logs
|
||||
|
|
@ -907,10 +907,11 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
|
|||
func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, config *TraceCallConfig) (interface{}, error) {
|
||||
// Try to retrieve the specified block
|
||||
var (
|
||||
err error
|
||||
block *types.Block
|
||||
statedb *state.StateDB
|
||||
release StateReleaseFunc
|
||||
err error
|
||||
block *types.Block
|
||||
statedb *state.StateDB
|
||||
release StateReleaseFunc
|
||||
precompiles vm.PrecompiledContracts
|
||||
)
|
||||
if hash, ok := blockNrOrHash.Hash(); ok {
|
||||
block, err = api.blockByHash(ctx, hash)
|
||||
|
|
@ -952,7 +953,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
|
|||
config.BlockOverrides.Apply(&vmctx)
|
||||
rules := api.backend.ChainConfig().Rules(vmctx.BlockNumber, vmctx.Random != nil, vmctx.Time)
|
||||
|
||||
precompiles := vm.ActivePrecompiledContracts(rules)
|
||||
precompiles = vm.ActivePrecompiledContracts(rules)
|
||||
if err := config.StateOverrides.Apply(statedb, precompiles); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -977,13 +978,13 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
|
|||
if config != nil {
|
||||
traceConfig = &config.TraceConfig
|
||||
}
|
||||
return api.traceTx(ctx, tx, msg, new(Context), vmctx, statedb, traceConfig)
|
||||
return api.traceTx(ctx, tx, msg, new(Context), vmctx, statedb, traceConfig, precompiles)
|
||||
}
|
||||
|
||||
// traceTx configures a new tracer according to the provided configuration, and
|
||||
// executes the given message in the provided environment. The return value will
|
||||
// be tracer dependent.
|
||||
func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) {
|
||||
func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig, precompiles vm.PrecompiledContracts) (interface{}, error) {
|
||||
var (
|
||||
tracer *Tracer
|
||||
err error
|
||||
|
|
@ -1009,6 +1010,9 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
|
|||
}
|
||||
tracingStateDB := state.NewHookedState(statedb, tracer.Hooks)
|
||||
evm := vm.NewEVM(vmctx, tracingStateDB, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true})
|
||||
if precompiles != nil {
|
||||
evm.SetPrecompiles(precompiles)
|
||||
}
|
||||
|
||||
// Define a meaningful timeout of a single transaction trace
|
||||
if config.Timeout != nil {
|
||||
|
|
|
|||
|
|
@ -642,6 +642,7 @@ func TestTracingWithOverrides(t *testing.T) {
|
|||
t.Parallel()
|
||||
// Initialize test accounts
|
||||
accounts := newAccounts(3)
|
||||
ecRecoverAddress := common.HexToAddress("0x0000000000000000000000000000000000000001")
|
||||
storageAccount := common.Address{0x13, 37}
|
||||
genesis := &core.Genesis{
|
||||
Config: params.TestChainConfig,
|
||||
|
|
@ -940,6 +941,48 @@ func TestTracingWithOverrides(t *testing.T) {
|
|||
},
|
||||
want: `{"gas":25288,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000055"}`,
|
||||
},
|
||||
{ // Call to precompile ECREC (0x01), but code was modified to add 1 to input
|
||||
blockNumber: rpc.LatestBlockNumber,
|
||||
call: ethapi.TransactionArgs{
|
||||
From: &randomAccounts[0].addr,
|
||||
To: &ecRecoverAddress,
|
||||
Data: newRPCBytes(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")),
|
||||
},
|
||||
config: &TraceCallConfig{
|
||||
StateOverrides: &override.StateOverride{
|
||||
randomAccounts[0].addr: override.OverrideAccount{
|
||||
Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether))),
|
||||
},
|
||||
ecRecoverAddress: override.OverrideAccount{
|
||||
// The code below adds one to input
|
||||
Code: newRPCBytes(common.Hex2Bytes("60003560010160005260206000f3")),
|
||||
MovePrecompileTo: &randomAccounts[2].addr,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: `{"gas":21167,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000002"}`,
|
||||
},
|
||||
{ // Call to ECREC Precompiled on a different address, expect the original behaviour of ECREC precompile
|
||||
blockNumber: rpc.LatestBlockNumber,
|
||||
call: ethapi.TransactionArgs{
|
||||
From: &randomAccounts[0].addr,
|
||||
To: &randomAccounts[2].addr, // Moved EcRecover
|
||||
Data: newRPCBytes(common.Hex2Bytes("82f3df49d3645876de6313df2bbe9fbce593f21341a7b03acdb9423bc171fcc9000000000000000000000000000000000000000000000000000000000000001cba13918f50da910f2d55a7ea64cf716ba31dad91856f45908dde900530377d8a112d60f36900d18eb8f9d3b4f85a697b545085614509e3520e4b762e35d0d6bd")),
|
||||
},
|
||||
config: &TraceCallConfig{
|
||||
StateOverrides: &override.StateOverride{
|
||||
randomAccounts[0].addr: override.OverrideAccount{
|
||||
Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether))),
|
||||
},
|
||||
ecRecoverAddress: override.OverrideAccount{
|
||||
// The code below adds one to input
|
||||
Code: newRPCBytes(common.Hex2Bytes("60003560010160005260206000f3")),
|
||||
MovePrecompileTo: &randomAccounts[2].addr, // Move EcRecover to this address
|
||||
},
|
||||
},
|
||||
},
|
||||
want: `{"gas":25664,"failed":false,"returnValue":"000000000000000000000000c6e93f4c1920eaeaa1e699f76a7a8c18e3056074"}`,
|
||||
},
|
||||
}
|
||||
for i, tc := range testSuite {
|
||||
result, err := api.TraceCall(context.Background(), tc.call, rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, tc.config)
|
||||
|
|
|
|||
Loading…
Reference in a new issue