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

eth/tracers: use atomic type #27031

Merged
merged 7 commits into from
Apr 4, 2023
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
16 changes: 9 additions & 7 deletions eth/tracers/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -835,8 +835,8 @@ func TestTraceChain(t *testing.T) {
signer := types.HomesteadSigner{}

var (
ref uint32 // total refs has made
rel uint32 // total rels has made
ref atomic.Uint32 // total refs has made
rel atomic.Uint32 // total rels has made
nonce uint64
)
backend := newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
Expand All @@ -849,8 +849,8 @@ func TestTraceChain(t *testing.T) {
nonce += 1
}
})
backend.refHook = func() { atomic.AddUint32(&ref, 1) }
backend.relHook = func() { atomic.AddUint32(&rel, 1) }
backend.refHook = func() { ref.Add(1) }
backend.relHook = func() { rel.Add(1) }
api := NewAPI(backend)

single := `{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}`
Expand All @@ -863,7 +863,8 @@ func TestTraceChain(t *testing.T) {
{10, 20, nil}, // the middle chain range, blocks [11, 20]
}
for _, c := range cases {
ref, rel = 0, 0 // clean up the counters
ref.Store(0)
rel.Store(0)

from, _ := api.blockByNumber(context.Background(), rpc.BlockNumber(c.start))
to, _ := api.blockByNumber(context.Background(), rpc.BlockNumber(c.end))
Expand All @@ -888,8 +889,9 @@ func TestTraceChain(t *testing.T) {
if next != c.end+1 {
t.Error("Missing tracing block")
}
if ref != rel {
t.Errorf("Ref and deref actions are not equal, ref %d rel %d", ref, rel)

if nref, nrel := ref.Load(), rel.Load(); nref != nrel {
t.Errorf("Ref and deref actions are not equal, ref %d rel %d", nref, nrel)
}
}
}
8 changes: 4 additions & 4 deletions eth/tracers/logger/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ type StructLogger struct {
gasLimit uint64
usedGas uint64

interrupt uint32 // Atomic flag to signal execution interruption
reason error // Textual reason for the interruption
interrupt atomic.Bool // Atomic flag to signal execution interruption
reason error // Textual reason for the interruption
}

// NewStructLogger returns a new logger
Expand Down Expand Up @@ -149,7 +149,7 @@ func (l *StructLogger) CaptureStart(env *vm.EVM, from common.Address, to common.
// CaptureState also tracks SLOAD/SSTORE ops to track storage change.
func (l *StructLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
// If tracing was interrupted, set the error and stop
if atomic.LoadUint32(&l.interrupt) > 0 {
if l.interrupt.Load() {
return
}
// check if already accumulated the specified number of logs
Expand Down Expand Up @@ -258,7 +258,7 @@ func (l *StructLogger) GetResult() (json.RawMessage, error) {
// Stop terminates execution of the tracer at the first opportune moment.
func (l *StructLogger) Stop(err error) {
l.reason = err
atomic.StoreUint32(&l.interrupt, 1)
l.interrupt.Store(true)
}

func (l *StructLogger) CaptureTxStart(gasLimit uint64) {
Expand Down
6 changes: 3 additions & 3 deletions eth/tracers/native/4byte.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func init() {
type fourByteTracer struct {
noopTracer
ids map[string]int // ids aggregates the 4byte ids found
interrupt uint32 // Atomic flag to signal execution interruption
interrupt atomic.Bool // Atomic flag to signal execution interruption
reason error // Textual reason for the interruption
activePrecompiles []common.Address // Updated on CaptureStart based on given rules
}
Expand Down Expand Up @@ -93,7 +93,7 @@ func (t *fourByteTracer) CaptureStart(env *vm.EVM, from common.Address, to commo
// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
func (t *fourByteTracer) CaptureEnter(op vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
// Skip if tracing was interrupted
if atomic.LoadUint32(&t.interrupt) > 0 {
if t.interrupt.Load() {
return
}
if len(input) < 4 {
Expand Down Expand Up @@ -124,7 +124,7 @@ func (t *fourByteTracer) GetResult() (json.RawMessage, error) {
// Stop terminates execution of the tracer at the first opportune moment.
func (t *fourByteTracer) Stop(err error) {
t.reason = err
atomic.StoreUint32(&t.interrupt, 1)
t.interrupt.Store(true)
}

func bytesToHex(s []byte) string {
Expand Down
10 changes: 5 additions & 5 deletions eth/tracers/native/call.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ type callTracer struct {
callstack []callFrame
config callTracerConfig
gasLimit uint64
interrupt uint32 // Atomic flag to signal execution interruption
reason error // Textual reason for the interruption
interrupt atomic.Bool // Atomic flag to signal execution interruption
reason error // Textual reason for the interruption
}

type callTracerConfig struct {
Expand Down Expand Up @@ -161,7 +161,7 @@ func (t *callTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, sco
return
}
// Skip if tracing was interrupted
if atomic.LoadUint32(&t.interrupt) > 0 {
if t.interrupt.Load() {
return
}
switch op {
Expand Down Expand Up @@ -197,7 +197,7 @@ func (t *callTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.
return
}
// Skip if tracing was interrupted
if atomic.LoadUint32(&t.interrupt) > 0 {
if t.interrupt.Load() {
return
}

Expand Down Expand Up @@ -262,7 +262,7 @@ func (t *callTracer) GetResult() (json.RawMessage, error) {
// Stop terminates execution of the tracer at the first opportune moment.
func (t *callTracer) Stop(err error) {
t.reason = err
atomic.StoreUint32(&t.interrupt, 1)
t.interrupt.Store(true)
}

// clearFailedLogs clears the logs of a callframe and all its children
Expand Down
10 changes: 7 additions & 3 deletions eth/tracers/native/prestate.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ type prestateTracer struct {
to common.Address
gasLimit uint64 // Amount of gas bought for the whole tx
config prestateTracerConfig
interrupt uint32 // Atomic flag to signal execution interruption
reason error // Textual reason for the interruption
interrupt atomic.Bool // Atomic flag to signal execution interruption
reason error // Textual reason for the interruption
created map[common.Address]bool
deleted map[common.Address]bool
}
Expand Down Expand Up @@ -136,6 +136,10 @@ func (t *prestateTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64,
if err != nil {
return
}
// Skip if tracing was interrupted
if t.interrupt.Load() {
return
}
stack := scope.Stack
stackData := stack.Data()
stackLen := len(stackData)
Expand Down Expand Up @@ -259,7 +263,7 @@ func (t *prestateTracer) GetResult() (json.RawMessage, error) {
// Stop terminates execution of the tracer at the first opportune moment.
func (t *prestateTracer) Stop(err error) {
t.reason = err
atomic.StoreUint32(&t.interrupt, 1)
t.interrupt.Store(true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realized through your PR that prestateTracer is ignoring the interrupt signal sort of. It has to check for interrupts in CaptureState. I'd be grateful if you add it in this PR, but don't feel obliged.

}

// lookupAccount fetches details of an account and adds it to the prestate
Expand Down