Skip to content

Update op-reth to v2.4.0 (no reth bump)#8

Open
maoueh wants to merge 41 commits into
firehose/2.xfrom
feature/update-to-op-reth-version-2-4-0
Open

Update op-reth to v2.4.0 (no reth bump)#8
maoueh wants to merge 41 commits into
firehose/2.xfrom
feature/update-to-op-reth-version-2-4-0

Conversation

@maoueh

@maoueh maoueh commented Jul 14, 2026

Copy link
Copy Markdown

Summary

Merges upstream op-reth/v2.4.0 into the Firehose branch (firehose/2.x).

No reth/revm/alloy version bump. Upstream's [workspace.dependencies] reth pins are byte-for-byte identical between op-reth/v2.3.3 and op-reth/v2.4.0 (still paradigmxyz/reth tag v2.3.0), so our streamingfast/reth v2.3.0-fh-2 already covers it — no new reth tag required.

The merge was conflict-free. Upstream's op-reth changes live in functions disjoint from the Firehose hooks, so tracing is untouched.

What's new in op-reth v2.4.0

Only 2 of 39 upstream commits touch rust/op-reth (rest is docs/CI/contracts/kona/op-node/op-deployer):

Firehose impact

None. The commit-hook change sits in execute_best_transactions, disjoint from firehose_trace_built_block (in the no_tx_pool branch of build_payload). Pool seams are opt-in and default to prior behavior. The crates/firehose/ crate is untouched upstream.

Verification

  • cargo check firehose + node + payload + txpool — PASSED
  • cargo test firehose + payload + txpool — 56 passed, 0 failed
  • cargo test -p reth-optimism-node --no-run (custom_pool + firehose wiring) — compiles
  • Battlefield reth tests — not run

Build note: reth-optimism-chainspec build.rs requires the superchain-registry submodule checked out.

Changelog

rust/op-reth/CHANGELOG.sf.md updated.

fakedev9999 and others added 30 commits June 26, 2026 17:06
alloy-provider's reqwest HTTP transport was force-enabled via workspace
inheritance, pulling reqwest/hyper/tokio(net)/mio/socket2 into every consumer.
The Optimism network marker and RecommendedFillers impl only need
transport-agnostic types, so make reqwest an opt-in feature (on by default to
preserve behavior).
* feat(contracts): add L2CM deploy mode for genesis

* chore(contracts): update L2CM snapshots

* feat(contracts): route L2 genesis proxy initialization through L2CM

* chore(contracts): lint

* fix(contracts): use deterministic l2cm address

* test(contracts): cover L2CM deploy-mode touched set across feature combos

* fix(contracts): replace the cheatcode with the plain CREATE2 derivation to fix breaking test in op-deployer

* test(contracts): test_run_l2cmInteropScheduledNotActive_succeeds tests all relevant forks

* fix(l2cmutil-test): fix testname issue

* docs(l2genesis): remove unneeded comment

* fix(l2genesis): extract repeated logic

* fix(l2genesis): fix the condition after the extraction

* fix(l2genesis): remove redundant check

* fix(l2genesis): remove unifinished test

* fix(l2cmutils): improve comment

Co-authored-by: Maurelian <john@oplabs.co>

* feat(l2genesis): rework the deploy path so it should be called with delegatecall

* fix(l2genesis): fix submodule issue after merge conflict

* fix(semver): add missing semver bump and regenerate bundle

* feat(deployutils): implement getDeployedCode to avoid using incorrect artifacts

* fix(l2genesis): assert the proxyadmin impl  was restored

---------

