mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-07 23:48:36 +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,
|
TxIndex: i,
|
||||||
TxHash: tx.Hash(),
|
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 {
|
if err != nil {
|
||||||
task.results[i] = &txTraceResult{TxHash: tx.Hash(), Error: err.Error()}
|
task.results[i] = &txTraceResult{TxHash: tx.Hash(), Error: err.Error()}
|
||||||
log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err)
|
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,
|
TxIndex: i,
|
||||||
TxHash: tx.Hash(),
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -676,7 +676,7 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
|
||||||
// concurrent use.
|
// concurrent use.
|
||||||
// See: https://github.com/ethereum/go-ethereum/issues/29114
|
// See: https://github.com/ethereum/go-ethereum/issues/29114
|
||||||
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
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 {
|
if err != nil {
|
||||||
results[task.index] = &txTraceResult{TxHash: txs[task.index].Hash(), Error: err.Error()}
|
results[task.index] = &txTraceResult{TxHash: txs[task.index].Hash(), Error: err.Error()}
|
||||||
continue
|
continue
|
||||||
|
|
@ -894,7 +894,7 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
|
||||||
TxIndex: int(index),
|
TxIndex: int(index),
|
||||||
TxHash: hash,
|
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
|
// 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) {
|
func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, config *TraceCallConfig) (interface{}, error) {
|
||||||
// Try to retrieve the specified block
|
// Try to retrieve the specified block
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
block *types.Block
|
block *types.Block
|
||||||
statedb *state.StateDB
|
statedb *state.StateDB
|
||||||
release StateReleaseFunc
|
release StateReleaseFunc
|
||||||
|
precompiles vm.PrecompiledContracts
|
||||||
)
|
)
|
||||||
if hash, ok := blockNrOrHash.Hash(); ok {
|
if hash, ok := blockNrOrHash.Hash(); ok {
|
||||||
block, err = api.blockByHash(ctx, hash)
|
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)
|
config.BlockOverrides.Apply(&vmctx)
|
||||||
rules := api.backend.ChainConfig().Rules(vmctx.BlockNumber, vmctx.Random != nil, vmctx.Time)
|
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 {
|
if err := config.StateOverrides.Apply(statedb, precompiles); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -977,13 +978,13 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
|
||||||
if config != nil {
|
if config != nil {
|
||||||
traceConfig = &config.TraceConfig
|
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
|
// traceTx configures a new tracer according to the provided configuration, and
|
||||||
// executes the given message in the provided environment. The return value will
|
// executes the given message in the provided environment. The return value will
|
||||||
// be tracer dependent.
|
// 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 (
|
var (
|
||||||
tracer *Tracer
|
tracer *Tracer
|
||||||
err error
|
err error
|
||||||
|
|
@ -1009,6 +1010,9 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
|
||||||
}
|
}
|
||||||
tracingStateDB := state.NewHookedState(statedb, tracer.Hooks)
|
tracingStateDB := state.NewHookedState(statedb, tracer.Hooks)
|
||||||
evm := vm.NewEVM(vmctx, tracingStateDB, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true})
|
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
|
// Define a meaningful timeout of a single transaction trace
|
||||||
if config.Timeout != nil {
|
if config.Timeout != nil {
|
||||||
|
|
|
||||||
|
|
@ -642,6 +642,7 @@ func TestTracingWithOverrides(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
// Initialize test accounts
|
// Initialize test accounts
|
||||||
accounts := newAccounts(3)
|
accounts := newAccounts(3)
|
||||||
|
ecRecoverAddress := common.HexToAddress("0x0000000000000000000000000000000000000001")
|
||||||
storageAccount := common.Address{0x13, 37}
|
storageAccount := common.Address{0x13, 37}
|
||||||
genesis := &core.Genesis{
|
genesis := &core.Genesis{
|
||||||
Config: params.TestChainConfig,
|
Config: params.TestChainConfig,
|
||||||
|
|
@ -940,6 +941,48 @@ func TestTracingWithOverrides(t *testing.T) {
|
||||||
},
|
},
|
||||||
want: `{"gas":25288,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000055"}`,
|
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 {
|
for i, tc := range testSuite {
|
||||||
result, err := api.TraceCall(context.Background(), tc.call, rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, tc.config)
|
result, err := api.TraceCall(context.Background(), tc.call, rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, tc.config)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue