Every tracer that implements Stop/GetResult held a `reason error`
field that is written by Stop (called from the trace-timeout watchdog
goroutine in api.go) and read by GetResult (called by the RPC handler
main goroutine). These accesses were unsynchronized.
Because Go's error is an interface, a racing reader can observe a
torn eface (type pointer and data pointer from different stores),
which is undefined behaviour and can crash the node.
Replace the plain field with atomic.Pointer[error] in:
- eth/tracers/native/call.go (callTracer)
- eth/tracers/native/4byte.go (fourByteTracer)
- eth/tracers/native/erc7562.go (erc7562Tracer)
- eth/tracers/native/prestate.go (prestateTracer)
- eth/tracers/logger/logger.go (StructLogger)
The flatCallTracer shares callTracer.reason and is fixed transitively.
Add TestTracerStopRace which exercises the concurrent Stop/GetResult
path under -race for each of the five tracers. It fails on master
with the race detector, passes after the fix.
This PR introduces a new native tracer for AA bundlers. Bundlers participating in the alternative
mempool will need to validate userops. This tracer will return sufficient information for them to
decide whether griefing is possible. Resolves#30546
---------
Co-authored-by: Sina M <1591639+s1na@users.noreply.github.com>