Skip to content

Merge op-reth/v2.3.3 into firehose/2.x#4

Merged
sduchesneau merged 75 commits into
firehose/2.xfrom
firehose/v2.3.3
Jun 29, 2026
Merged

Merge op-reth/v2.3.3 into firehose/2.x#4
sduchesneau merged 75 commits into
firehose/2.xfrom
firehose/v2.3.3

Conversation

@sduchesneau

Copy link
Copy Markdown

Bump the SF op-reth fork to upstream op-reth/v2.3.3 (72 upstream commits, mostly non-firehose: docs, op-node, contracts, kona).

Key facts

  • No reth/revm/alloy bump — reth pin stays streamingfast/reth tag v2.3.0-fh. Firehose tracing code unchanged. Much lighter than the v2.3.1→v2.3.2 bump.
  • Only merge conflict was rust/Cargo.lock (regenerated). The 5 fork-touched code files auto-merged clean; each verified to preserve firehose instrumentation (OpFirehose* wrappers, .inner unwrap, inspect-mode system-call branch).

Adaptations

  1. crates/firehose/Cargo.toml — enable reth-codec feature on reth-optimism-primitives. Upstream feat(op-reth): make chainspec reth-codec opt-in ethereum-optimism/optimism#21483 made reth-codec opt-in, dropping the Compact impls for OpReceipt/OpTxEnvelope; firehose crate now opts in like payload/rpc/storage/post-exec-replay.
  2. New build prerequisite — chainspec build.rs loads configs from the superchain-registry git submodule (feat(op-reth): load OP Mainnet/Sepolia from superchain-registry, drop Base ethereum-optimism/optimism#21397, superchain: couple registry via hoisted root submodule ethereum-optimism/optimism#21474). Run just update-superchain-registry-submodule before building.

Validation

Step Status
cargo check -p reth-optimism-firehose
cargo check --workspace
cargo build -p op-reth --bin op-reth
Battlefield op-reth-devnet not run

🤖 Generated with Claude Code

sbvegan and others added 30 commits June 15, 2026 16:20
… bug (ethereum-optimism#21381)

* docs(notices): warn op-reth operators on OP Sepolia about SCR loading bug

op-reth does not load the Karst activation timestamp from the Superchain
Registry for op-sepolia and op. Adds a Warning banner and updates Step 2
to direct affected node operators to manually configure karstTime via
genesis file.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs(notices): note osakaTime restriction and fix ETA for op-reth v2.3.1

Per George's review: genesis file for op-reth v2.3.1 must not include
osakaTime; both the SCR loading bug and this restriction will be fixed
in a following op-reth release.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs(notices): add OP Sepolia genesis.json download link for op-reth workaround

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* adding a note about op mainnet

---------

Co-authored-by: soyboy vegan <soyboy@soyboys-MacBook-Pro.local>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…imism#21384)

Point engineers at OpHardfork::activates_l1_fork in alloy-op-hardforks as
the single place to add a new OP→implied-L1 fork arm, following the
centralization in ethereum-optimism#21368.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…ethereum-optimism#21392)

* docs(notices): replace genesis.json Drive link with GCS artifact link

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs(notices): add op-proposer game type step and fold contract upgrade into steps

- Moves "Execute the L1 Contract Upgrade" from a standalone section into
  the permissionless FP steps sequence
- Adds step to update op-proposer to game type 8 (CANNON_KONA) after
  the contract upgrade executes, addressing the gap that caused proposer
  failures on Sepolia

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: soyboy vegan <soyboy@soyboys-MacBook-Pro.local>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…m#21379)

* refactor(sdm): gate SDM directly on Lagoon hardfork

PR ethereum-optimism#21105 renamed the Interop hardfork to Lagoon. SDM previously gated
transitively through the interop feature toggle (IsSDM -> IsInterop ->
IsLagoon), which coupled two unrelated features: if interop's activation
is ever decoupled from Lagoon, SDM would silently follow.

Gate SDM directly on the Lagoon hardfork accessor in all three clients
(op-node, op-reth, kona), and refresh the stale "rides the Interop
hardfork" comments. Behavior-preserving today, since both paths resolve
to lagoon_time.

- op-node: IsSDM -> IsLagoon
- op-reth: is_sdm_active_at_timestamp -> is_lagoon_active_at_timestamp
- kona: add is_lagoon_active / is_first_lagoon_block fork accessors; SDM
  and the fork-ordered spec_id gate on them. is_interop_active is kept as
  the interop *feature* gate (mirroring op-node's IsInterop, = Lagoon
  today but separable) and continues to back interop-feature code
  (message graph, proof driver interop mode, derivation, sequencer).

Closes ethereum-optimism#21129

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

* docs(sdm): stop naming Lagoon hardfork in SDM/interop comments

Address review feedback: refer to the activating hardfork in the
abstract rather than naming Lagoon, so comments don't go stale if SDM
or interop is ever rescheduled to a different fork.

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

---------

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

RecordBlockStats set BlockGas twice — once with gas used and once with
the base fee — which left the BlockBaseFee gauge unset and clobbered the
gas gauge. Record the base fee on BlockBaseFee instead.

Also fix the pre-block status log, which emitted status.Gas for the
"basefee" field instead of status.BaseFee.

Adds a regression test asserting gas and base fee land on their own
gauges.

Closes ethereum-optimism#20958
…ethereum-optimism#21396)

Host.Call swallows the go-ethereum state-journal panic that forge scripts
trigger as ordinary control flow ("revision id N cannot be reverted"). The
guard matched the literal substring "revision id 1", so it only recognised
revision ids beginning with 1 (1, 10-19, 1xx...); any other id — e.g. the
"revision id 36" reached by the OPCM v2 upgrade path — slipped past the
recover handler and re-panicked, crashing op-deployer integration tests
data-dependently.

Extract the predicate into isExpectedRevertPanic and match the full
"revision id <N> cannot be reverted" pattern via regexp. Add a unit test
covering the regression (ids not starting with 1) and non-matching panics.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…um-optimism#21346)

* refactor(contracts): track predeploy initialization in registry

* test(contracts): derive L2CM upgrade coverage from predeploy registry

* refactor(contracts): drop redundant parens in predeployToCodeNamespace

* test(contracts): assert init path never taken for non-init predeploys

* refactor(contracts): model predeploys as proxy variants

* chore(contracts): regenerate predeploy variant snapshots
…on (ethereum-optimism#21345)

* test(op-deployer): assert L2 genesis predeploy invariants

* feat(op-chain-ops): validate L2 genesis allocs in production generation

* test(op-deployer): assert interop stays inactive in L2 genesis allocs

* test(op-deployer): drop proxy admin owner EOA allowance from L2 genesis oracle
…tension node (ethereum-optimism#19728)

Adds a length check before slicing in `TrieNode::open` to prevent a
panic when `prefix.len()` exceeds `path.len()` for Extension nodes.

Adds a unit test that calls `TrieNode::open` on an Extension node with
a path shorter than the prefix, verifying it returns `Ok(None)` rather
than panicking. Also enables the `thread_rng` feature for `rand` in
dev-dependencies so the existing proptest compiles.

Co-authored-by: Einar Rasmussen <einar@oplabs.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…ptimism#21436)

* feat(op-supernode): honor explicit per-chain p2p key path

withNamespacedP2P unconditionally overrode --vn.<chainID>.p2p.priv.path,
so a statically supplied per-chain key was always ignored in favor of an
auto-generated key in the datadir. Guard the override with IsChainSet so an
explicit per-chain path is honored (e.g. a read-only mounted static key),
falling back to the namespaced datadir default when unset. A vn.all value is
still not honored: one shared path would collide across every virtual node,
matching the listen-port handling.

Adds tests for both the default-namespacing and per-chain-honored cases.

* chore: remove comments + kick ci
…rotocol dep (ethereum-optimism#21442)

The kona-hardforks crate depended on kona-protocol solely to use the
Predeploys address constants. This dependency was backwards: a low-level
fork-transactions crate should not pull in the higher-level protocol crate.

Move the Predeploys struct and its address constants to kona-genesis, the
base crate that both kona-protocol and kona-hardforks already depend on and
which has no kona-* dependencies. kona-protocol re-exports Predeploys to
preserve its public API. kona-hardforks now depends on kona-genesis instead
of kona-protocol, breaking the cycle.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…er candidates (ethereum-optimism#21359)

SDM block-warming refunds are recorded by an inspector during EVM execution —
before the commit decision — and are not journaled, so discarding a tx's changes
does not roll them back. The op-rbuilder payload builder selects txs via
execute_transaction_with_commit_condition and declines candidates
(CommitChanges::No) that exceed a builder gas/DA/address limit or are
reverted-and-excluded; those declined candidates still warmed the maps, so a
later committed tx could claim a block-warming refund attributed to a tx that
never entered the block. Commit-only paths (block import, debug_replaySDMBlock
derivation) never observe that warmth, so the producer's payload diverged from
derivation. With Osaka active (ethereum-optimism#21337) this surfaced as
TestFlashblocksSDMMaterializesPostExecBlock failing, so the test was skipped.

Fix: override execute_transaction_with_commit_condition on OpBlockExecutor to
snapshot the block-scoped warming state before execution and restore it whenever
the tx is not committed. The snapshot (a clone of the warming maps) is taken only
in Producing mode, so there is no clone cost when SDM is off or verifying.

- alloy-op-evm: the override plus a unit test for the declined-candidate rollback.
- op-rbuilder: comment at the decline site noting the rollback dependency.
- flashblocks_sdm_phantom_test.go: TestFlashblocksSDMPhantomWarmingDivergence
  drives a persistently-declined poisoner alongside committed victims and, per
  victim block, compares the producer-baked SDM payload against the commit-only
  derivation. FAILS pre-fix (divergent_blocks=6, refund 18400 vs 0), PASSES after.
- flashblocks_sdm_test.go: re-enable TestFlashblocksSDMMaterializesPostExecBlock
  (remove the t.Skip) and match the streamed flashblock to the sealed block by
  canonical hash instead of a "final flashblock" guess, fixing the 9-vs-15 flake.

Fixes: ethereum-optimism#21354

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

Interop and custom gas token are not a supported combination; the
interop genesis upgrades a heavier predeploy set, which under CGT
pushed the gas-profile recommended limit past the static budget.
Skip the interop variants when CGT is enabled, and bump the
upgradeExecution gas limit (3.7M -> 4M) for headroom.
… interop-smoke) (ethereum-optimism#21395)

* feat(op-chain-ops): promote op-up interop smoke tests to standalone interop-smoke tool

The interop smoke tests (chain identity, ETH transfers, cross-chain ETH
bridging, and valid/invalid executing-message validation against two live
chain RPCs) were added as the op-up smoke-interop subcommand in ethereum-optimism#19747 and
briefly disappeared when op-up was deleted in ethereum-optimism#21207 (restored by ethereum-optimism#21323).

Move the implementation to a shared op-chain-ops/interopsmoke package and
expose it as a standalone op-chain-ops/cmd/interop-smoke CLI, alongside the
other one-off chain tools, so it no longer depends on op-up's fate. op-up
keeps its smoke-interop subcommand (same flags and OP_UP_SMOKE_* env vars)
by mounting the shared command. check-interop/run.sh now builds the
standalone tool instead of all of op-up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(op-chain-ops): add check-lagoon and interop-smoke bridge failsafe testing

Renames check-interop to check-lagoon and adds comprehensive interop
smoke testing to both tools:

interop-smoke bridge:
- TOML config support via --config flag (altsrc)
- Random bridge amounts, pre/post balance logging
- --test-failsafe flag: verifies A↔B bridging works, enables failsafe
  on one or more op-interop-filter instances (JWT-authenticated,
  multi-filter support), confirms relay is rejected in both directions
  with multiple retry attempts, disables failsafe, confirms bridging
  works again

check-lagoon failsafe:
- Multi-filter support (FilterAdmins []client.RPC)
- JWT secrets as inline hex strings instead of file paths
- Bidirectional testing (A→B and B→A) at each lifecycle step
- 3 relay rejection attempts with full error logging per attempt

* chore(op-chain-ops): check-lagoon cleanup

- Replace run.sh with README documenting commands and config format
- Fix config.example.toml env var prefix: CHECK_INTEROP_* → CHECK_LAGOON_*
- Consolidate smoke.go constants into one block; add failsafeSubmitGasLimit
  to replace the hardcoded 300_000 in expectBridgeBlocked
- Fix stale checks.go comment on expectBlocked ("once" → multiple attempts)

* chore(op-chain-ops): wrap relay errors with %w (errorlint)

* chore(op-chain-ops): make check-lagoon canonical for interop failsafe

Strip the duplicated bridge-loop and failsafe logic from interop-smoke so
check-lagoon is the single owner of round-trip bridging and the failsafe
lifecycle test. interop-smoke returns to the simpler op-up-derived smoke
tool (identity/transfer/bridge/valid-message/invalid-message).

- remove smokeFailsafe, expectBridgeBlocked, setFailsafeAll,
  isFailsafeRejection, dialFilterAdmins and the --test-failsafe/--loops/
  --config/--filter.* flags from the bridge command
- revert smokeBridge and waitForRelaySuccess to their pre-promotion form
- drop rpcErrCode/rpcErrOutOfScope and now-unused imports
- delete orphaned check-lagoon/bridge.example.toml (documented the removed
  interop-smoke bridge --config feature)

* refactor(op-chain-ops): single shared interop bridge implementation

Both check-lagoon and interop-smoke had their own send->relay->verify ETH
bridge. Extract check-lagoon's (the canonical one) into a new shared
op-chain-ops/interopbridge package and have both tools call it.

- add interopbridge.BridgeETH / BridgePlan / SendETHTrigger
- check-lagoon checks: bridgeETH and failsafe send-leg use interopbridge;
  drop the local sendETHTrigger/sendETHFn/retryPlan and dead imports
- interop-smoke smokeBridge delegates to interopbridge (bounded by a 2m
  timeout); drop the local sendETHTrigger/sendETHFn/waitForRelaySuccess
- document the new package in op-chain-ops/README.md

* docs(op-chain-ops): harden check-lagoon config secret handling

Address PR review: the config now holds live secrets inline (account key,
filter JWT secrets) but only bridge.toml was gitignored, so a user creating
config.toml per the README could commit secrets.

Ignore *.toml except config.example.toml, and make the README explicit that
any local config name is gitignored.

---------

Co-authored-by: Karl Floersch <karl@oplabs.co>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…imism#21448)

* feat(op-reth): gate payload builder on interop failsafe

The payload builder never read the supervisor interop failsafe, so it kept
sealing interop txs into unsafe blocks during a failsafe window until async
pool eviction caught up, and it never excluded interop txs that bypassed the
filter (e.g. private or locally-submitted txs).

Thread a shared InteropFailsafe handle (Arc<AtomicBool>, mirroring
SdmPostExecOptIn) from the txpool interop filter client (writer) through node
setup into OpBuilderConfig (reader). When the failsafe is active, the build
loop now excludes every interop tx, detected intrinsically via its
CrossL2Inbox access list rather than the pool's interop-deadline marker, so
unfiltered interop txs are caught too.

* docs(op-reth): tighten interop failsafe comments

* test(op-reth): assert interop tx re-includes after failsafe clears

Thread one shared InteropFailsafe handle through three builds (off, on,
off) so the test proves the gate is re-evaluated per build and the
mark_invalid an excluded interop tx triggers does not persist once the
failsafe clears.
…harden test suite (ethereum-optimism#21434)

* test(alloy-op-evm): cover SDM post-exec settlement conservation

Add post-exec settlement conservation tests for the SDM gas/fee
accounting and fix the warming-rebate logic they uncovered:

- exclude a tx's own sender/to/created address from warming rebates
- stop rebating fee-vault settlement touches
- close remaining ethereum-optimism#21324 gaps and add design-doc rebate examples

Also drops stale "failing/known bug" wording from the tests and
silences a clippy field_reassign_with_default warning.

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

* test(alloy-op-evm): name SDM warming-contract test constants

Address review nits: replace the warming_contract() helper with a
const WARMING_CONTRACT address, and lift the inline warming-contract
bytecode in lib.rs into a named WARMING_CONTRACT_CODE const.

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

---------

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

* op-core/types: add DepositTx, PostExecTx and Receipt types

Part of the op-geth decoupling (ethereum-optimism#20257, closes ethereum-optimism#20262). Defines the OP Stack
deposit and post-exec transactions as standalone types matching op-geth's wire
formats (verified by differential tests to be removed at cutover),
free-function replacements for op-geth's Transaction methods, and a Receipt
extending the go-ethereum receipt with the OP Stack L1-cost and operator-fee
JSON fields.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(ai): add PostExecTx to op-geth decoupling plan

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* op-core/types: address review findings

Extend Receipt to op-geth's complete OP receipt field set — a partial set
would silently drop fields from receipt JSON at the cutover, masked until
then by the embedded op-geth receipt. Fix the Mint helper doc (nil mints
decode to zero, never nil) and add tests for empty post-exec payloads,
JSON-RPC-decoded deposits (depositTxWithNonce path), and null receipt
fields.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* op-core/types: document transition-only tx helpers; plan accessor partition

Mark IsDepositTx/SourceHash/Mint/IsSystemTx/IsPostExecTx as transition
scaffolding: an upstream *types.Transaction cannot hold a 0x7E/0x7D tx, so
these are removed at the cutover with the differential test, and the durable
shape reads fields off optypes structs decoded from raw bytes.

Update the decoupling plan: PostExecTx is a canonical Lagoon block tx (trailing
sequencer-rebate tx), so the L2 decode path must route both 0x7E and 0x7D out;
and resolve the L2 tx representation as a class-partitioned accessor set
(InfoAndUserTxs / InfoAndDeposits / InfoAndFirstDeposit) instead of an
optypes.Transaction wrapper.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* op-core/types: clarify PostExecTx payload encoding (review)

Address @nonsense's review on ethereum-optimism#21356: the 0x7D || data wire format has no
outer RLP envelope around the tx body (unlike deposits), but data itself is an
RLP-encoded PostExecPayload (version + SDM gas_refund_entries) that op-alloy/
kona parse — op-geth (and op-core/types.PostExecTx) just treat it as opaque
bytes. Reword the plan doc and the type doc-comment so they no longer call the
payload 'not RLP'.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…ethereum-optimism#21466)

* test(alloy-op-evm): cover included-but-reverted tx warming a later tx

An included tx that reverts still pays for its cold EIP-2929 accesses
(revert undoes state, not burned gas), so its block-scoped SDM warming
must survive and flow to a later committed tx. This was untested.

Add test_included_reverted_tx_warms_later_committed_tx and a
balance_probe_then_revert helper: tx0 is included but reverts after a
cold BALANCE touch, and tx1 cold-touching the same account earns the
rewarm rebate attributed to the reverted tx0. Mirror of the existing
declined-candidate test, where an excluded candidate's warming is
rolled back because it paid nothing.

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

* test(alloy-op-evm): cover all-reverted block still settling rebates

A reverted tx that re-touches a block-warmed account keeps its rebate
(recorded at step time, never journaled), so the executor produces a
non-empty SDM entry set — and thus a post-exec settlement tx — even
when every user tx in the block reverts.

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

---------

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

Capture the diagnostic pattern from the op-core/types work (ethereum-optimism#21356): when CI
fails on a long-lived feature branch, rule out inherited/pre-existing failures
(diff-scope check, look for fixes on develop, rebase) before assuming a
regression.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…hereum-optimism#21469)

Document that op-reth, kona, op-alloy, alloy-op and op-revm were officially
migrated into the monorepo in coordination with the upstream repo owners (the
upstream crates were deleted or deprecated), so the whole Rust OP Stack is
developed here. Note the generic upstream crates these still depend on, the
op-alloy-flz migration remnant (ethereum-optimism#21087), and that op-rbuilder and rollup-boost
remain vendored pending deprecation.

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

* fix(op-rbuilder): append trailing SDM PostExec tx in the standard builder

The standard builder threaded the post-exec mode into its ctx — so in
Produce mode the executor applied SDM refund settlement to state and
post-refund gas to receipts — but never materialized the trailing
PostExec (0x7D) tx carrying the refund entries. A verifier re-executes
the block with the mode derived from its transactions, finds no 0x7D,
runs with SDM disabled, and computes a different state root: every
block built by an opted-in standard-mode builder was consensus-invalid.

Materialize the tx at the end of OpBuilder::execute with the same
produce-side rules as op-reth's try_include_post_exec_tx and the
flashblocks builder's materialize_post_exec (shared via the new
context::build_current_post_exec_tx): empty entries produce no tx, the
sender is the zero address, and the tx is appended last. Derived
blocks (no_tx_pool) never append — they must reproduce exactly the
attribute transactions.

The new integration test runs both builder variants on a chain with
Interop (Lagoon) at genesis and pins the operator opt-in contract:
no PostExec tx without the opt-in, exactly one trailing anchored
PostExec tx with non-empty entries under a repeated-slot workload with
it, and none again after opting out. The driver round-trips every
payload through newPayload, so the missing-append bug fails it with a
state-root mismatch (verified against the unfixed builder). The test
framework now registers SdmAdminExt like the production launcher and
exposes an IPC rpc_client() for extension namespaces.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor(op-rbuilder): address review on SDM PostExec append

- Add `OpPayloadBuilderCtx::force_empty()` mirroring op-reth and use it at
  the standard builder's PostExec append site instead of inlining
  `!attributes().no_tx_pool`.
- Replace the opaque init-code hex in the SDM test with named revm opcode
  constants; the runtime offset is derived from the constructor length so it
  can't drift. Byte-equivalent — both test variants still pass.

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix: audit finding ethereum-optimism#29

* fix: audit finding ethereum-optimism#13

* fix: audit finding ethereum-optimism#30

* fix: audit finding ethereum-optimism#27

* fix: audit finding ethereum-optimism#22

* fix: audit finding #8

* fix: audit finding ethereum-optimism#15

* fix: ci

* fix: semver

* fix: constant value
… Base (ethereum-optimism#21397)

* feat(op-reth): load OP Mainnet/Sepolia from superchain-registry, drop Base

OP Mainnet and OP Sepolia chain specs now load from the embedded
superchain-registry like every other superchain, replacing the hand-coded
flagship statics. OP Mainnet's Bedrock genesis hash is pinned in
`From<Genesis>` (chain id 10) because its header can't be recomputed from
genesis state, mirroring op-geth's core/superchain.go override; OP Sepolia
(block-0 genesis) is computed normally.

The hand-maintained fork-schedule statics (OP_MAINNET_HARDFORKS,
OP_SEPOLIA_HARDFORKS, BASE_*_HARDFORKS) are removed. The canonical fork
*order* now lives in `OP_HARDFORK_ORDER`; each fork's activation time comes
from the chain's own registry config, eliminating the duplicated timestamp
tables.

Base support is removed entirely (statics, embedded genesis JSONs, gas-limit
constants, CLI/parser arms); test and example fixtures move to OP Mainnet /
OP Sepolia.

`superchain-configs` stays non-default (the op-reth binary enables it via the
cli crate). Adds an `op-mainnet` chain alias.

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

* fix(op-reth): enable superchain-configs for examples; use OP Sepolia for rollup-boost launch test

CI follow-ups for the registry-only-chains change:

- The `engine-api-access` and `op-db-access` examples use `OP_MAINNET`, which
  now lives behind the non-default `superchain-configs` feature. Enable it on
  their chainspec dependency (op-db-access goes through the `reth-op` umbrella,
  so expose a `superchain-configs` feature there too). Fixes `rust-cargo-hack`.
- The rollup-boost `flashblocks-rpc` test launches a node from a block-0
  genesis, so it needs the Bedrock-at-genesis `optimism_sepolia()` builder, not
  `optimism_mainnet()` (whose Bedrock is at block 105235063). Fixes
  `rollup-boost-checks`.

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

* refactor(op-reth): centralize OP Mainnet genesis-hash pin in a shared seal helper

Add `make_op_sealed_genesis_header`, which wraps `make_op_genesis_header` and
applies OP Mainnet's pinned genesis hash (chain id 10) at seal time. Route all
three genesis-seal sites through it (`From<Genesis>`, `OpChainSpecBuilder::build`,
and `OP_DEV`), so the pin lives in one place.

The builder now pins OP Mainnet's hash too, so the manual `set_hash` workaround
in the `op_mainnet_forkids` test is no longer needed and is removed.

Addresses PR review feedback.

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

* fix(op-reth): convert new interop-failsafe payload test to OP Mainnet

A develop commit added `execute_best_transactions_excludes_interop_txs_when_failsafe_active`
using the now-removed `base_mainnet()` builder and an `op_interop_pooled_tx` helper on chain
8453; switch both to OP Mainnet (chain 10) to match this branch's Base removal.

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

---------

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

* superchain: couple registry via hoisted root submodule

Hoist the superchain-registry submodule from
packages/contracts-bedrock/lib/superchain-registry to the repo root as the
single canonical commit pin, and have op-core/superchain (Go) and kona read it
directly instead of cloning the registry independently. Nothing enforced that
the previously separate pins agreed; now they all derive from one submodule.

- Move the submodule to /superchain-registry and delete the standalone
  op-core/superchain/superchain-registry-commit.txt pin.
- op-core/superchain/sync-superchain.sh reads the submodule (no clone); init.go
  derives the embedded commit from the zip's COMMIT entry and keeps the op-geth
  cross-check.
- Repoint kona build.rs, contracts-bedrock foundry paths, and the rust-ci
  submodule init to the root path. Rename KONA_BIND to KONA_SYNC_SUPERCHAIN.
- Add `just update-superchain-registry-submodule [<ref>]` (the single scoped,
  shallow update) and split sync-superchain into sync-superchain-go /
  sync-superchain-rust; `just sync-superchain [<ref>]` is the one-command bump.
- check-prestate reads the submodule gitlink, falling back to the legacy txt
  for older kona-client tags.

op-reth's archive coupling (build.rs generating the tar, dropping the committed
archive) follows in a stacked PR.

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

* ci: verify op-reth pins the same superchain-registry commit

op-reth's res/superchain_registry_commit is a standalone pin that nothing
checked against the canonical submodule, so it could silently drift from
op-core/kona. Assert in prep-superchain that it equals the submodule gitlink
(read via HEAD:<path>, no submodule init needed).

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

* op-reth: read superchain-registry submodule, drop standalone commit pin

Fix op-reth's superchain-config script to read the hoisted superchain-registry
submodule (initializing it if absent, like op-core's sync script) instead of
cloning the registry's default branch, which silently tracked latest. Delete the
redundant res/superchain_registry_commit file — op-reth's Rust never reads it and
the generated tar already embeds the same commit — and run the script from
`just sync-superchain-rust`. CI now asserts the committed tar's embedded commit
matches the submodule gitlink.

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

* just: force-sync the superchain-registry submodule to the pinned commit

update-superchain-registry-submodule previously only initialized the submodule
when absent, leaving a stale or dirty checkout untouched. Always check it out at
the gitlink commit with --force; in the ref path, stage the new gitlink so the
subsequent no-ref syncs preserve the bump instead of resetting it.

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

---------

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

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* 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

* refactor: fail fast on invalid parent game

* refactor: fail fast on invalid l2chainid

* refactor: remove unecessary casts to IDisputeGame in checks

* docs: improve struct natspec and internal byte count getters

* chore: update game semver hashes

* fix: remove virtual from _gameImplArgsByteCount and fix naming

* feat: remove chain l2

* fix: ci

* fix: undo opcm changes

* fix: comments

* feat: opcm types szkdg (ethereum-optimism#21156)

* feat: merge with dev

* feat: merge with dev

* fix: merge with dev

* fix: merge with dev

* feat: opcm super zkdg

* feat: opcm super zkdg

* fix: enforce l2ChainId=0 in StandardValidator ZK game args

ZK_DISPUTE_GAME is a super game; the chain ID is embedded in per-game
extraData via the super-root proof, not in the immutable factory args
(makeGameArgs sets chainId=0 for isSuperGame() types). The previous
check args.l2ChainId == _l2ChainID always failed; drop the unused
_l2ChainID parameter and assert args.l2ChainId == 0.

* refactor: rename ZK_DISPUTE_GAME → SUPER_ZK_DISPUTE_GAME

Aligns the game type naming with the existing super-game convention
(CANNON→SUPER_CANNON, ASTERISC_KONA→SUPER_ASTERISC_KONA) since game type
10 uses super-root semantics (l2ChainId=0 in factory args). Also fixes
the StandardValidator ZKDG-60 check that always failed for super games
(args.l2ChainId == _l2ChainID → args.l2ChainId == 0) and removes the
now-unused _l2ChainID parameter.

Solidity:
- GameTypes.ZK_DISPUTE_GAME → SUPER_ZK_DISPUTE_GAME
- IOPContractsManagerUtils.ZKDisputeGameConfig → SuperZKDisputeGameConfig
- DevFeatures.ZK_DISPUTE_GAME flag, zkDisputeGameImpl field, and
  LibGameArgs.ZKGameArgs struct are intentionally kept (internal names).

Go (op-deployer):
- embedded.GameTypeZKDisputeGame → GameTypeSuperZKDisputeGame
- embedded.ZKDisputeGameConfig → SuperZKDisputeGameConfig
- state.VMTypeZK ("ZK") → VMTypeSuperZK ("SUPER_ZK")
- state.ZKDisputeGameParams → SuperZKDisputeGameParams
- state.ErrZKDisputeGameMissingParams → ErrSuperZKDisputeGameMissingParams
- JSON fields zkDisputeGame/zkDisputeGameConfig → superZkDisputeGame/
  superZkDisputeGameConfig

Note: the SuperZKDisputeGame.sol contract rename itself lands in a
companion PR; this PR keeps zkDisputeGameImpl field and devfeatures.
ZKDisputeGameFlag untouched until that merges.

* feat: rename and validator

* fix: revert renaming

* fix: merge with develop

* fix: coments

* chore: bump superchain-registry to match develop

* feat: remove l2 chain

* fix: complete l2ChainId removal

* fix: complete l2ChainId removal

* fix: lint and build

* fix: merge conflicts and tests

* fix: add super games validation for zk in validator utils

* fix: revert zk super game validation check and clean up todo wording

* chore: bump optimism portal version due to bytecode change

* docs: remove deleted l2ChainId error comment

* refactor: make superRootProof function internal

* fix: replace exclusion for types test

---------

Co-authored-by: OneTony <onetony@defi.sucks>
Co-authored-by: Ashitaka <ashitaka@defi.sucks>
Co-authored-by: Ashitaka <96790496+ashitakah@users.noreply.github.com>
nonsense and others added 25 commits June 23, 2026 08:36
…thereum-optimism#21515)

Adds a MixedL2ELOpRethPremium EL kind that boots op-reth-premium in place
of op-reth. The premium binary uses reth_optimism_cli::Cli (the same CLI
as op-reth, with the proofs subcommands) plus an additive --subblocks.*
namespace, so it is a genuine CLI superset and reuses the existing
buildMixedOpRethNode invocation unchanged — only the resolved binary
differs (new OpRethWithBinary option / OpRethConfig.Binary). Wired into
both EL dispatch sites (NewMixedSingleChainRuntime and the env-driven
startL2ELForKey, so DEVSTACK_L2EL_KIND=op-reth-premium also works).

op-reth-premium lives in a separate repo, so it is resolved via the
existing rustbin env overrides (RUST_BINARY_PATH_OP_RETH_PREMIUM, or
RUST_SRC_DIR_OP_RETH_PREMIUM + RUST_JIT_BUILD).

Adds TestPremiumSequencerProducesDerivableBlocks: a baseline regression
guard that boots a premium sequencer (subblocks producer, SDM off) with a
stock op-reth verifier and asserts both unsafe heads advance — i.e.
premium produces derivable blocks as a drop-in. It does NOT assert SDM /
0x7D behavior (premium does not produce PostExec blocks yet). The test
skips unless the premium binary is provided, so it is inert in CI without
a premium image and never fails there.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… state-root mismatch (ethereum-optimism#21495)

* fix(op-reth): surface pruned block bodies as a typed error instead of state-root mismatch

* ci fixes

* op-rbuilder fixes

* bump rollup-boost cargo

* review fixes

* revert op-rbuilder change

* revert space changes
…pt-in TOCTOU) (ethereum-optimism#21502)

* fix(sdm): harden post-exec payload handling

Reject Verify blocks that claim refunds without the trailing post-exec tx, and snapshot PostExecMode once per payload build so EVM setup and 0x7D appending agree.

* fix(op-reth): sync op-rbuilder and rollup-boost lockfiles

The reth-codec opt-in change (ethereum-optimism#21483) added reth-optimism-primitives as a
dependency of reth-optimism-post-exec-replay but only updated the main rust
workspace lockfile. The op-rbuilder and rollup-boost workspaces depend on
that crate via path, so their Cargo.lock files went stale and the Docker
builds (which run `cargo chef cook --locked`) failed with "cannot update
the lock file because --locked was passed".

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

---------

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

The report cover page identifies it as a Cantina Managed review, not
Spearbit. Rename the PDF and update the ledger row to match.
…/fees (ethereum-optimism#21508)

* op-core: wire op-node onto op-core/eip1559 and txinclude onto op-core/fees

Switch op-node's eip1559 consumers and op-service/txinclude's fee consumers off
op-geth onto the op-core packages, completing the eip1559 + fees parts of ethereum-optimism#20271
(sub-issue ethereum-optimism#21500). The superchain part landed separately in ethereum-optimism#21487.

eip1559: swap the import path in payload_util.go, engine_consolidate.go,
system_config.go (+ engine_consolidate_test.go) to op-core/eip1559, and add the
ValidateOptimismExtraData helper the initial extraction omitted (+ test).

fees: in txbudget.go and cost_oracle.go, replace types.NewL1CostFuncFjord and
tx.RollupCostData() with the op-core/fees equivalents. Simplify the op-core/fees
L1-cost API to free functions (L1CostEcotone/L1CostFjord taking an L1FeeParams
struct), consistent with the existing L1CostBedrock — dropping the closure
factories, the L1CostFunc type, and op-geth's vestigial calldataGasUsed return
and blockTime arg, none of which any monorepo consumer needs. Add a live
differential test pinning L1CostFjord to op-geth's NewL1CostFuncFjord.

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

* op-core/eip1559: dedupe ValidateOptimismExtraData dispatch test

Trim TestValidateOptimismExtraData to cover only fork dispatch — each per-fork
validator's edge cases stay in its own test (TestValidateHoloceneExtraData),
removing the overlap a reviewer flagged.

Keep ValidateHoloceneExtraData / ValidateJovianExtraData public rather than
folding them behind ValidateOptimismExtraData: with the whole monorepo in scope
for the op-geth decoupling, op-chain-ops/check-jovian (an ethclient checker that
stays in Go, not block-building) is a real direct consumer of
ValidateJovianExtraData.

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

* op-sync-tester: swap eip1559 onto op-core/eip1559

op-sync-tester validates header extraData and PayloadAttributes 1559 params via
the eip1559 helpers; point them at op-core/eip1559 (pure rename, the functions
already match). Removing op-sync-tester's remaining op-geth coupling — notably
the miner.BuildPayloadArgs.Id() PayloadID hash — is tracked in ethereum-optimism#21525.

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

* docs(ai): widen opgeth-decoupling scope to the whole monorepo

Replace the "in scope / out of scope" subset with the three-fates framing
(swap-to-op-core / migrate-execution-to-op-reth / delete), and surface two
components the plan had missed: op-sync-tester (a CL-sync EL mock that does no
execution — a swap target, with its OP-aware PayloadID hash tracked in ethereum-optimism#21525)
and the op-chain-ops/cmd/check-* per-fork checker family.

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

* docs(ai): drop op-program/op-supervisor from opgeth-decoupling doc

Both have been removed from the monorepo (op-program superseded by rust/kona,
op-supervisor by op-supernode), so the "replaced, not decoupled" note, the §12
out-of-scope subsection, and the §14 execution-engine reference to them are
stale. Per PR review.

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

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bumps Go module dependencies to clear Grype findings on current develop:

- golang.org/x/crypto v0.46.0 -> v0.53.0
- golang.org/x/net v0.48.0 -> v0.56.0
- golang.org/x/sys v0.40.0 -> v0.46.0
- golang.org/x/image v0.25.0 -> v0.43.0
- go.opentelemetry.io/otel{,/trace,/metric} v1.40.0 -> v1.44.0

Related golang.org/x modules updated by the solver: x/mod, x/sync, x/term,
x/text, x/tools, and x/telemetry.

Leaves quic-go/webtransport-go for a separate libp2p upgrade, and leaves the
btcd scanner finding untouched because the latest btcd module split breaks
existing btcutil import paths.
…imism#21513)

* cleanup(contracts): rename super permissioned game type

* review comments
…#21494)

* fix(op-rbuilder): gate interop txs during failsafe

* fix(op-rbuilder): remove interop feature gate
…ns) (ethereum-optimism#21441)

* fix(derive): keep upgrade gas on a NUT-bundle fork's activation block only

Karst introduced "upgrade gas": extra gas added to a NUT-bundle fork's
activation block gas limit so the network-upgrade transactions fit. It is meant
to apply only to the activation block, but it stuck to every later block — the
SystemConfig gas limit is reconstructed from the parent header (op-node
PayloadToSystemConfig / kona to_system_config), so the inflated activation-block
limit was read back as the steady-state limit indefinitely. op-node and kona
shared the bug, so they agreed but were both wrong.

Subtract the upgrade gas again at the block right after the activation block,
for every NUT-bundle fork from Karst onward (forks.From(forks.Karst) in Go,
OpHardfork::Karst.forks_from() in Rust), so future forks are covered
automatically. A new rollup-config bool KeepKarstUpgradeGas /
keep_karst_upgrade_gas (default false) lets chains that already activated Karst
with the leak baked into their history opt out of the Karst subtraction only, so
their history still validates; the operator clears it later with setGasLimit.
The strip runs during system-config reconstruction, before
UpdateSystemConfigWithL1Receipts / update_with_receipts, so a setGasLimit in the
post-activation block's L1 origin still takes precedence.

Also syncs the superchain-registry submodule to the companion change
(ethereum-optimism/superchain-registry#1259), which enables
keep_karst_upgrade_gas per-chain for the affected sepolia and mainnet chains,
and regenerates the Go + Rust embeddings via `just sync-superchain`. Migrates the
op-node derive test `ptr` helper to the shared op-service/ptr.New.

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

* derive: address upgrade-gas PR review feedback

Addresses review comments on ethereum-optimism#21441.

op-node:
- Simplify upgradeGasToStrip to a one-fork-per-block early return.
- Reword the strip doc/inline comments ("Starting with Karst", "subtract it
  back here").
- Tests: activate Jovian at genesis, fix an assertion message, parameterize
  TestUpgradeGasToStrip over forks.From(Karst), and drive the
  setGasLimit-precedence case through PreparePayloadAttributes instead of
  duplicating the strip/update ordering.
- Print keep_karst_upgrade_gas at startup when set, and add the
  --override.keep-karst-upgrade-gas flag.

kona:
- Extract a public upgrade_gas(fork) getter with a VARIANTS guard test
  (OpHardfork is #[non_exhaustive], so a missing fork can't fail compilation).
- Early-return simplification mirroring op-node; reword the strip comment.
- HardForkConfig::Display prints keep_karst_upgrade_gas when set; move its
  comment between Karst and Lagoon.
- Add the --keep-karst-upgrade-gas-override flag to kona-node and kona-cli.
- Action test: prove the post-activation block too.

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

* kona test: prove post-activation block in NUT-bundle action test

Run the fault-proof program over the post-activation block too, so kona-client
verifies the gas-limit revert directly rather than relying only on op-node's
assertion. Addresses review feedback on ethereum-optimism#21441.

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

* superchain: re-pin registry to superchain-registry#1259 merge commit

Bump the superchain-registry submodule to d84b53b (the ethereum-optimism#1259 merge into SR main,
adding keep_karst_upgrade_gas) and regenerate the Go + Rust embeddings via
`just sync-superchain`. superchain-registry#1263 removed creator-chain-testnet
and ethernity, so only lisk and the OP-stack chains carry the flag now.

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

* derive: address tuicr review feedback

- payload_util_test: use op-service/ptr.New instead of a local minBaseFee const.
- kona: extract a RollupConfig::is_fork_activation_block helper (mirrors op-node's
  IsActivationBlockForFork) and use it in upgrade_gas_to_strip.
- kona: fix the Lagoon override env var (KONA[_NODE]_OVERRIDE_INTEROP ->
  KONA[_NODE]_OVERRIDE_LAGOON), a leftover from the Interop -> Lagoon rename.

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

* rust: refresh SP1 guest Cargo.lock

kona-protocol depends on alloy-op-hardforks and kona-hardforks (the upgrade_gas logic); the SP1 guest workspace path-depends on kona-protocol, so its separate lockfile needs those entries. Regenerated via `just lock-sp1-guest`.

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

* fix(ci): make op-reth-compact-codec resilient to a superchain-registry bump

The op-reth-compact-codec job builds op-reth on develop (to write compact
vectors) and then on the PR branch (to read them). `git checkout` switches the
tracked files between base and PR but leaves both the superchain-registry
submodule working tree and the gitignored res/superchain-configs.tar at the
other side's content. reth-optimism-chainspec's build.rs (superchain-configs is
a hard, unconditional dep of the op-reth bin) regenerates/validates that tar
against the committed .sha256, so on a PR that bumps the submodule it panics on
a base-vs-PR mismatch.

After each checkout, re-sync the submodule to the checked-out pin
(`just update-superchain-registry-submodule`) and drop the stale gitignored tar
so build.rs regenerates it from the now-current submodule.

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

* derive: address further PR review feedback

- kona to_system_config / upgrade_gas_to_strip tests: activate all forks through
  Jovian at genesis via a forks_through_jovian_at_genesis() helper, matching the
  op-node test's fork schedule (geoknee).
- kona NUT-bundle action test: prove the activation-block span before building the
  post-activation block (in addition to the post-activation span), and refresh the
  stale Lagoon early-return comment (drop the closed-ethereum-optimism#21114 reference and the
  outdated "op-node strips just Karst" note).
- docs/ai/fault-proofs.md: call out that these tests cover op-node (which sequences
  and derives the chain) as well as kona-client (which proves it).

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

* genesis: add modular HardForkConfig fork accessors + activate_at_genesis

Replaces the ad-hoc test helper with a proper API on HardForkConfig, mirroring
op-node's Config.ActivateAtGenesis: OpHardfork-keyed fork_time / set_fork_time
accessors and activate_at_genesis(fork), which iterates the fork sequence setting
each to genesis up to and including the target. The kona to_system_config and
upgrade_gas_to_strip tests use it (via a thin karst_at helper) so their fork
schedule matches the op-node test.

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

* karst: add keep_karst_upgrade_gas action-test variant + deploy-config plumbing

Adds TestKarstActivationKeepUpgradeGas to the NUT-bundle action test, covering the
keep_karst_upgrade_gas opt-out (the other branch of testActivationBlockNUTBundle's
revert assertion): the inflated activation-block gas limit must persist on later
blocks, and kona-client must agree.

The flag is set the same way as fork timestamps — via the deploy config: a new
KeepKarstUpgradeGas field on UpgradeScheduleDeployConfig flows into rollup.Config
through DeployConfig.RollupConfig(), and activateFork takes a keep parameter that
sets it. This bakes the opt-out into the whole chain (sequencer, derivation, fault
proof) from genesis, rather than mutating the live rollup config mid-test.

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

* e2eutils: propagate keep_karst_upgrade_gas into the action-test rollup config

e2eutils.Setup builds rollup.Config by hand and wasn't copying the deploy config's
KeepKarstUpgradeGas, so the kona fault-proof action test's keep variant
(TestKarstActivationKeepUpgradeGas) saw the default and reverted the gas limit. Copy
the field, alongside the fork-time fields it sits next to.

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

* karst: assert exact activation-block gas limit in the NUT-bundle action tests

Check the activation block's gas limit is exactly preActivation + UpgradeGas(fork)
rather than merely greater, in both the revert and keep variants. Verified locally:
TestActivationBlockNUTBundle and TestKarstActivationKeepUpgradeGas both pass under a
freshly built kona-host (revert + keep, fault proofs included).

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

---------

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

Follow-up to ethereum-optimism#21489. The ci-base-clang image now ships protobuf-compiler +
libprotobuf-dev (the sp1-sdk prost/tonic build dep), so the per-job apt-get
fallback install added in that PR is no longer needed.

- Pin the rebuilt ci-base-clang digest (sha256:873a6709…, attested by the
  build-images workflow on develop; provenance verified by security.yml).
  This also realigns the c-rust_base_image fragment defaults, which had
  drifted to an older digest (758f67c7…) since the last manual bump (ethereum-optimism#21361)
  only updated config.yml + main.yml's rust_base_image.
- Replace the protoc apt-get install in rust-prepare with a clang-style
  presence check that fails fast if protoc / the protobuf well-known type
  includes are missing from the image.

Validated: merge-configs.sh, circleci config validate (orb stubbed), and
test-decision-tree.sh (18/0).

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

* feat(op-node): remove deprecated Req/Resp CL P2P sync client

Removes the client side of the deprecated Req/Resp CL P2P sync protocol
from op-node, while keeping the serving side (ReqRespServer) intact. This
is the first of two changes: serving payloads to peers that still request
them lets nodes on older versions keep syncing against upgraded nodes
during a rolling upgrade. The server is removed in a follow-up.

- Delete the SyncClient (and all client-only helpers) from
  op-node/p2p/sync.go; the file now contains only ReqRespServer and the
  shared stream/protocol helpers it needs.
- Strip client activation/wiring from NodeP2P: the req-resp serving side
  is still registered behind `p2p.sync.req-resp` (+ a data-source), but
  the client peer-tracking, RequestL2Range and AltSyncEnabled are gone.
- Remove the driver AltSync interface, the altSync field/param, and
  OpNode.RequestL2Range / unixTimeStale. The unsafe-queue gap-check ticker
  is kept (renamed altSync* -> unsafeGap* locals) and now always drives the
  engine-queue gap-fill path.
- Make `syncmode.req-resp` and `p2p.sync.onlyreqtostatic` hidden,
  deprecated no-op flags; delete `sync.Config.SyncModeReqResp` and simplify
  every branch that read it (sync_deriver, engine_controller) to the false
  path. Drop the cross-flag startup validation in service.go.
  `p2p.sync.req-resp` stays active and now gates only the serving side.
- Remove the client payload-by-number metrics (ClientPayloadByNumberEvent,
  PayloadsQuarantineSize) and the quarantine collector; keep the server
  metric and the shared p2p req collectors.
- Update devstack/op-e2e/op-acceptance-tests: drop the client-only
  UseReqResp(Sync) knobs (keeping EnableReqResp* which gates the server);
  delete the enabled-path depreqres suite and the e2e TestSystemP2PAltSync;
  keep a server-only TestMutexUnlocks in p2p/sync_test.go.

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

* docs(op-node): address review comments on req-resp client removal

- Note that the req-resp sync server will be deprecated in a future
  release in favor of EL P2P sync, in the p2p.sync.req-resp flag usage.
- Adapt the checkForGapInUnsafeQueue comment: it no longer retrieves
  payloads from peers over the network; it re-inserts the locally
  queued unsafe payload to drive the engine-queue gap-fill.

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

---------

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

Adds a Karst-activation acceptance test in op-acceptance-tests/tests/karst
that activates Karst mid-chain and observes the gas limit across the
pre-activation, activation, and post-activation blocks. It asserts the
activation block carries the one-time NUT-bundle upgrade gas (gas limit >
pre-activation) and that the post-activation block reverts to the
steady-state limit, covering the fix in ethereum-optimism#21441.

Two variants:
- default: post-activation gas limit reverts to the pre-activation value.
- keep_karst_upgrade_gas = true: post-activation gas limit keeps the
  inflated activation-block value.

Each variant runs the kona-client fault proof (RunKonaNative) over a span
agreeing on the pre-activation block and proving into the post-activation
block, so the fault-proof program covers the behaviour too.

Plumbs keep_karst_upgrade_gas through the deploy path so the second
variant can opt out: a KeepKarstUpgradeGas DeployConfig field flows into
rollup.Config via RollupConfig(), an intentbuilder L2 setter writes the
deploy override, and a sysgo.WithKeepKarstUpgradeGas deployer option sets
it on all L2s. Adds a small L2ELNode.GasLimitAtBlock DSL getter.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…thereum-optimism#694) (ethereum-optimism#21146)

* docs(op-stack): reflect op-reth/kona defaults in protocol explainers

Light conceptual-prose pass for the op-geth -> op-reth and op-program ->
kona-client deprecations (partial ethereum-optimism#694):

- fp-components: present kona-client as the default fault-proof program;
  op-program framed as predecessor with EOS at Karst
- transaction-flow: state execution by "the execution client (op-reth by
  default)"; op-geth noted as supported-but-EOS
- smart-contracts: MIPS-upgrade note covers kona-client (Cannon VM stays,
  client program changes)

Out of scope here (op-geth-specific operational config or historical
source links): architecture.mdx (GETH_* config -> ethereum-optimism#691), components.mdx,
fees.mdx, sync-op-mainnet.mdx.

Refs ethereum-optimism/solutions#694

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

* docs(chain-operators): convert network-design-example to op-reth

architecture.mdx (ethereum-optimism#694): replace op-geth as the default EL in prose and
convert the GETH_* config blocks to op-reth.

- txpool/netrestrict/gossip blocks -> op-reth CLI flags
  (--txpool.disable-transactions-backup/.nolocals/.lifetime, --netrestrict);
  op-reth has no GETH_*-style env vars for these (reth clap args define no
  env=; only globals like RETH_DATADIR exist)
- archive: op-reth is archive by default (no gcmode); full -> --full
- DB_ENGINE / STATE_SCHEME / snap syncmode have no op-reth equivalent
  (MDBX storage + staged sync) -> honest notes, snapshot-restore guidance
- fix pre-existing broken /operators/* monitorism link

Refs ethereum-optimism/solutions#694

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

* docs(op-stack): point EVM/tx-encoding source links to op-reth stack

ethereum-optimism#694 follow-up on the two remaining source-link pages:

- components.mdx: drop the op-geth diff-viewer link and the geth-comparison
  Specifications line; point EVM "Source code" to op-reth (rust/op-reth)
- fees.mdx: repoint the tx-RLP encoding links from op-geth's
  core/types/transaction.go to op-alloy's OpTxEnvelope
  (rust/op-alloy/.../transaction/envelope.rs); keep "standard Ethereum
  transaction RLP encoding" phrasing (accurate for user txs)

Refs ethereum-optimism/solutions#694

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

* docs(fault-proofs): frame cannon-kona as the path forward in challenger explainer

challenger.mdx (ethereum-optimism#694): the op-challenger trace-executables note presented
cannon/op-program host/kona-host as a flat list. Reframe so cannon-kona
(kona-host) is the respected game type going forward and op-program host /
the legacy cannon game type is marked end-of-support at Karst.

Refs ethereum-optimism/solutions#694

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

* docs: drop architecture.mdx from explainers PR

Defer the network-design-example op-reth retarget to the dedicated
PR ethereum-optimism#21296 (docs/network-design-op-reth) to avoid a merge conflict on
this file; ethereum-optimism#21146 keeps its protocol-explainer scope.

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

* docs: address review on explainers migration

- smart-contracts: revert Holocene MIPS bullet to op-program (point-in-time release note)
- fees: restore pinned op-geth RLP encoding links (stable vs unpinned op-alloy/develop)
- transaction-flow: end-of-support past tense + drop redundant double-link

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

* docs: fix op-geth support tense contradiction in transaction-flow

"is also supported but reached end-of-support" was self-contradictory;
reword to past tense "was previously supported but reached".

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

---------

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

* feat(kona): add kona-sp1 range-executor + SP1 execute action test

Add an SP1 execute test harness so the kona-sp1 range guest can be
exercised end-to-end by op-e2e action tests, mirroring the native
fault-proof program harness.

- New `kona-sp1-range-executor` binary: takes the native kona-host
  `single` boot inputs, generates the witness via the kona-host preimage
  server, runs the range guest in SP1 execute mode (no proving), reads the
  committed BootInfoStruct, and exits 0 (valid) / 1 (invalid claim) /
  2 (infra), matching the native fault-proof exit-code convention.
- Go wiring: rustbin.RunKonaSP1Range (shared oracle-server exec path),
  RunRangeExecutor + ProgramRunner refactor in the proofs helpers,
  RunSP1RangeProgram env method, and TestSP1RangeSimpleEmptyChain.
- just recipes (build-range-executor, action-tests-sp1) + README section.
- Add ETHDAWitnessGenerator::new()/Default and use it from the host.

The test skips unless KONA_SP1_RANGE_EXECUTOR_PATH is set and is not yet
wired into a CI job (needs the Dockerized SP1 ELF build in CI). It covers
the honest-claim path only; the host-side witness generator rejects invalid
claims before the guest runs, so invalid-claim coverage is a follow-up.

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

* fix zepter lint

* cargo fmt

* review comments

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat: add FeeVault withdrawal route setter

Allow proxy admin owners to update the fee recipient and withdrawal network atomically.

* fix: bump FeeVault NUT deployment gas limits

Increase FeeVault implementation deployment headroom so generated upgrade bundles satisfy CI gas profile checks.

* doc(ctb): add context on natspec comment

* fix: bump L2ContractsManager semver for inlined FeeVault gas limits

The FeeVault deployGasLimit bumps in Predeploys.sol are inlined at compile
time into L2ContractsManager, changing its initCodeHash. The semver-diff
check requires a version bump whenever semver-lock.json changes.

* chore: regenerate current-upgrade-bundle.json for L2CM version bump

L2ContractsManager 1.10.0 changes its compiled bytecode, which the
upgrade bundle embeds. Regenerated via `just generate-nut-bundle`.

* debug: dump callTracer for reverted activation-block txs

Surfaces the revert frame for TestActivationBlockNUTBundle failures
so karst-jovian tx 31 can be diagnosed in CI logs.

* fix(contracts): update semver-lock

* fix(deployment): bump gas limit left out during merge conflict

* test(feevault): remove debug code

* fix(feevault): use prefork state in tests which start pre-fork, and activate at runtime

* fix(feevault): preserve storage during overlay

---------

Co-authored-by: 0xCoati <258754646+0xCoati@users.noreply.github.com>
…thereum-optimism#21211)

Document SDM: block-scoped warming rebates, the protocol/operator gates,
the admin_setSdmPostExecOptIn and admin_sdmStatus RPCs, and verification.
Register the page in the Features nav.

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

op-node's superchain-registry decoder dropped keep_karst_upgrade_gas: the
Go HardforkConfig struct had no field for it (BurntSushi/toml silently
ignores unknown keys) and applyHardforks never copied it. So an op-node
started with --network=op-sepolia (or op-mainnet) loaded the flag as false
even though the registry sets keep_karst_upgrade_gas = true, and would
subtract the Karst upgrade gas at the post-activation block and diverge from
canonical history. Operators had to pass --override.keep-karst-upgrade-gas
by hand.

PR ethereum-optimism#21441 wired the flag into kona (its HardForkConfig reads it from the
embedded registry) and added the op-node rollup.Config field plus the CLI
override, but never extended the Go SCR-loading path. This closes that gap:

- Add KeepKarstUpgradeGas to superchain.HardforkConfig so the TOML key is
  decoded.
- Copy it in applyHardforks alongside the fork-time fields.

Tested first: asserting KeepKarstUpgradeGas == true for the SCR-loaded
sepolia and mainnet configs in TestGetRollupConfig fails on the baseline
(expected true, actual false) and passes after the fix. The reflection-based
TestApplyHardforks is updated to handle the new non-pointer bool field.

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

Extract the kona-sp1 range execution logic behind a shared Rust API so tests can exercise the core without running the SP1 ELF. Keep the guest entrypoint as the SP1 IO wrapper and add a range-executor native-core mode for faster action-test coverage while preserving the full SP1 execute smoke path.
…mism#21561)

BlobStore leaned on two implicit invariants: kzg_rs's batch verifier
(which skips length checks at 0/1 blob) and an undocumented host
packing order. Move both checks local to blob_provider.rs:

* assert_eq! on the three BlobData lengths at top of From<BlobData>.
* By-hash lookup (linear scan + swap_remove) in get_and_validate_blobs,
  panicking on miss instead of silently dropping the request.
* Drop the now-dead .rev() in the constructor.

In the SP1 guest both new panics surface as "invalid proof".

Behavior note: if a host returned the correct set of blobs in wrong
order, baseline returned an empty Vec; by-hash lookup now succeeds.
Strictly more correct.

Three unit tests fail on baseline cf2ce09 and pass after the fix.

Closes ethereum-optimism#21490.
* op-devstack: add controlled lifecycle support

* review comment

* fix op-up
…on, prestate TBD (ethereum-optimism#21544)

* docs: U19 notice draft — SCR fix, component versions, deposit gas, prestate TBD

- remove OP Sepolia genesis.json workaround (SCR loading fixed in op-reth v2.3.2)
- refresh component table (op-node v1.19.1, op-reth v2.3.2, kona-node TBD,
  rollup-boost v0.7.16, op-rbuilder v0.4.9) + Engine API upgrade-order note
- EIP-7825: clarify outer L1 gas budget for deposits (_gasLimit + ~150k)
- kona-client prestate tag + hashes set to [TBD] pending finalization
- op-proposer step: warn it fails immediately if game type not updated

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

* docs: U19 notice — add affected-chains section for Karst gas limit bug

Lists the Sepolia chains that activated Karst with the buggy release and
have an elevated block gas limit; clarifies mainnet needs no setGasLimit()
action after activation.

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

* docs: U19 notice — setGasLimit required for ALL chains, add procedure

keep_karst_upgrade_gas = true is set in the Superchain Registry for both
Sepolia AND mainnet (verified against SR main: mainnet/op.toml and
sepolia/op.toml), enshrining the elevated block gas limit after Karst.
All chain operators must call SystemConfig.setGasLimit() after activation.

- correct the prior (wrong) claim that mainnet needs no action
- rename section to "Gas limit: action required for all chains"
- add setGasLimit() procedure (read / set from owner / verify)

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

* docs: U19 notice — drop per-chain gas-limit list, keep timing note

The enumerated Sepolia chain list added no action over "all chains" and
risked going stale; collapse to a one-line timing note (Sepolia live now,
mainnet later).

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

* docs: U19 notice — remove deposit outer-L1-gas budget note

Drop the EIP-7825 deposit L1 gas-budget paragraph per review.

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

* docs: U19 notice — drop OP Mainnet/OP Sepolia from SCR examples list

Keep the example list illustrative; the explicit OP entries aren't needed.

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

* docs: U19 notice — address review (revert prestate TBD, name affected chains)

- Revert prestate section to as-is: keep_karst_upgrade_gas preserves consensus,
  so no new prestate is required (restore kona-client/v1.6.0-rc.2 tag + hashes,
  drop the TBD Info note). Per @geoknee review.
- Gas-limit section: name the affected chains (canonical SR ethereum-optimism#1259 list) and use
  the has-flag / no-flag / already-activated conditional instead of "all chains".

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

* docs: U19 notice — address joshklop review

- remove kona-node row (no kona-node release tied to Karst; clears last TBD)
- op-reth: note v2.3.1 is now deprecated
- upgrade-order: "break the sequencer" -> "cause downtime"
- gas-limit: note some not-yet-activated mainnet chains also set the flag

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

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… under Karst (ethereum-optimism#21574)

* fix(op-reth): set tx_gas_limit_cap for Osaka so eth_estimateGas works under Karst

EIP-7825 (Osaka) caps a single transaction's gas at 2^24, and the OP Stack
inherits this cap from Karst onward (KARST/INTEROP -> OSAKA eth base). The OP
EVM-env builder never populated `cfg_env.tx_gas_limit_cap`, so reth's
`estimate.rs` fell back to the block gas limit (e.g. 30-60M) as the trial upper
bound for `eth_estimateGas`. The Osaka EVM then rejected that trial with
"intrinsic gas too high", breaking any contract-call estimate that omitted an
explicit `gas <= 2^24`. This is the OP-side dual of reth PR #25612.

Set the cap in `evm_env_for_op` (the chokepoint for the block, next-block, and
payload env constructors), mirroring alloy-evm's `for_eth_block`. This is
forward-compatible: once reth is bumped past #25612 the field-set becomes
harmless belt-and-suspenders.

Add a chronology-driven unit guard in alloy-op-evm asserting the cap is set
exactly for Osaka+ forks, plus an op-reth integration test that drives a real
`eth_estimateGas` RPC end-to-end on a Karst-active chain.

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

* fix: satisfy clippy::if_then_some_else_none in tx_gas_limit_cap guard test

Use `.then_some(...)` instead of an if/else returning Some/None. CI runs clippy
with `--all-targets`, which lints `#[cfg(test)]` code; the local `-p alloy-op-evm`
run did not.

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

* refactor

* fix(op-reth): add backticks to satisfy clippy::doc_markdown

The estimate_gas_7825.rs module doc referenced eth_estimateGas without
backticks, which clippy::doc_markdown rejects under -D warnings.

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

* Add TODO

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: geoknee <georgeknee@googlemail.com>
Bump the SF op-reth fork to upstream op-reth/v2.3.3.

No reth/revm/alloy version bump (reth pin stays streamingfast/reth tag
v2.3.0-fh), so the Firehose tracing code is unchanged. Two adaptations:

- Enable the reth-codec feature on the firehose crate's reth-optimism-primitives
  dependency. Upstream ethereum-optimism#21483 made reth-codec opt-in, dropping the Compact impls
  for OpReceipt/OpTxEnvelope from the default features; the firehose crate now
  opts in like payload/rpc/storage/post-exec-replay.
- New upstream build prerequisite: chainspec build.rs loads configs from the
  superchain-registry git submodule (ethereum-optimism#21397, ethereum-optimism#21474). Run
  `just update-superchain-registry-submodule` before building.

Validated: cargo check (reth-optimism-firehose), full workspace check, and the
op-reth binary build.
v2.3.3's chainspec build.rs generates superchain-configs.tar from the
superchain-registry submodule, which sits at the repo root outside the `rust`
docker context. Mirror upstream DockerfileOp: COPY the submodule's `superchain/`
subdir from a `superchain-registry` named build context (resolved by build.rs at
/superchain-registry). sf-release.yml inits the submodule and passes it via
build-contexts.
@sduchesneau sduchesneau merged commit a91ea78 into firehose/2.x Jun 29, 2026
2 checks passed
@sduchesneau sduchesneau deleted the firehose/v2.3.3 branch June 29, 2026 16:01
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.