diff --git a/eth/tracers/native/call_flat.go b/eth/tracers/native/call_flat.go index fd5f820af1..68cdb3749c 100644 --- a/eth/tracers/native/call_flat.go +++ b/eth/tracers/native/call_flat.go @@ -23,6 +23,7 @@ import ( "math/big" "slices" "strings" + "sync/atomic" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -115,6 +116,7 @@ type flatCallTracer struct { config flatCallTracerConfig ctx *tracers.Context // Holds tracer context data reason error // Textual reason for the interruption + interrupt atomic.Bool // Atomic flag to signal execution interruption activePrecompiles []common.Address // Updated on tx start based on given rules } @@ -169,6 +171,9 @@ func (t *flatCallTracer) OnEnter(depth int, typ byte, from common.Address, to co // OnExit is called when EVM exits a scope, even if the scope didn't // execute any code. func (t *flatCallTracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) { + if t.interrupt.Load() { + return + } t.tracer.OnExit(depth, output, gasUsed, err, reverted) if depth == 0 { @@ -194,6 +199,9 @@ func (t *flatCallTracer) OnExit(depth int, output []byte, gasUsed uint64, err er } func (t *flatCallTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { + if t.interrupt.Load() { + return + } t.tracer.OnTxStart(env, tx, from) // Update list of precompiles based on current block rules := env.ChainConfig.Rules(env.BlockNumber, env.Random != nil, env.Time) @@ -201,6 +209,9 @@ func (t *flatCallTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction } func (t *flatCallTracer) OnTxEnd(receipt *types.Receipt, err error) { + if t.interrupt.Load() { + return + } t.tracer.OnTxEnd(receipt, err) } @@ -225,7 +236,7 @@ func (t *flatCallTracer) GetResult() (json.RawMessage, error) { // Stop terminates execution of the tracer at the first opportune moment. func (t *flatCallTracer) Stop(err error) { t.reason = err - t.tracer.Stop(err) + t.interrupt.Store(true) } // isPrecompiled returns whether the addr is a precompile. diff --git a/eth/tracers/native/call_flat_test.go b/eth/tracers/native/call_flat_test.go index c13ad4e349..94d360877c 100644 --- a/eth/tracers/native/call_flat_test.go +++ b/eth/tracers/native/call_flat_test.go @@ -1,7 +1,6 @@ package native_test import ( - "encoding/json" "errors" "math/big" "testing" @@ -16,17 +15,21 @@ import ( ) func TestCallFlatStop(t *testing.T) { - - ctx := &tracers.Context{} - - tracer, err := tracers.DefaultDirectory.New("flatCallTracer", ctx, json.RawMessage(`{}`)) + tracer, err := tracers.DefaultDirectory.New("flatCallTracer", &tracers.Context{}, nil) require.NoError(t, err) // this error should be returned by GetResult stopError := errors.New("stop error") // simulate a transaction - tx := types.NewTransaction(0, common.Address{}, big.NewInt(0), 0, big.NewInt(0), nil) + tx := types.NewTx(&types.LegacyTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(0), + Gas: 0, + GasPrice: big.NewInt(0), + Data: nil, + }) tracer.OnTxStart(&tracing.VMContext{ ChainConfig: params.MainnetChainConfig,