Skip to content

op-reth proofs history can lag permanently after clean shutdown #22089

Description

@HDauven

Description

With op-reth v2.4.0 and v2 proofs history enabled, a clean SIGTERM can leave the persisted proofs window behind the execution-chain tip. On restart the gap is permanent: ExEx notifications for the missing blocks are not replayed, proofs init is a no-op for an initialized store and debug_proofsSyncStatus.latest remains below eth_blockNumber. Rebuilding the proofs store from the chain DB repairs it.

Reproduction

  1. Initialize v2 proofs history and run op-reth with --proofs-history while an op-node sequencer produces blocks.
  2. Observe a small live lag, for example execution tip 3642 and persisted proof latest 3640.
  3. Send SIGTERM and wait for op-reth to exit cleanly.
  4. Restart against the same execution DB and proofs DB.
  5. The execution tip remains 3642, while debug_proofsSyncStatus.latest remains 3640 indefinitely. Running op-reth proofs init does not advance it because the store is already initialized.

This was reproduced with the official op-reth:v2.4.0 image. The same shutdown path is still present on current develop.

Suspected cause

OpProofsExEx::handle_notification emits ExExEvent::FinishedHeight after the collector action returns, but that action only buffers the block; persistence happens asynchronously and below-threshold blocks can remain in memory. The engine shutdown path drains only an already in-flight save and does not schedule the remaining memory buffer for persistence. The ExEx WAL therefore considers those notifications finished even though their proof state was never persisted.

Relevant code:

  • rust/op-reth/crates/exex/src/lib.rs: FinishedHeight is emitted after queueing collector work.
  • rust/op-reth/crates/trie/src/engine/runner.rs: shutdown calls only drain_persistence().
  • rust/op-reth/crates/trie/src/engine/state.rs: drain_persistence() waits for an existing save but does not start one for buffered blocks.

Expected behavior

A clean shutdown should persist all buffered proof-history blocks before the collector exits and before a completed ExEx height can become unrecoverable. A regression test should cover shutdown with fewer buffered blocks than the persistence threshold and verify that the restarted proof window reaches the execution tip.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions