Skip to content

op-reth: fix reth v2.6.0 review findings - #23118

Merged
joshklop merged 5 commits into
joshklop/update-reth-v2.6.0from
seb/reth-v2.6.0-review-fixes
Oct 12, 2026
Merged

joshklop merged 5 commits into
joshklop/update-reth-v2.6.0from
seb/reth-v2.6.0-review-fixes

Conversation

@sebastianst

@sebastianst sebastianst commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

This fixes the blocking findings from my review of #23046. Each one is a regression that the reth v2.6.0 bump introduces. Stacked on #23046.

  • Isthmus withdrawals root: with state masking on (the new default), an op-reth sequencer could write a wrong withdrawalsRoot into a block header, and a verifier could reject a valid block with L2WithdrawalsRootMismatch. The cause is upstream: OverlayStateProvider::storage_root ignored the overlay trie nodes. This PR pins reth to perf(trie): backport reth#27129 overlay storage roots and historical proofs reth#11, which backports the upstream fix (reth#27129, released in v2.7.0); that backport also fixes historical proofs over masked rows. A regression test, masked and unmasked over both storage versions, fails on rust!: update reth to v2.6.0 #23046.
  • Forkchoice updates: pins reth to fix(engine): backport forkchoice-update fixes from v2.7.0 reth#13, which also backports two upstream forkchoice fixes from v2.7.0. They validate safe and finalized before applying a reorg (reth#27247), and stop reporting VALID for a reorged-out persisted head, which on OP could start a payload job on it (reth#27429). A forward sweep of upstream after v2.6.0 found no other OP-relevant fix worth taking before the v2.7.0 bump.
  • op-reth proofs init: init now refuses a datadir whose state trie lags its tip, or where reth's repair of it was interrupted, which happens after an unclean shutdown or on a snapshot of a running node. Before, init seeded a proofs store that matched no block. With backfill, that then failed with StateRootMismatch; without backfill, the node silently served wrong historical proofs. The error tells operators to start the node once and stop it cleanly.
  • Block access lists: debug_getRawBlockAccessList is no longer served. op-reth now refuses to start with --rpc-cache.prewarm-bals or --rpc-cache.cache-computed-bals: on OP, prewarming re-executes every block forever, and it feeds the untested block access list reconstruction into tracing.
  • Flashblock log stream: flashblock_receipts_stream returns logs for filters with an address or topic again. Since the bump, it returned none for them.

Before merge: keep this as a draft until ethereum-optimism/reth#11 and #13 merge, then re-pin to the merged commit. The current pin is reachable only from the fork PR's branch.

Not addressed:

  • Low-impact test-helper refactors suggested by the Rust review: a shared RethTrieStorageLayout conversion, named test tuples, and a network-args helper.
  • A pre-existing issue: flashblock stream logs carry per-flashblock, hash-ordered transaction_index/log_index.

🤖 Co-created with Claude Opus 5.5

sebastianst and others added 2 commits October 11, 2026 15:30
With state masking, reth persists blocks through the Finish checkpoint
while its hashed-state and trie tables lag at the partial state trie
frontier until `op-reth node` repairs them on launch. `proofs init`
copied those tables as the tip's state, seeding a proofs store that
matches no block after an unclean shutdown or a live-node snapshot.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Stop serving `debug_getRawBlockAccessList`, which reconstructs block
access lists through the same untested OP execution path as the eth
methods, and refuse to launch with `--rpc-cache.prewarm-bals` or
`--rpc-cache.cache-computed-bals`: prewarming never stops on OP chains,
and cached lists would position tracing state.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@joshklop
joshklop force-pushed the seb/reth-v2.6.0-review-fixes branch 2 times, most recently from a9acc1b to 41a5488 Compare October 11, 2026 22:58
joshklop and others added 3 commits October 11, 2026 17:27
…ckports

Pin reth to a fork commit that adds upstream fixes on top of the
CanonicalInMemoryStateProvider pin:

- reth#27129: the `OverlayStateProvider` storage root and storage proofs
  read trie nodes through the overlay, and historical proofs complete the
  overlay to the Finish checkpoint. With state masking, the database
  storage trie omits nodes overwritten by the masking suffix, so the
  Isthmus withdrawals root (the L2ToL1MessagePasser storage root) was
  computed from stale cached child hashes, both when building blocks and
  when validating them. A regression test covers masked and unmasked
  tries over both storage versions.
- reth#27634, the follow-up to #27129: use trie changesets for every
  overlay. Without it, #27129 makes historical proofs and witnesses for
  blocks below the in-memory window rehash from the leaves, which takes
  minutes and hits the read-transaction timeout.
- reth#27247 and reth#27429: validate safe and finalized before applying
  a forkchoice reorg, and stop reporting VALID for a reorged-out
  persisted head.
- reth#27252: the state root task persisted accounts emptied under
  EIP-161 as all-zero `HashedAccounts` rows instead of deleting them. The
  block's root is still right, but a later full recomputation of that
  trie branch diverges and halts the node.
- reth#27832: the walker used by the startup Merkle unwind, which repairs
  a masked state trie after an unclean shutdown, could leave stored
  branch nodes that their parent no longer references. The regular walker
  skips them, so the repair's root check passes, but proof_v2 reads them
  and the engine can then compute a wrong state root.

The fork branch follows the maintenance procedure: the upstream release,
the retained patches oldest first, then the CI commit. The backports
change no symbol a mirror covers, so every reth mirror tag advances to
the new pin unchanged.

Co-authored-by: Sebastian Stammler <seb@oplabs.co>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`proofs init` reads the chain tip it anchors to before it opens the copy
transaction, and it opens the database read-only, so a node still running
on the datadir can persist past that tip in between. With state masking
off, the lagging-trie check then passes and the proofs store anchors the
earlier block over tables from a later one. Refuse when the copy
transaction's Finish checkpoint no longer matches the anchor, and tell
operators to stop any node on the datadir.

Also drop a dev-dependency on reth-chain-state, which is now a regular
dependency.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
op-reth's CLI already rejects every block access list option, so the
add-ons check only guards code that builds a `NodeConfig` without that
CLI. Say so, point new upstream flags at `DENIED_ARGS`, and track the
auth-port `EngineEthApi`, which also declares the unserved methods.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@joshklop
joshklop force-pushed the seb/reth-v2.6.0-review-fixes branch from 41a5488 to 16aa7fc Compare October 12, 2026 00:33
@joshklop
joshklop merged commit 16aa7fc into joshklop/update-reth-v2.6.0 Oct 12, 2026
26 of 59 checks passed
@joshklop
joshklop deleted the seb/reth-v2.6.0-review-fixes branch October 12, 2026 00:35
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.

2 participants