Could you elaborate on what a ‘"counter factual” trace responses’ would be? Would eth_simulate satisfy this? (look in the recurring calls, they occurs every week on Mondays)
With EOF seemingly dead in the water I wanted to bring attention back to this EIP, mostly in the form of getting eyes on a PR in the execution-apis repo trying to standardize the opcode tracer.
main ← MysticRyuujin:opcode-tracer-spec
opened 11:17PM - 03 Mar 26 UTC
Note: PR is in draft to gather feedback, and so I can continue testing go-ethere… um via rpctestgen
## Summary
This PR adds OpenRPC method and schema definitions for:
- `debug_traceTransaction`
- `debug_traceBlockByNumber`
Scope is intentionally limited to the default opcode (struct) logger output, while still allowing named tracers through `TraceConfig.tracer`.
The design goal is:
- strict where behavior is semantically important (`error`, `storage`, `returnValue`, types)
- concrete where implementations diverge (`stack` compact quantity form)
- explicit about what is out of scope (named tracer result schemas)
## Why now
`debug_traceTransaction` and `debug_traceBlockByNumber` are widely used by indexers,
debuggers, and client-compat test suites, but their default opcode tracer
output has remained under-specified. That creates avoidable client divergence and
integration complexity.
This PR turns observed behavior into a concrete interoperable contract:
- define exact field presence/absence rules
- define exact encoding rules for stack/memory/storage/return data
- preserve named-tracer support while explicitly scoping named-tracer output schemas
This work builds on prior debug-namespace standardization interest:
- PR #247 (merged): standardized non-trace debug methods
- PR #464 (merged): improved debug examples
- PR #728 (closed): prior trace standardization/testing attempt
- ethPandaOps cross-client investigation: <https://investigations.ethpandaops.io/2026-01/trace-comparisons/>
## Files changed
### `src/schemas/opcode-tracer.yaml` (new)
- Adds `TraceConfig`, `StructLog`, `OpcodeTransactionTrace`, `OpcodeBlockTransactionTrace`
- Stack is compact `uint256` (e.g. `0xd`)
- Memory is `bytes32[]` and absent when disabled
- Storage keys/values are `bytes32` and storage is scoped to `SLOAD`/`SSTORE`
- `refund` remains MUST/SHOULD normative
### `src/debug/trace.yaml` (new)
- Adds `debug_traceTransaction` and `debug_traceBlockByNumber`
- Includes opcode-tracer and named-tracer examples
### `tools/testgen/generators_debug_trace.go` (new)
- Adds 9 cases:
- `debug_traceTransaction/trace-legacy-transfer` (SpecOnly)
- `debug_traceTransaction/trace-contract-call` (SpecOnly)
- `debug_traceTransaction/trace-unknown-tx` (Recorded)
- `debug_traceBlockByNumber/trace-block-with-transactions` (SpecOnly)
- `debug_traceBlockByNumber/trace-block-memory-encoding` (SpecOnly)
- `debug_traceBlockByNumber/trace-block-storage-encoding` (SpecOnly)
- `debug_traceBlockByNumber/trace-block-return-data-behavior` (SpecOnly)
- `debug_traceBlockByNumber/trace-genesis` (Recorded)
- `debug_traceBlockByNumber/trace-block-invalid-number` (Recorded)
- `SpecOnly` means schema/rule validation only, not byte-for-byte fixture matching
Why most are `SpecOnly`:
- trace payloads are large and include implementation-dependent details outside this
PR's intended normalization scope
- for cross-client compatibility, these tests should enforce the spec contract,
not geth byte-for-byte formatting
- exact byte-for-byte tests are still used where they are unambiguous and valuable
(`trace-unknown-tx`, `trace-genesis`, `trace-block-invalid-number`)
Should we want to move away from SpecOnly tests, we'd need to tighten remaining flexible parts of the spec (for example `SHOULD` rules and implementation-dependent response details) into deterministic `MUST` requirements.
### `tools/testgen/generators.go` (modified)
- Registers `DebugTraceTransaction` and `DebugTraceBlockByNumber` in `AllMethods`
## Current geth state (`make fill`)
`make fill` was run against current go-ethereum.
- 7 of 9 debug trace fixtures generate successfully
- 2 fail with concrete spec mismatches:
- `debug_traceBlockByNumber/trace-block-memory-encoding`
- `debug_traceBlockByNumber/trace-block-storage-encoding`
### Confirmed mismatch `#1`: memory encoding
For block `0x1` with `enableMemory=true`, geth emits memory chunks without `0x` prefix.
Spec requires memory chunks to be `bytes32` (`0x`-prefixed 32-byte hex).
```text
structLogs[7]: memory[0] must be 0x-prefixed 32-byte hex (got "6000438152602001468152602001418152602001488152602001448152602001")
```
### Confirmed mismatch `#2`: storage encoding
For block `0x2` with storage capture enabled, geth emits storage keys/values without `0x` prefix.
Spec requires storage keys and values to be `bytes32` (`0x`-prefixed 32-byte hex).
## What still passes
- stack values are compact `0x` quantities (`0xd`, `0x0`, ...)
- empty top-level `returnValue` is `"0x"` for transfer case
- EOA transfer has `structLogs: []`
- genesis trace request returns error
- invalid block-number format returns invalid params
- block trace entries include `txHash` and `result`
- `returnData` field is absent when `enableReturnData=false` and valid hex when present with `enableReturnData=true`
## Coverage still incomplete
Current chain coverage still does not fully prove:
- `refund` presence when non-zero
- storage snapshot timing semantics across broader opcode patterns
- revert-path variants where some clients historically emitted `error: ""`
## Build/validation status
- `make build`: pass
- `make fill`: fails due to the two focused encoding tests above
- `go test ./testgen/...` (from `tools/`): pass (`[no test files]`)
## Assumptions for other clients
From the [ethPandaOps trace comparison investigation](https://investigations.ethpandaops.io/2026-01/trace-comparisons/) (assumptions, not validated here):
- Erigon: broadly geth-like trace shape/behavior
- Besu: most divergent for encoding and field presence
- Nethermind: verbose null/empty-field behavior and storage timing differences
- Reth: generally close with some conditional field/timing differences
## Likely client changes for buy-in
Based on the [ethPandaOps trace comparison investigation](https://investigations.ethpandaops.io/2026-01/trace-comparisons/) plus the focused geth fixtures:
| Client | Likely changes to align |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Geth | add `0x` prefix to memory chunks when `enableMemory=true`; add `0x` prefix to storage keys/values |
| Erigon | likely low-risk alignment; verify stack/memory/storage encodings and `txHash` behavior in block traces |
| Besu | normalize stack type to string array, normalize memory/storage to 0x-prefixed bytes32 where required, align storage population scope, align return value and error field conventions |
| Nethermind | omit `error`/`storage` when empty where required, align storage snapshot timing, align refund behavior where applicable |
| Reth | align `returnData` gating to `enableReturnData`, verify storage timing/encoding consistency against the spec |
The table above is a concrete negotiation starting point for client teams; exact
implementation tickets should still be validated against each client's latest behavior.
There are a handful of questions in the PR about aligning it more with this EIP, and I’d be curious to get input on if some of the changes to the status quo are required, or worth the effort of introducing additional breaking changes.
It’s not seemingly dead in the water, it’s just plain old dead.
While working through the EOF tracing I did come through some of these issues. The fuzzing framework Marius built hedges around some of these differences but I think they should be normalized and it’s mostly a question of getting some formatting changes done. Some issues are deeper, like memory sizing in Nethermind if I remember correctly. But golden tests I think would be an incentive for clients to converge.
Because these APIs originated with Geth, there is a strong case to make their output the golden master.