Expand description
Trace data types and their wire-format serializers.
§Architecture
Capture, data, and output format are separated:
- Capture lives in
ethrex-levm(LevmOpcodeTracer, the dispatch-loop hook). It runs once per tx and produces aVec<OpcodeStep>plus the trailing metadata inOpcodeTraceResult. - Data are the bare structs
OpcodeStepandOpcodeTraceResultin this module. They carry noSerializeimpl — they’re consumer-agnostic. The same captured data feeds every downstream wire format. - Wire format is a newtype wrapper around one of those data structs with its
own
Serializeimpl. Two shapes coexist:StructLoggerStep/StructLoggerResult— the geth-RPCdebug_traceTransactionstructLogger shape:opas string mnemonic, noopName, decimalgas, etc. Used by the RPC handler and matches what every major client (geth, besu, …) emits from this endpoint. Consumers: Blockscout, Foundry, Tenderly, anything readingdebug_traceTransaction.Eip3155Step— strict EIP-3155 shape: numericopbyte + separateopName,"0xN"hexgas/gasCost/refund,stack:[](never null) when disabled. Used by streaming sinks that want spec-conformant per-step JSONL — e.g. theef-tests-statev2 statetestsubcommand feeding goevmlab.
Adding a third format (Parity-style flat call, opcode-count tracers, …) means another
newtype with its own Serialize impl. No changes to the data types or capture layer.
§Why not match geth-RPC everywhere
debug_traceTransaction predates EIP-3155 by years and its de-facto shape diverges
from the spec on three points: op is a string, opName is absent, and gas/gasCost
are decimal numbers instead of "0xN" hex strings. Every major client matches geth’s
shape there for tooling compat, not EIP-3155. So:
- RPC consumer expects structLogger → use
StructLoggerStep/StructLoggerResult. - EIP-3155-conformant CLI consumer (goevmlab, fuzzers) → use
Eip3155Step.
Structs§
- CallLog
- Call
Trace Frame - Trace of each call frame as defined in geth’s
callTraceroutput https://geth.ethereum.org/docs/developers/evm-tracing/built-in-tracers#call-tracer - Eip3155
Step - Wraps an
OpcodeStepto serialize in strict EIP-3155 shape. See module-level docs and the comment above this type for the field-shape choices. - Memory
Chunk - A 32-byte chunk of EVM memory, serialized as
"0x" + 64 lowercase hex chars. The caller zero-pads the last partial chunk before constructing this type. - Opcode
Step - Per-opcode trace entry — pure data, no
Serializeimpl. - Opcode
Trace Result - Top-level result of one opcode-traced transaction — pure data, no
Serializeimpl. - PrePost
State - Per-transaction prestate trace (diff mode). Contains the pre-tx and post-tx state for all touched accounts.
- Prestate
Account State - Per-account state entry emitted by the prestateTracer.
- Struct
Logger Emit - Controls which always-populated per-step fields the structLogger wire format emits.
- Struct
Logger Result - Wraps an
OpcodeTraceResultto serialize as the geth-RPCdebug_traceTransactionresponse:{failed, gas, returnValue, structLogs: [...]}. Each step insidestructLogsis itself serialized viaStructLoggerStepusing the sameemitflags. - Struct
Logger Step - Wraps an
OpcodeStepto serialize in the geth-RPCstructLoggershape used bydebug_traceTransaction. See module-level docs and the comment above this type for the field-shape divergences from EIP-3155.
Enums§
- Call
Type - Prestate
Result - Result of a prestateTracer execution — either a plain prestate map or a diff.
Functions§
- geth_
uint256_ hex - Converts a
U256to geth’suint256.Int.Hex()form:"0x"followed by lowercase hex with leading zeros stripped. Zero →"0x0"(not"0x"). - opcode_
name - Returns the opcode mnemonic for
byte.
Type Aliases§
- Call
Trace - Collection of traces of each call frame as defined in geth’s
callTraceroutput https://geth.ethereum.org/docs/developers/evm-tracing/built-in-tracers#call-tracer - Prestate
Trace - Per-transaction prestate trace (non-diff mode).
BTreeMapkeeps JSON output deterministic via sorted keys.