Skip to main content

Module tracing

Module tracing 

Source
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 a Vec<OpcodeStep> plus the trailing metadata in OpcodeTraceResult.
  • Data are the bare structs OpcodeStep and OpcodeTraceResult in this module. They carry no Serialize impl — 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 Serialize impl. Two shapes coexist:
    • StructLoggerStep / StructLoggerResult — the geth-RPC debug_traceTransaction structLogger shape: op as string mnemonic, no opName, decimal gas, etc. Used by the RPC handler and matches what every major client (geth, besu, …) emits from this endpoint. Consumers: Blockscout, Foundry, Tenderly, anything reading debug_traceTransaction.
    • Eip3155Step — strict EIP-3155 shape: numeric op byte + separate opName, "0xN" hex gas/gasCost/refund, stack:[] (never null) when disabled. Used by streaming sinks that want spec-conformant per-step JSONL — e.g. the ef-tests-statev2 statetest subcommand 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:

Structs§

CallLog
CallTraceFrame
Trace of each call frame as defined in geth’s callTracer output https://geth.ethereum.org/docs/developers/evm-tracing/built-in-tracers#call-tracer
Eip3155Step
Wraps an OpcodeStep to serialize in strict EIP-3155 shape. See module-level docs and the comment above this type for the field-shape choices.
MemoryChunk
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.
OpcodeStep
Per-opcode trace entry — pure data, no Serialize impl.
OpcodeTraceResult
Top-level result of one opcode-traced transaction — pure data, no Serialize impl.
PrePostState
Per-transaction prestate trace (diff mode). Contains the pre-tx and post-tx state for all touched accounts.
PrestateAccountState
Per-account state entry emitted by the prestateTracer.
StructLoggerEmit
Controls which always-populated per-step fields the structLogger wire format emits.
StructLoggerResult
Wraps an OpcodeTraceResult to serialize as the geth-RPC debug_traceTransaction response: {failed, gas, returnValue, structLogs: [...]}. Each step inside structLogs is itself serialized via StructLoggerStep using the same emit flags.
StructLoggerStep
Wraps an OpcodeStep to serialize in the geth-RPC structLogger shape used by debug_traceTransaction. See module-level docs and the comment above this type for the field-shape divergences from EIP-3155.

Enums§

CallType
PrestateResult
Result of a prestateTracer execution — either a plain prestate map or a diff.

Functions§

geth_uint256_hex
Converts a U256 to geth’s uint256.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§

CallTrace
Collection of traces of each call frame as defined in geth’s callTracer output https://geth.ethereum.org/docs/developers/evm-tracing/built-in-tracers#call-tracer
PrestateTrace
Per-transaction prestate trace (non-diff mode). BTreeMap keeps JSON output deterministic via sorted keys.