Skip to content

rust!: update reth to v2.6.0 - #23046

Open
joshklop wants to merge 39 commits into
developfrom
joshklop/update-reth-v2.6.0
Open

joshklop wants to merge 39 commits into
developfrom
joshklop/update-reth-v2.6.0

Conversation

@joshklop

@joshklop joshklop commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Moves op-reth onto the reth v2.6.0 dependency stack so it remains aligned with current reth, REVM, and Alloy APIs. Every cherry-pick on the previous fork pin is in v2.6.0 or superseded upstream. The new pin (ethereum-optimism/reth#15) carries the upstream fixes paradigmxyz/reth#27129, #27247, #27252, #27286, #27429, #27634, #27782 and #27832. Problems the reviews found that already exist on develop are tracked separately on the Protocol Team board.

Migration notes:

Proofs history (--proofs-history):

BREAKING CHANGE: op-reth no longer accepts reth's block access list (BAL) options, because OP blocks do not carry EIP-7928 block access lists. This affects operators whose op-reth command lines or unit files pass any of these flags, which previous releases accepted:

  • --rpc-cache.max-bals
  • --db.balstore-cache-size, on node and every other subcommand (db, init, prune, stage, proofs, ...)
  • --engine.disable-bal-parallel-execution
  • --engine.disable-bal-parallel-state-root
  • --engine.disable-bal-batch-io

They are hidden from help, and using any of them now makes op-reth exit with "Block access list options are not supported by op-reth". The BAL options new in reth v2.6.0 (--rpc-cache.cache-computed-bals, --rpc-cache.prewarm-bals) are rejected the same way. To migrate, remove these flags. None of them had any effect on OP chains.

op-reth also does not serve the block access list RPC methods eth_getBlockAccessList, eth_getBlockAccessListByBlockHash, eth_getBlockAccessListByBlockNumber, eth_getBlockAccessListRaw and debug_getRawBlockAccessList. They now return method not found (-32601).

Verified with the Rust workspace checks, feature combinations, mirror audit, and the affected CL sync, EL sync, and restart acceptance scenarios using both op-node and kona-node. After 4dcdefc, the op-reth trie and ExEx tests and just lint were rerun. The acceptance scenarios were not.

Fixes https://github.com/ethereum-optimism/protocol-team/issues/354

@joshklop
joshklop requested a review from a team as a code owner September 25, 2026 20:48
@joshklop joshklop added rust Pull requests that update Rust code A-op-reth Area: op-reth labels Sep 25, 2026
@joshklop
joshklop force-pushed the joshklop/update-reth-v2.6.0 branch 5 times, most recently from 7b51ebc to becef55 Compare September 28, 2026 18:21
op-will
op-will previously approved these changes Sep 28, 2026
Comment thread rust/op-reth/crates/exex/src/lib.rs Outdated
Comment thread rust/op-reth/crates/node/tests/it/main.rs
recursion128 added a commit to Chaintable/leafage-evm that referenced this pull request Sep 29, 2026
- revm 36 -> 43.0.3, revm-inspectors 0.44, revm-bytecode 43, alloy-evm 0.39,
  alloy / alloy-contract 2.5, alloy-sol-types 1.7.3, plus alloy-chains/hardforks/rlp
- vendor op-revm (ported to revm 43 upstream in ethereum-optimism/optimism#23046)
  into crates/op-revm until a compatible op-revm is published on crates.io
- port all chain modules (arbitrum, tempo, bsc, polygon, cosmos, citrea, monad,
  rsk, moonbeam, iotex) and rpc to the new handler / gas / precompile /
  instruction APIs, preserving pre-Amsterdam behavior
- standalone: default mainnet-derived spec AMSTERDAM -> OSAKA (revm 43 AMSTERDAM
  enables Glamsterdam gas); keep --spec-id on the legacy revm 36 numbering;
  OpSpecId::OSAKA -> KARST
- bump rust-version to 1.95 and Docker RUST_VERSION to 1.97.1
- fix flaky cpu recorder / spawn_blocking_with_cancel tests
@joshklop
joshklop force-pushed the joshklop/update-reth-v2.6.0 branch from becef55 to 02ac617 Compare September 29, 2026 12:49
@op-will op-will self-assigned this Sep 29, 2026

@joshklop joshklop left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Full reth/revm/alloy update sweep found six runtime/build risks and two compatibility notes; details are inline. Coverage included all 283 reth commits, the complete revm/alloy ranges, both lockfiles, fork ancestry, and all changed mirror annotations. just mirrors stale --json and git diff --check passed; affected-package tests passed. The revm/asyncdb feature-unification failure was reproduced locally despite the standard CI matrix being green.

Comment thread rust/op-reth/crates/exex/src/lib.rs Outdated
Comment thread rust/op-reth/crates/rpc/src/eth/proofs.rs Outdated
Comment thread rust/op-reth/crates/evm/src/config.rs Outdated
Comment thread rust/Cargo.toml
Comment thread rust/Cargo.toml Outdated
Comment thread rust/Cargo.toml Outdated
Comment thread rust/Cargo.toml
Comment thread rust/op-reth/crates/consensus/src/lib.rs

@sebastianst sebastianst left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Review against docs/ai/reth-update-review.md, including the partitioned full-range sweep (#23063): every commit in reth 3a83ccc546..dfcb10454c (v2.5.2 fork base → v2.6.0), revm v115..v119, alloy-evm 0.38→0.39, revm-inspectors, alloy-eip7928, alloy-hardforks and reth-core 0.6→0.7. The results are a per-commit verdict ledger, the mirror funnel, and a check of the adaptation diff. Mirrors: all 63 advanced tags match their upstream diffs. Old fork cherry-picks are all contained in v2.6.0.

Four blocking findings. For each, a red test fails on this head and passes with the fix. Fixes and tests are ready to share.

1. [blocking, consensus] Isthmus withdrawals_root is wrong over a masked state trie.
parent_state() is now an OverlayStateProvider (reth f0166c32e2), and state masking is on by default (--engine.num-state-masking-blocks 30, bd61f3919e). Upstream OverlayStateProvider::storage_root (reth crates/storage/storage-overlay/src/provider.rs:573) builds the overlay but passes only its hashed storage to DbStorageRoot::overlay_root. That drops the overlay trie nodes and walks the DB storage trie directly. storage_proof and storage_multiproof have the same problem. Under partial persistence, disjointed_merge_batch skips DB trie nodes that the masking suffix overwrites. Their cached child hashes therefore predate the persisted hashed storage, and siblings outside the prefix set are hashed with stale values.

Ethereum never uses storage_root for consensus. OP does, twice: the validator's Isthmus check (node/src/engine.rs:149) and the sequencer's header (evm/src/build.rs:81). Each node's DB layout depends on its own persistence timing, so op-reth nodes can disagree with each other, not only with kona/op-program.

A regression test in consensus/src/validation/isthmus.rs writes L2ToL1MessagePasser storage across the persisted batch, the masking suffix and an in-memory block, over v1 and v2 storage. It compares withdrawals_root via OverlayStateProviderFactory::database_provider_ro() against a from-scratch root. The masked cases fail (0x9334cfa9…acc4 vs 0xa976ad4c…672a); the unmasked controls pass. The same scenario as an upstream storage-overlay test is red at v2.6.0 and green once storage_root/storage_proof/storage_multiproof read nodes through InMemoryTrieCursorFactory over the overlay nodes, with the full reth-storage-overlay suite passing.

The fix belongs upstream, then backported to the fork pin. Until then, the only mitigation I see is forcing num_state_masking_blocks = 0 in op-reth. The same flaw affects the conditional-tx storage roots (rpc/src/eth/ext.rs:93). eth_getProof uses proof and is not affected.

2. [blocking] op-reth proofs init seeds a corrupt proofs store after an unclean shutdown.
With masking on, a datadir left by a crash, OOM or SIGKILL, or a snapshot of a running node, has Finish.block_number at the tip. The hashed and trie tables, however, hold a disjointed merge at Finish.partial_state_trie. reth repairs that only at node launch (launch/common.rs:553). proofs init opens with RoInconsistent, anchors at chain_info().best_number and copies the tables unchecked (cli/src/commands/op_proofs/init.rs:161,179, trie/src/initialize.rs). This PR adapted the ExEx to partial_state_trie but not init.

A repro persists blocks via the real save_blocks with frontiers 6/3. Init returns Ok, seeding slot values from before the tip and a state root that differs from header #6. With V2 plus backfill (the default), backfill then fails with StateRootMismatch, and re-running init reports "already initialized", so the proofs dir must be deleted. With --proofs-history.skip-backfill or V1, the node silently serves wrong historical proofs; --proofs-history.verification-interval defaults to 0.

Suggested fix: InitializationJob::run reads the Finish checkpoint in its copy transaction and refuses when partial_state_trie < block_number, with an actionable error ("start op-reth node once and stop it cleanly"). Reading both in one transaction also closes the existing race between chain_info() and the copy.

3. [blocking] BAL disablement is incomplete (inline on node.rs).

4. [blocking, downstream API] Filtered flashblock log streams return nothing.
reth #26946 (1ca1201167) added if !filter.matches_bloom(header.logs_bloom()) { return Ok(vec![]) } to matching_block_logs_with_tx_hashes. The synthetic header in OpEthApi::flashblock_receipts_stream (rpc/src/eth/mod.rs:180) leaves logs_bloom zeroed. So since this bump, any filter with an address or topic yields no logs. Only the empty filter still works.

A unit test fails for the address and topic filters (0 logs, expected 1). It passes once the header carries alloy_primitives::logs_bloom(fb.metadata.receipts.values().flat_map(|r| r.logs())). Nothing in-tree calls the method (eth_subscribe logs uses upstream's canonical log_stream), so only downstream users of this public API are affected.

Follow-ups referenced in threads were closed. #23096 (+12 pending timestamp) and #23103 (pending logs in latest..pending) were closed unmerged after the replies pointing at them. Only issues #22685 and #23104 remain, and #23104 still names the closed PR. #23106 (proofs ExEx acks) is an open draft; see the inline note on exex/src/lib.rs, which shows the problem also applies in live mode.

Migration notes: missing items

  • Startup failure. --engine.persistence-threshold ≤ 35 now fails startup unless --engine.num-state-masking-blocks 0 is also set (EngineArgs::validate). This includes the old default of 7 when it is pinned via flag or RETH_ENGINE_PERSISTENCE_THRESHOLD.
  • Env vars. The engine flags now also read RETH_ENGINE_PERSISTENCE_THRESHOLD and RETH_ENGINE_NUM_STATE_MASKING_BLOCKS.
  • Priority fee. --txpool.minimum-priority-fee now also rejects local and private (conditional) txs (74ce7f1b2b).
  • Tx fetcher. New per-peer cap of 4096 announced hashes, with no CLI flag. --max-tx-pending-fetch now also counts inflight hashes (b2d7bd7f3f).
  • eth_getLogs. Errors instead of [] on missing receipts, for example pre-Bedrock ranges on init-state --without-ovm datadirs (d5cd94331e). Also errors when fromBlock is beyond head (1e9a9438ad).
  • RocksDB. max_open_files is now -1 (keep all open) when RLIMIT_NOFILE ≥ 131072 (853a42db1c).
  • Tx pool. --txpool.max-batch-size 0 is now rejected.

payload_handoff.rs removal. The removal is fine, but the stated reason isn't quite right. Upstream #26917 (68877d5fd7) removed the persistence lease/handoff mechanism entirely, including #26708's own test, rather than the cherry-pick becoming redundant.

The revm/asyncdb dismissal holds: the feature is enabled in neither lock nor in op-rbuilder. Other non-blocking notes are inline.

🤖 Co-created with Claude Opus 5.5

Comment thread rust/op-reth/crates/node/src/node.rs
Comment thread rust/op-reth/crates/exex/src/lib.rs Outdated
Comment thread rust/op-reth/crates/consensus/Cargo.toml
Comment thread rust/op-reth/crates/consensus/src/validation/mod.rs Outdated
Comment thread rust/op-reth/crates/rpc/src/eth/proofs.rs Outdated
@sebastianst sebastianst mentioned this pull request Oct 14, 2026
7 tasks
This was referenced Oct 14, 2026

This branch has not been deployed

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

Labels

A-op-reth Area: op-reth rust Pull requests that update Rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants