Skip to content

Trace locally-built derivation blocks in Firehose#7

Merged
sduchesneau merged 4 commits into
firehose/2.xfrom
firehose/trace-built-blocks
Jul 2, 2026
Merged

Trace locally-built derivation blocks in Firehose#7
sduchesneau merged 4 commits into
firehose/2.xfrom
firehose/trace-built-blocks

Conversation

@sduchesneau

Copy link
Copy Markdown

Problem

When op-reth catches up from an old snapshot, large ranges of blocks never emit a FIRE BLOCK. Root cause: op-node reconstructs the L1-derived (safe) chain by building each block via engine getPayload (no_tx_pool), which inserts it as canonical without going through the traced newPayload/validate_block_with_state path. The later newPayload for the same block short-circuits (already canonical), so it's never traced.

Only two surfaces were instrumented — the staged-sync batch_executor and the live engine validator. The payload-builder surface was not, so derivation-built blocks were invisible to Firehose. Live gossip→newPayload blocks trace fine, which is why only the catch-up range was missing.

This is OP-specific: vanilla L1 reth followers never rebuild canonical blocks via the payload builder.

Fix

  • New firehose_trace_built_block hook on ConfigurePostExecEvm, default no-op.
  • OpFirehoseEvmConfig overrides it: re-execute the frozen block through the existing OpChainHooks::execute_one_traced (same OpPostTxExtras/OpPreTxAdjust wrapping as the pipeline + engine paths -> byte-identical output), bracketed by a FirehoseBlockTracer.
  • Payload builder calls it after a Freeze, gated on is_tracer_initialized().

Properties

  • Re-execution confined to built (older, L1-derived) blocks; never the live gossip path.
  • No double-emit: the later newPayload for a built block short-circuits without re-execution.
  • Data parity: reuses the canonical tracing executor + OP hooks, not a divergent reimplementation.
  • Off by default: is_tracer_initialized() false => pure no-op; non-firehose/vanilla builds unaffected.

Scope

Optimism monorepo only; zero changes to the streamingfast/reth fork. The base repo needs a parallel change.

op-node reconstructs the L1-derived (safe) chain by building each block
via engine getPayload (no_tx_pool), which inserts it as canonical without
passing through the traced newPayload path. Those blocks never emitted a
FIRE BLOCK, leaving gaps whenever a node caught up from an old snapshot.

Add a firehose_trace_built_block hook on ConfigurePostExecEvm (default
no-op) that OpFirehoseEvmConfig overrides to re-execute the frozen block
through the existing OpChainHooks tracing executor, reusing the exact
OpPostTxExtras/OpPreTxAdjust wrapping as the pipeline and engine paths so
output is byte-identical. The payload builder calls it after a Freeze,
gated on is_tracer_initialized so non-firehose builds are unaffected.

Re-execution is confined to these built (older, derived) blocks and never
touches the live gossip newPayload path.
@sduchesneau sduchesneau requested a review from UlysseCorbeil July 2, 2026 19:16
@sduchesneau

Copy link
Copy Markdown
Author

Tested on unichain data over 20k blocks \o/

@sduchesneau sduchesneau requested a review from Copilot July 2, 2026 19:21

@UlysseCorbeil UlysseCorbeil left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@sduchesneau sduchesneau merged commit 36932a0 into firehose/2.x Jul 2, 2026
3 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses missing Firehose FIRE BLOCK emissions for OP derivation (no_tx_pool) blocks that are locally built via getPayload and inserted as canonical without traversing the traced newPayload path. It introduces a Firehose-specific hook in the OP EVM configuration and invokes it from the payload builder to re-execute and trace those locally-built blocks when the tracer is installed.

Changes:

  • Add a default no-op firehose_trace_built_block hook to ConfigurePostExecEvm, overridden by the Firehose EVM config to re-execute a built block through OpChainHooks::execute_one_traced.
  • Invoke the hook from the payload builder after a Freeze outcome for no_tx_pool builds, gated by reth_firehose::is_tracer_initialized().
  • Update the StreamingFast release workflow to remove branch-push builds, add build caching, and select the Docker build profile based on whether the ref is a tag.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
rust/op-reth/crates/payload/src/builder.rs Re-executes and traces no_tx_pool frozen payload blocks when Firehose tracing is active.
rust/op-reth/crates/payload/Cargo.toml Adds reth-firehose dependency for tracer initialization gating.
rust/op-reth/crates/firehose/src/evm_config.rs Implements the new Firehose tracing hook by running the block through the traced executor path.
rust/op-reth/crates/evm/src/post_exec_ext.rs Extends ConfigurePostExecEvm with a default no-op Firehose tracing hook.
rust/Cargo.lock Locks new transitive dependency inclusion (reth-firehose).
.github/workflows/sf-release.yml Adjusts triggers and build behavior; adds build caching and profile selection.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 130 to +136
build-args: |
VERSION=${{ steps.extract-version.outputs.VERSION }}
FIREHOSE_ETHEREUM=${{ inputs.firehose_ethereum || 'latest' }}
# Full LTO `maxperf` is only worth its ~19m link tail for shippable
# builds (tags); PRs and manual dispatch use `fast-build` (no LTO) to
# validate faster.
BUILD_PROFILE=${{ startsWith(github.ref, 'refs/tags/') && 'maxperf' || 'fast-build' }}
Comment on lines +314 to +317
if tracer.is_genesis() {
tracer.mark_verified();
return Ok(());
}
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