Repository navigation
op-reth: acceptance test for the Isthmus withdrawals root across persistence cycles #23398
Description
What: An acceptance test with a withdrawal in nearly every block for longer than a persistence cycle, asserting every header's withdrawalsRoot matches the message passer's storage root on every node.
Why: Since Isthmus the withdrawals root is a storage root computed through reth's overlay state providers, which the bump rewrites, with an in-memory window of about 55 blocks instead of about 12. docs/ai/reth-update-review.md (precondition 6) requires testing storage roots with persistence engaged, and the only acceptance test does one withdrawal.
Description
Mixed runtime: op-reth sequencer, an op-reth follower without proofs history (sysgo.OpRethWithoutProofsHistory()), an op-geth follower. Initiate a withdrawal in every block from several EOAs in parallel for at least twice the threshold in blocks. For every block compare withdrawalsRoot across all nodes' headers, and on the op-reth follower compare it with eth_getProof's storage hash for L2ToL1MessagePasser (VerifyWithdrawalHashChangedIn is the seed). Assert the run covers at least one persistence boundary (block count greater than threshold plus buffer).
Matrix for this test
Threshold {7, 50} x masking {0, 30 when reachable} x CL {op-node, kona-node}.
Verification criterion
- Green on
developand on rust!: update reth to v2.6.0 #23046. - The assertion that a persistence boundary was crossed is part of the test, not a comment.
Shared context for whoever picks this up
- The bump. rust!: update reth to v2.6.0 #23046 (reth v2.6.0), tracked in ethereum-optimism/protocol-team#354. The PR description lists the migration notes: changed defaults, rejected flags and the upstream behaviour changes. The persistence side is explained in the internal write-up Proofs exex, state masking, and persistence.
- What changes under op-reth with no diff in our tree. reth's persistence threshold default moves from 7 to 50 (now an in-memory block count; backpressure 16 to 100), so an unclean stop loses up to the threshold plus
--engine.memory-block-buffer-targetblocks, about 55 instead of about 12. State masking exists in reth 2.6 but op-reth forces it to 0 (ethereum-optimism/protocol-team#457). Forkchoice updates whose safe or finalized hash is not on the head's chain are rejected (reth#27247, reth#27429).--txpool.minimum-priority-feenow also applies to local and conditional transactions (reth#26861).eth_getLogsreturns error 4444 for a range whose receipts are missing and -32602 for afromBlockbeyond the head (reth#27002, reth#26891). Peers negotiate eth/71 and the transaction fetcher was rewritten (reth#26924). Block access list flags and RPC methods are rejected. The deferred persistence handoff from the fork fix reth#26708 is replaced by upstream's overlay snapshots, and its regression testrust/op-reth/crates/node/tests/it/payload_handoff.rswas deleted. - Existing coverage. CI on the bump head is green for
memory-all-opn-op-reth,memory-all-kona-op-reth,rust-e2e-restart,op-reth-e2e-sysgo-testsandop-reth-integration-tests. Acceptance tests restart nodes only gracefully (nothing sends SIGKILL), several EL-restart and EL-sync tests areSkipOnOpReth, no test crosses a persistence boundary on purpose, andop-acceptance-tests/tests/flashblockshas no tests. - Devstack seams.
sysgo.OpRethWithBinaryselects a per-node binary (resolved throughRUST_BINARY_PATH_<NAME>),OpRethWithExtraArgsadds flags, and a follower gets its options throughMixedSingleChainNodeSpec.OpRethOpts(presets.WithOpRethOptionreaches only sequencer-capable ELs). Missing today: a hard kill (SubProcess.Stop(false)only waits; addKill()), an L2 CL sync-mode option in the mixed runtime, and a hook to assert on op-reth log lines. op-reth: acceptance test for proofs history across an unclean shutdown #23380 adds the kill seam and op-reth: add a windowed proof oracle to the devstack DSL #23379 the proof oracle; depend on them rather than duplicating. - Conventions.
docs/ai/writing-acceptance-tests.md,docs/ai/acceptance-tests.md,docs/ai/rust-dev.md, anddocs/ai/reth-update-review.md(precondition 6: a per-account storage root is consensus on OP, so test it with persistence engaged). Scoped commits; runrust-code-reviewerorgo-code-reviewerbefore opening the PR. - Target branch. Write against
developwhere the behaviour exists there. A test that only makes sense on the bump is written against rust!: update reth to v2.6.0 #23046's branch and says so in the PR. A test that fails for a tracked reason is kept and skipped naming the issue.
Parameter matrix (applies to every sub-issue)
Persistence-related tests run over reth threshold {7 (develop), 50 (bump)} via --engine.persistence-threshold, masking {0, 30 when reachable (ethereum-optimism/protocol-team#457)}, and where the CL matters {op-node, kona-node} (CI runs both). Go tests use table-driven subtests with the configuration in the subtest name; Rust tests use rstest tables, one case per line. Every skipped cell says why in the skip message.
Activity