Skip to content

fix(archiver): reconcile local blocks with L1 checkpoints by block number#23461

Merged
spalladino merged 1 commit into
merge-train/spartanfrom
spl/archiver-prune-mismatching-by-block-number
May 21, 2026
Merged

fix(archiver): reconcile local blocks with L1 checkpoints by block number#23461
spalladino merged 1 commit into
merge-train/spartanfrom
spl/archiver-prune-mismatching-by-block-number

Conversation

@spalladino
Copy link
Copy Markdown
Contributor

Motivation

When the sequencer locally proposed block N at slot S1 and L1 mined a different block N at slot S2 (same block number, different slot), the archiver's reconciliation in pruneMismatchingLocalBlocks joined local↔checkpoint blocks by slot and missed the conflict. The local block was never pruned and the subsequent re-apply of L1's block N threw Contract instance ... already exists, cannot add again at block N. The archiver's serial queue then retried in a loop and wedged the data store — this is the cause of the e2e flake at yarn-project/end-to-end/src/composed/ha/e2e_ha_full.test.ts:693.

Approach

pruneMismatchingLocalBlocks now keys conflict detection on blockNumber only, so a same-number-different-slot block is correctly detected as a conflict and pruned. The per-checkpoint trailing prune (which handles "local has extra blocks at the same slot as the published checkpoint") stays scoped by slot so speculative blocks at later slots that belong to a pending proposed checkpoint are preserved — this keeps the pipelining model in promoteProposedToCheckpointed intact. After any prune, pending proposed checkpoints from the offending checkpoint number onwards are evicted so they do not dangle while referencing removed blocks.

Changes

  • archiver: pruneMismatchingLocalBlocks joins by blockNumber only; trailing slot-scoped prune unchanged; new evictProposedCheckpointsForPrunedBlocks helper clears stale pending proposed checkpoints after a prune.
  • archiver (tests): four new regression tests in data_store_updater.test.ts covering the e2e_ha scenario, the prune-by-number path without contract data, pipelining preservation, and eviction of higher-numbered proposed checkpoints chaining off pruned blocks.

…mber, not slot

When the sequencer locally proposed block N at slot S1 and L1 mined a
different block N at slot S2, pruneMismatchingLocalBlocks filtered by
slot and missed the conflict, so the local block (and its contract data)
was never pruned. The subsequent re-apply of L1's block N then threw
"Contract instance ... already exists" and the archiver's serial queue
got stuck retrying.

Fixed by reconciling on blockNumber. The per-checkpoint trailing prune
remains scoped by slot so speculative blocks at later slots (which may
belong to a pending proposed checkpoint) are preserved. Also evict
pending proposed checkpoints that referenced pruned blocks so they do
not dangle after a conflict prune.

Regression tests added in data_store_updater.test.ts.
@spalladino spalladino force-pushed the spl/archiver-prune-mismatching-by-block-number branch from c14aaa6 to 50d22cd Compare May 21, 2026 10:28
@spalladino spalladino changed the title fix(archiver): reconcile local blocks with L1 checkpoints by block number, not slot fix(archiver): reconcile local blocks with L1 checkpoints by block number May 21, 2026
@PhilWindle PhilWindle enabled auto-merge (squash) May 21, 2026 10:48
@spalladino spalladino disabled auto-merge May 21, 2026 15:59
@spalladino spalladino merged commit 65989b5 into merge-train/spartan May 21, 2026
17 checks passed
@spalladino spalladino deleted the spl/archiver-prune-mismatching-by-block-number branch May 21, 2026 15:59
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