Co-authored-by: Maurelian <john@oplabs.co>
…lidation (ethereum-optimism#21587)

op-reth v2.3.2 added an unconditional history-expiry guard to recovered_block
(reth PR #24760), which eth_getBlockByNumber resolves through. On a pruned EL
whose lowest retained Transactions static-file jar starts above block 0, the
genesis block now returns RPC error 4444 ("pruned history unavailable") instead
of the block. This caused CL-sync op-node init to fail in CheckL2GenesisBlockHash
with "failed to get L2 genesis blockhash: ... pruned history unavailable".

The genesis block hash is fully determined by the rollup config, so when the EL
can no longer serve genesis — either NotFound or history-pruned — accept the
configured value rather than failing initialization, mirroring the existing
CheckL1GenesisBlockHash behavior.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…across compiler profiles (ethereum-optimism#21592)

The `_calculateTokenAddress` helper predicted the child token address using
`type(OptimismMintableERC20).creationCode`. Because the test's compilation unit
imports dispute-restricted contracts, that embedded subobject is compiled under
the "dispute" optimizer profile (5000 runs), while L2 genesis etches the factory
predeploy from the default-profile artifact (999999 runs). The two creation codes
differ, so the predicted CREATE2 address no longer matched the address the factory
actually deploys, breaking the `vm.expectEmit` checks in the three
`*_validParams_succeeds` fuzz tests.

Use `DeployUtils.getCode("OptimismMintableERC20")`, which pins the default-profile
artifact (the same code genesis uses), matching the pattern already used in
OptimismMintableERC721Factory.t.sol.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* fix(op-node): tolerate EL-expired genesis history during L2 config validation

op-reth v2.3.2 added an unconditional history-expiry guard to recovered_block
(reth PR #24760), which eth_getBlockByNumber resolves through. On a pruned EL
whose lowest retained Transactions static-file jar starts above block 0, the
genesis block now returns RPC error 4444 ("pruned history unavailable") instead
of the block. This caused CL-sync op-node init to fail in CheckL2GenesisBlockHash
with "failed to get L2 genesis blockhash: ... pruned history unavailable".

The genesis block hash is fully determined by the rollup config, so when the EL
can no longer serve genesis — either NotFound or history-pruned — accept the
configured value rather than failing initialization, mirroring the existing
CheckL1GenesisBlockHash behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: u19 notice page mentions op-reth v2.3.2

---------

Co-authored-by: Einar Rasmussen <einar@oplabs.co>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
…ereum-optimism#21581)

Add docs/ai/reth-update-review.md, a review guide for upstream
reth/revm/alloy dependency bumps. It targets the failure mode the generic
code/security review misses: an upstream change that should have forced a
change in our in-tree op- forks but produced no diff in our tree. Covers
the lockfile-delta scope funnel, a change-driven review approach, a risk
taxonomy organised by detection difficulty, succinct output, and an
all-severities triage/investigation handoff.

Add the reth-update-reviewer agent that executes the guide, and wire cross
references from UPDATING-RETH.md, rust-dev.md, the update-reth skill, and
the AGENTS.md doc index.
…hell script) (ethereum-optimism#21542)

* feat(op-challenger): add game-proposal-outputs subcommand

Replaces the op-challenger/scripts/game-proposal-outputs.sh shell+python
script with a native op-challenger subcommand. For each dispute game
(enumerated from the factory within the game window, or explicitly named
game addresses), it reports the output root our op-node derives at the
proposed L2 block and our node's safe head at the game's L1 head anchor,
with rootMatch / safeHeadAtOrAboveBlock flags. Supports text and json output.

This reuses the existing contract bindings, factory enumeration, and rollup
client already in op-challenger, removing the fragile hand-rolled eth_call
ABI decoding and JSON handling in the shell script (which had a result
serialization bug that made it non-functional).

Updates the dispute-game investigation docs and agent/skill references to
point at the subcommand.

* fix(op-challenger): use bigs.Uint64Strict for l1Head block number

Satisfies the custom bigint linter, which forbids big.Int.Uint64().
…eum-optimism#21596)

* fix(op-reth): drain Prometheus metric buckets in op-proofs CLI

* fmt fixes
…o op-reth (ethereum-optimism#21145)

* docs(chain-operators): default feature guides to op-reth

Replace incidental op-geth mentions in the Flashblocks and Alt-DA mode
guides with op-reth (op-geth EOS 2026-05-31), where the feature works
identically across execution clients:

- Flashblocks: the fallback/default builder is a standard EL node; default
  to op-reth (op-rbuilder is reth-based), with an op-geth EOS note
- Alt-DA: op-reth prerequisite; "no EL config changes" note generalized

Refs ethereum-optimism/solutions#695

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Apply suggestions from code review

Co-authored-by: soyboy <85043086+sbvegan@users.noreply.github.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: soyboy <85043086+sbvegan@users.noreply.github.com>
…m#21628)

The link checker job was configured to never fail anyway so errors were being ignored.
The kona README was significantly out of date - predating the merge into the monorepo.
…imism#21626)

The node architecture overview under node-operators/reference/architecture/
is pure explanation — it builds a mental model of a node's components (Rollup
Node, Execution Client, Legacy Geth) and how they relate to an Ethereum node,
with analogies and the "why" behind Legacy Geth, and no austere lookup
structure. Declare its true Diátaxis quadrant (diataxis: explanation) in
frontmatter and reframe the opening to read as an explainer, so the taxonomy is
explicit and lint-able. No technical claims changed — this is a structural
relabel, not an accuracy pass.

Tracks ethereum-optimism/solutions#814

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: consitent bit format in decodeZK and LibGameArgs ZK game args roundtrip test

* docs: natspec improvements and clarifications for super zk game

* test: libClone vulnerability regression test for CWIA game creation

* chore: reference issue number in zk todos

* chore: bump validator version due to natspec change
…#21632)

* Update upgrade-19.mdx with gas configuration check

Added a check for 'keep_karst_upgrade_gas' in activation configuration.

* Apply suggestion from @geoknee

* Apply suggestion from @geoknee
Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
…ests (ethereum-optimism#21128)

* feat: SuperZKGame rootClaim semantics + extraData layout + dynamic parsing

* feat: SuperZKGame rootClaimByChainId implementation

* feat: SuperZKGame l2chainId and SuperRootProof init checks

* feat: l2SequenceNumber semantic changes

* feat: prove public values update

* test: first unit and integration test modification pass with new helpers

* refactor: make l2chainId getter internal and remove it from the interface

* fix: rename NoChainIdNeeded to ZKDisputeGame_NoChainIdNeeded to comply with convention, update interface

* test: remove unused import and fix ASR ZK failing tests due to wrong CWIA args encoding

* fix: rename superrootproof local var to proof to fix compiler warnings

* test: improve test coverage by testing new calldata branches in verification function

* test: fix l2sequence number in go tests

* chore: update codehash change

* test: clean up zk game unit tests, resuse helpers and make default game multi chain

* chore: fuzz test lint

* test: expand test_superRootProof_returnsExpectedBytes_succeeds and l2chainid 0 enforcement

* test: improve super zk game integration test coverage

* test: lint integration tests

* Merge zk game changes

* test: end to end super migration test

* fix: zk game changes, add missing helper for integration tests

* fix: natspec about anchor root re-init and assertions for sfdg close

* fix: rename super permissioned canon type to fix build

* chore, small natspec nit
…ract to OP Sepolia (ethereum-optimism#21607)

Adds a learning-oriented tutorial (Diátaxis `tutorial` quadrant) that walks an
app developer end-to-end through deploying their first contract to OP Sepolia
with Foundry: install → project + Greeter contract → configure the OP Sepolia
RPC and a funded account → deploy with `forge create` → read/write with `cast`
→ view on the block explorer. Every network parameter, RPC endpoint, and faucet
link is grounded in OP's own docs; the Greeter contract and `forge`/`cast`
patterns match the existing interoperability tutorial.

Wires the page into the App Developers → Tutorials nav as the first entry.

Tracks ethereum-optimism/solutions#801

Co-authored-by: Claude <noreply@anthropic.com>
* feat: merge with dev

* feat: merge with dev

* fix: merge with dev

* fix: merge with dev

* feat: added mock to op deployer

* feat: added mock to op deployer

---------

Co-authored-by: 0xarktos <arktos@wonderland.xyz>
…thereum-optimism#21582)

The fpvm precompile provider's hand-rolled `run` panicked via
`assert!(underflow, "Gas underflow is not possible")` if a precompile
reported `gas_used > gas_limit`. revm v40's `EthPrecompiles::run` (which
op-revm inherits by delegation) instead gracefully out-of-gases this case
(`spend_all` + `PrecompileOOG`).

The branch is unreachable for the registered precompile set — each checks
cost <= gas_limit before returning `Ok` — so there is no consensus impact.
But matching upstream keeps the FPVM and op-reth aligned by construction
rather than by audit, and removes a foot-gun where a future precompile
that omits the check would halt the fault-proof program instead of
deterministically OOG-ing.
…ptimism#21625)

* test: remove post-U19 cannon transitional handling in fork/upgrade tests

U19 disables the legacy CANNON permissionless game, leaving CANNON_KONA as the live game on upgraded chains. Remove the CANNON->CANNON_KONA startingRespectedGameType override from the fork setup and the mirrored helpers in the OPCM V2 upgrade tests, plus the now-dead _isPermissionlessGameType helper.

Fork upgrade tests for chains that have not yet run U19 (e.g. unichain) will fail until they upgrade; this is intentional.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: report cannon-kona permissionless game in FetchChainInfo

FetchChainInfo derived the permissionless game only from GameTypes.CANNON, so post-U19 chains (CANNON disabled, CANNON_KONA live) reported no permissionless game. Fall back to CANNON_KONA when CANNON is absent, and dedupe the CANNON_KONA lookup.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* ci: pin fork test block daily instead of weekly

The pinned block is the forked-state cache key, floored to the start of the period. Weekly pinning let fork tests lag live mainnet by up to a week, so a mid-week upgrade (e.g. Unichain U19) failed every run until the pin rolled forward. Daily cuts the lag to at most a day, at the cost of ~7x more cold-fork cache misses (one per fork cache key per day), each amortized across that day's runs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…m-optimism#21634)

Follow-up to ethereum-optimism#21582. The fpvm precompile provider's hand-rolled run left
all gas as remaining on a precompile halt, unlike revm's
precompile_output_to_interpreter_result (which spend_all()s on the
not-success-or-revert path). Align the halt branch by spending all gas.

Currently unobservable: on a non-ok-or-revert result the caller frame and
top-level handler discard the callee's remaining gas and force-consume the
forwarded/limit gas anyway. This keeps the FPVM aligned with op-reth by
construction rather than relying on that downstream behavior.

test_run_halting_precompile_spends_all_gas registers a mock accelerated
precompile that halts and asserts run returns PrecompileOOG with all gas
spent. Red without the fix (remaining == gas_limit), green with it.

Co-authored-by: wwared <541936+wwared@users.noreply.github.com>
…m#21579)

Move the inline bash from the prepare-continuation-config "Compute
workflow conditions" step in config.yml into a standalone
compute-workflow-conditions.sh, with no behavioral change. The
decision-tree and schedule-trigger tests now read the extracted script
instead of the config.yml inline command.

test-decision-tree.sh runs the real routing script and so must not write
the pipeline's shared /tmp/pipeline-parameters.json: finalize would leave
c-run_* flags (e.g. c-run_close_issue from the last scenario) that the
later collect-params/compute steps inherit. It now uses an isolated,
exported OUTPUT file; workflow-helpers.sh honors that override.
Removes the six PR-time Go fuzz jobs (the `fuzz-golang` matrix over
op-challenger/op-node/op-service/op-chain-ops, plus `cannon-fuzz` and
`op-e2e-fuzz`) and their `fuzz-golang` reusable job definition, and drops
the six corresponding `terminal` entries from the `ci-gate` required-check
fan-in.

These jobs ran short, cold-start `-fuzztime` exploration (10-60s) gated on
package change, with no committed seed corpus, so nothing from prior
exploration was ever persisted. Their deterministic value (the seed cases)
is already exercised by the normal unit-test jobs, which run each Fuzz
target's seed corpus as regular subtests. The fuzz functions are retained
and keep running as seed tests.

Also fixes a stale target name in op-node/justfile
(FuzzL1InfoAgainstContract -> FuzzL1InfoBedrockAgainstContract) so the
against-contract differential fuzzer resolves for local `just fuzz` runs.

Closes ethereum-optimism#21636

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…blob[0] bits (ethereum-optimism#21647)

The two high bits of blob[0] are not part of the encoding: FromData writes
them as 0 (x & 0b0011_1111) and ToData masks them off in reassembleBytes, so
flipping them decodes to identical data. FuzzDetectNonBijectivity's
sha256-derived flip could land there and fail require.NotEqual even though
nothing is wrong (flaky test ethereum-optimism#21539).

Relax the invariant to assert equality when the flip targets those two bits,
add a corpus seed that deterministically hits the case, and add
TestBlobNonEncodedHighBits asserting a no-op decode there. Test-only; no
production behavior change.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eum-optimism#21648)

* superchain: reject unknown keys when decoding registry configs

The BurntSushi/toml decoder silently drops keys the config structs don't model.
That is how keep_karst_upgrade_gas could be added to the registry yet never reach
op-node's rollup.Config until ethereum-optimism#21566 added the missing struct field by hand: the
value was read from the embedded TOML and thrown away with no error.

Add jsonutil.DecodeTOMLStrict, a shared strict TOML decode that rejects any source
key no struct field captures (an allowUnknown predicate lets callers tolerate
specific keys). Decode the embedded chain and superchain configs through it. Chain
configs allow nothing — ChainConfig models every field, which
TestAllEmbeddedConfigsDecodeStrictly enforces across all embedded chains — so a
registry bump that adds a field now fails to load until the struct is updated to
consume it. The superchain path allow-lists only the deliberately-unmodeled legacy
protocol_versions_addr.

Also extract the registry -> rollup.Config conversion into rollupConfigFromRegistry,
separate from the registry lookup, and add TestRollupConfigFromRegistry_AllFieldsSet:
it reflects over the converted Config and fails if any field is left zero, so a new
registry-derived field forgotten in the conversion is caught.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* kona: reject unknown keys when decoding registry ChainConfig

Mirror the strict decoding added on the op-node Go side. kona's HardForkConfig
already had deny_unknown_fields, so the keep_karst_upgrade_gas class of dropped
field could not happen there, but the top-level ChainConfig did not — an unmodeled
registry key was silently ignored.

Add deny_unknown_fields to ChainConfig, matching every other config struct in the
crate. The embedded configs.json and the promoted superchain-registry TOMLs at the
pinned commit only carry modeled keys, so this is a no-op today; a future registry
bump that adds a field now fails loudly (at deserialization, or at
KONA_SYNC_SUPERCHAIN=true regeneration, with a chain-named build.rs panic) instead
of dropping it.

test_chain_config_unknown_field_json previously passed only because its [optimism]
values were hex strings that failed u64 parsing — the unknown key was never the
cause. Make those values numeric so the extra key is the sole error, so the test
actually guards the attribute.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
)

* feat(kona-sp1): scaffold super interop programs

* fix(kona-sp1): bind range intermediate super roots

* address review comments
0xiamflux and others added 11 commits July 8, 2026 19:07
…-optimism#21650)

Extract LoadOPStackRollupConfig (and applyHardforks) out of op-node/rollup
into a new op-node/superchain package. superchain.go was the only file making
op-node/rollup transitively depend on op-core/superchain, whose //go:embed of
the (gitignored, ~3MB) superchain config bundle forces the zip to be generated
before the package compiles.

op-node/rollup is imported by ~50 packages that only need its config types;
they no longer pull in the bundle. In particular op-fetcher/... and
op-chain-ops/script are now superchain-free, which unblocks the
superchain-registry ops/cmd/codegen build chain.

The five call sites of the moved function are all packages that legitimately
read the registry, repointed to op-node/superchain. op-node/rollup/deps_test.go
guards against reintroducing the dependency. No behavior change: the loader
body is unchanged apart from type qualifiers.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…21640)

Make precompile statuses more explicit via an enum rather than just
using Err returns.
* ci: make CircleCI workflow routing declarative

Move the routing data (schedule->workflows, API dispatch flags,
change-detection patterns, passthrough params) into a standalone
routing.yml and have compute-workflow-conditions.sh read it, so the
scripts hold only the routing logic. collect-params.sh now reads the
change patterns from routing.yml, and test-schedule-triggers.js reads
the schedule map directly instead of parsing the routing script.

* ci: address routing review comments
…p paths (ethereum-optimism#21659)

Restructure the multi-part "Create your own L2 rollup testnet" entry page so it
reads as a clean linear getting-started flow, grounded entirely in the page's
existing content (no command, version, or instruction changes):

- Move the "Before you start" prerequisites (dependency table, sepolia node
  access, required Sepolia ETH + L1 RPC URL) above both setup paths, so
  requirements come before either the automated or manual path.
- Add a "Choose your path" section presenting automated vs manual as an explicit
  up-front choice.
- Consolidate the manual path: merge the orphan "Manual setup" heading, the
  directory-structure section, and the separate "Manual Tutorial Overview" Steps
  into one ordered "Manual setup" section.
- Fix the closing Card link to the canonical /chain-operators/... path (was a
  non-canonical /operators/... path that only resolved via a redirect).
- Add diataxis: tutorial frontmatter.

Tracks ethereum-optimism/solutions#873

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ptimism#21643)

* test(contracts): cover post-upgrade fork live setup

* fix(contracts): support post-migration fork live setup

* test(contracts): consolidate permissioned game proposer lookup

* test(contracts): consolidate permissioned challenger lookup

* test(contracts): remove unused migration helper args
…m-optimism#18494) (ethereum-optimism#21656)

kona-sp1 carried a near-verbatim copy of kona_driver's advance_to_target
loop solely to emit SP1 cycle-tracker markers around the derivation and
execution phases. Copying consensus-critical derivation logic risks silent
drift from the canonical loop.

Replace the copy with the canonical kona_driver::Driver::advance_to_target
via an optional, prover-agnostic metric-collector interface:

- kona-driver: add DriverMetrics (phase_start/phase_end, default no-ops),
  DriverPhase, and NoopDriverMetrics. advance_to_target becomes a thin
  wrapper over a generic advance_to_target_with_metrics that reports each
  phase. The default path uses NoopDriverMetrics and compiles away, so the
  canonical derivation pays nothing and kona stays free of prover concepts.
- kona-sp1: delete the copied loop; add CycleTrackerDriverMetrics that emits
  the same cycle-tracker keys (payload-derivation, block-execution) the host
  reads, so the per-phase cost breakdown is preserved. The witness executor
  drives advance_to_target_with_metrics with that collector.

The GHSA-5jh4-3p33-85xc post-check and the outer block-execution-and-derivation
span are unchanged.

Verified: kona-driver + kona-sp1-client-utils build and clippy clean; unit
tests pass; guest ELF rebuilt for riscv64im-succinct-zkvm-elf; the
TestSP1RangeSimpleEmptyChain action test passes for honest and junk claims,
with both per-phase cycle-tracker markers emitted from the guest.
…thereum-optimism#21531)

* feat(op-reth): make OpPoolBuilder ordering and validator injectable

The pool's transaction ordering (CoinbaseTipOrdering) and validator were
fixed at construction, so downstream builders had no way to substitute a
custom ordering or wrap the validator without reimplementing build_pool.

Add two defaulted, general-purpose seams to OpPoolBuilder: an ordering
generic (O = CoinbaseTipOrdering<T>) and a validator-wrapper generic
(W = IdentityValidatorWrapper) with with_ordering / with_validator_wrapper
methods. The defaults reproduce the standard pool exactly, so the default
op-reth configuration and every existing call site are unchanged and
zero-cost.

* test(op-reth): cover OpPoolBuilder ordering and validator seams

Add behavioral integration tests for the OpPoolBuilder ordering and
validator-wrapper seams, organized under a custom_pool/ test module:

- ordering: a custom gas-descending ordering reorders block composition
  versus the default tip ordering, proving the ordering seam drives
  selection end-to-end.
- validator: a custom gas-limit-filtering wrapper rejects an oversized
  transaction at ingress so it never reaches a block, while the default
  wrapper admits it — proving the wrapper gates admission.

Each seam pairs a default-build test with a custom-build test through a
shared launch/inject/build harness.

* feat(op-reth/payload): add OpBestTransactions commit hook to execute_best_transactions

Introduce OpBestTransactions: a PayloadTransactions whose on_commit(gas_used) is
called once per committed transaction, in commit order, so a custom iterator can
maintain its own per-inclusion state (any tx-derived data it needs is captured
at next() time, where it still owns the tx). execute_best_transactions now takes
an OpBestTransactions and calls on_commit at the commit seam.

A plain PayloadTransactions is adapted via RethBestTransactions, whose on_commit
is a no-op, so the standard build path is unchanged.

* test(op-reth): address review feedback on OpPoolBuilder seams PR

Rename the payload commit-hook types for clarity and no collision with
reth_transaction_pool::BestTransactions:
- OpBestTransactions -> PayloadTransactionsWithCommitHook
- RethBestTransactions -> RethPayloadTransactions

Make the on_commit contract explicit in its doc comment and fix the
execute_best_transactions doc (drop the "committed tx and the" relic; the hook
takes only gas_used, and a plain PayloadTransactions satisfies the trait via
RethPayloadTransactions, not a blanket impl).

Replace the two order-insensitive on_commit tests with a single order- and
value-sensitive regression test that pins each committed tx's gas to the
most-recently-yielded hash. Per-tx gas is measured by re-executing through a
second identically-configured builder (oracle), and an over-gas-limit tx that
is yielded but skipped proves the hook fires per committed tx, not per yielded
tx. DRY the pool-tx test helpers over a shared base.

Fix two custom_pool/validator.rs assertion messages (below- -> above-threshold).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* post karst activation cleanup

* Apply suggestions from code review

Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>

* swapped mainnet and sepolia

* fixing sep chain

---------

Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
Finalized release tag for op-reth/v2.4.0-rc.1 (created by baked-goods)
Merged upstream op-reth/v2.4.0 into the Firehose branch (merge commit
made separately). No reth/revm/alloy version bump: upstream's reth pins
are byte-for-byte identical between v2.3.3 and v2.4.0 (still
paradigmxyz/reth v2.3.0), so streamingfast/reth v2.3.0-fh-2 already
covers it. The merge was conflict-free; Firehose hooks sit in functions
disjoint from upstream's op-reth changes.

- Add CHANGELOG.sf.md entry documenting the merge and reth-pin rationale.
- Add .dev/todo task plan capturing the merge scope and verification.
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.