Skip to content

fix(proofs): harden proof history across reorgs#223

Draft
davidtaikocha wants to merge 27 commits into
feat/reth-v2.4.0-jitfrom
codex/proof-history-correctness-v2
Draft

fix(proofs): harden proof history across reorgs#223
davidtaikocha wants to merge 27 commits into
feat/reth-v2.4.0-jitfrom
codex/proof-history-correctness-v2

Conversation

@davidtaikocha

Copy link
Copy Markdown
Collaborator

Summary

  • cut proof history over to upstream op-reth V2 initialization, backfill, pruning, and engine APIs
  • harden canonical notification handling, lag recovery, persisted reorg barriers, and receiver replacement across reorg, revert, and recommit sequences
  • pin proof RPC work to exact canonical identities and install the proof override on both public and authenticated RPC modules
  • reuse upstream proof execution limits and reject invalid zero prune intervals

Compatibility and design notes

  • Existing non-empty V1 proof-history stores are refused with an actionable migration error; empty stores can cut over to V2.
  • The retained earliest proof block is an immutable boundary. Reorgs that replace it fail closed and require rebuilding proof storage.
  • Reth v2.4.0 improves the upstream pieces this implementation now reuses, but it still does not provide the persistent per-block OP proof-history window or the Taiko RPC retention semantics, so the sidecar remains necessary.

Reorg correctness

  • readiness stays gated until the canonical database and committed proof storage cross the same finite barrier
  • recovery subscribes before capturing a live target, so superseding notifications are represented or remain queued
  • ordinary pending commits do not chase the moving tip; pure-revert recommits replay once and rebase safely
  • stationary persisted-head polling is deduplicated so it cannot starve the upstream idle flush
  • canonical targets, proof progress, and queued pre-snapshot reorgs have dedicated regression coverage

Validation

  • just fmt
  • just clippy
  • just test: 352 passed
  • focused proof-history tests: 122 passed
  • RPC tests: 76 passed
  • CLI tests: 11 passed

Upstream reference: https://github.com/paradigmxyz/reth/releases/tag/v2.4.0

davidtaikocha and others added 5 commits July 18, 2026 14:11
Disable reth's five-minute read-transaction timeout on every main-database
transaction consumed by the initial state copy and the window backfill;
both outlive it and the abort crash-looped the node mid-initialization.

Treat a stored anchor or proof latest above the persisted best as a wait
state instead of demanding a wipe: after an unclean shutdown the driver
re-derives that gap on its own. A reorged stored latest at a persisted
height is left to startup reconciliation's suffix unwind for the same
reason.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The commit path pinned its decisions to a persisted-only canonical
snapshot and the flushed proof head. That combination panicked the node
when a queued stale commit met an already-persisted reorg, and in steady
state it dropped nearly every live notification's precomputed trie data
because the tip is rarely persisted at processing time, degrading the
sidecar to poll-driven full re-execution.

The upstream engine already deduplicates against its own buffered tip,
turns gaps into an internal sync target, and reports a same-height
branch conflict as ParentHashMismatch. Forward every exact notification
block, treat that conflict as a routine reorg-ordering race that defers
to canonical sync, and keep all other engine failures fatal.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two holes remained around never-delivered reorg notifications. Startup
subscribed after reth's consensus tasks were already live and then opened
readiness from persisted-state reconciliation alone, so a same-height
reorg published before the subscription could bless a displaced branch.
And a commit conflicting with the engine's branch fell back to a
number-only sync target, which cannot repair a same-height hash
divergence: readiness stayed off with no path back.

Gate startup readiness behind the live canonical target captured right
after subscribing, exactly like lag recovery. Surface an engine branch
conflict as its own routing outcome and recover it by replacing the
receiver and the generation, rebasing readiness onto a fresh
post-subscribe live target.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Proof and witness requests resolved their block and opened a historical
state provider before queueing for Reth's shared proof permit, so a
saturated pool left every queued request pinning an MDBX read
transaction. Take the permit first, then resolve, then hand the permit
to the detached blocking task, restoring the permit-first ordering the
base implementation and upstream reth use.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant