Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NIT-2437] Cherry-pick flat call tracer stopping bug #310

Merged
merged 1 commit into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions eth/tracers/native/call_flat.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"fmt"
"math/big"
"strings"
"sync/atomic"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
Expand Down Expand Up @@ -119,7 +120,7 @@ type flatCallTracer struct {
tracer *callTracer
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 CaptureStart based on given rules
}

Expand Down Expand Up @@ -159,6 +160,9 @@ func newFlatCallTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Trace

// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
func (t *flatCallTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
if t.interrupt.Load() {
return
}
t.tracer.CaptureStart(env, from, to, create, input, gas, value)
// Update list of precompiles based on current block
rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time, env.Context.ArbOSVersion)
Expand All @@ -167,21 +171,33 @@ func (t *flatCallTracer) CaptureStart(env *vm.EVM, from common.Address, to commo

// CaptureEnd is called after the call finishes to finalize the tracing.
func (t *flatCallTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
if t.interrupt.Load() {
return
}
t.tracer.CaptureEnd(output, gasUsed, err)
}

// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
func (t *flatCallTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
if t.interrupt.Load() {
return
}
t.tracer.CaptureState(pc, op, gas, cost, scope, rData, depth, err)
}

// CaptureFault implements the EVMLogger interface to trace an execution fault.
func (t *flatCallTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
if t.interrupt.Load() {
return
}
t.tracer.CaptureFault(pc, op, gas, cost, scope, depth, err)
}

// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
func (t *flatCallTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
if t.interrupt.Load() {
return
}
t.tracer.CaptureEnter(typ, from, to, input, gas, value)

// Child calls must have a value, even if it's zero.
Expand All @@ -194,6 +210,9 @@ func (t *flatCallTracer) CaptureEnter(typ vm.OpCode, from common.Address, to com
// CaptureExit is called when EVM exits a scope, even if the scope didn't
// execute any code.
func (t *flatCallTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
if t.interrupt.Load() {
return
}
t.tracer.CaptureExit(output, gasUsed, err)

// Parity traces don't include CALL/STATICCALLs to precompiles.
Expand All @@ -216,10 +235,16 @@ func (t *flatCallTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
}

func (t *flatCallTracer) CaptureTxStart(gasLimit uint64) {
if t.interrupt.Load() {
return
}
t.tracer.CaptureTxStart(gasLimit)
}

func (t *flatCallTracer) CaptureTxEnd(restGas uint64) {
if t.interrupt.Load() {
return
}
t.tracer.CaptureTxEnd(restGas)
}

Expand All @@ -243,12 +268,13 @@ func (t *flatCallTracer) GetResult() (json.RawMessage, error) {
if err != nil {
return nil, err
}
return res, t.reason
return res, t.tracer.reason
}

// Stop terminates execution of the tracer at the first opportune moment.
func (t *flatCallTracer) Stop(err error) {
t.tracer.Stop(err)
t.interrupt.Store(true)
}

// isPrecompiled returns whether the addr is a precompile.
Expand Down
3 changes: 3 additions & 0 deletions eth/tracers/native/tracer_arbitrum.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ func (*noopTracer) CaptureArbitrumTransfer(env *vm.EVM, from, to *common.Address
func (*prestateTracer) CaptureArbitrumTransfer(env *vm.EVM, from, to *common.Address, value *big.Int, before bool, purpose string) {
}
func (t *flatCallTracer) CaptureArbitrumTransfer(env *vm.EVM, from, to *common.Address, value *big.Int, before bool, purpose string) {
if t.interrupt.Load() {
return
}
transfer := arbitrumTransfer{
Purpose: purpose,
Value: bigToHex(value),
Expand Down
Loading