Skip to content

Implement callTracer withLog with receipt-aligned log index - #11342

Open
MysticRyuujin wants to merge 4 commits into
besu-eth:mainfrom
MysticRyuujin:calltracer-log-index
Open

MysticRyuujin wants to merge 4 commits into
besu-eth:mainfrom
MysticRyuujin:calltracer-log-index

Conversation

@MysticRyuujin

@MysticRyuujin MysticRyuujin commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

The callTracer ignored the withLog tracer option. Every frame came back without a logs array. This change implements it.

With withLog, each frame that emitted logs carries a logs array of {address, topics, data, position, index}. Frames that emitted no logs omit the key. Reverted frames and their descendants carry no logs. Without withLog the output is unchanged.

The field semantics follow the execution-apis spec change in ethereum/execution-apis#855. It defines index as: "The log's index within the block: the number of logs that took effect in the block before this one, counting the logs of all preceding transactions. It MUST equal the logIndex of the same log in the transaction receipt. Logs of reverted frames never take effect and do not consume an index, and onlyTopCall does not change the numbering. For debug_traceCall, where no receipt exists, numbering starts at zero for the traced call." position is the number of subcalls the frame had created when the log was emitted, so it is 0 under onlyTopCall.

Mechanism. CallTracer records new entries of frame.getLogs() after each opcode and at frame exit, so LOG opcodes and EIP-7708 transfer logs are both seen. At re-entry of a parent frame it skips the child logs the EVM merged in. buildResult matches the recorded logs by identity against TransactionProcessingResult.getLogs(), which holds only the logs that took effect, and assigns index from that order plus an offset. Logs that did not take effect are dropped. EIP-7708 closure logs, which MainnetTransactionProcessor adds to the initial frame after the root frame exits, go to the root frame, as in go-ethereum. The offset is the receipt log index offset for debug_traceTransaction, read only when withLog is set, the running count of preceding transaction logs in debug_traceBlock*, and 0 for debug_traceCall.

Hive rpc-compat with the spec branch fixtures, before: calltracer-with-log-index and calltracer-only-top-call-with-log fail (no logs key). After: both pass with index 0x3 and 0x2, and the existing calltracer-contract-call, calltracer-only-top-call, calltracer-simple-transfer, calltracer-revert-reason and calltracer-create fixtures stay green (9 of 9 including client launch).

Tests: CallTracerTest unit cases, and withLog spec fixtures in debug-geth/specs/call-tracer/with-log for blocks 0xf, 0x13, 0x19 and 0x22, including onlyTopCall and debug_traceTransaction. Every index in them equals the logIndex from eth_getBlockReceipts.

The other besu callTracer differences listed in ethereum/execution-apis#855 are out of scope. #11077 already fixed the root gasUsed, the DELEGATECALL from address and onlyTopCall. The block hash parameter of debug_traceCall is a separate change.

Signed-off-by: Chase Wright <chase.wright@ethereum.org>
@MysticRyuujin MysticRyuujin removed their assignment Sep 30, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants