You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- README: replace the stale prune model (markPruned/markCanonical/SlotWatcher,
in-flight-work reuse) with cancel-and-remove-on-prune + rebuild-on-re-add.
- CheckpointStore.stop() now awaits teardowns still in flight for provers already
removed by a prune or reap (tracked in a self-clearing set), not just live ones.
- Drop the now-redundant "canonical" method naming (every prover in the store is
canonical): listCanonical* -> list*, canonicalCheckpointsForSpec -> checkpointsForSpec.
- Remove the openFullSessionIfReady terminal-replace guard; recreateInvalidSessions
already deletes terminal sessions before it runs.
- Note that the failure-upload suppression is best-effort and inherently races the
prune (the store lags the world-state unwind).
State: epoch N has checkpoints c1..c4 all canonical (slots s1..s4). `fullSessions[N]`
375
-
holds `EpochSession`**A** with spec `{kind:'full', N, fromSlot:s1, toSlot:s4}`, referencing
376
-
checkpoints `[c1, c2, c3, c4]`.
369
+
State: epoch N has checkpoints c1..c4 (slots s1..s4). `fullSessions[N]` holds `EpochSession`
370
+
**A** with spec `{kind:'full', N, fromSlot:s1, toSlot:s4}`, referencing `[c1, c2, c3, c4]`.
377
371
378
-
1.**chain-pruned arrives, target c3.**Store flips c4 to pruned. Reconcile fires:
379
-
for `EpochSession` A, canonical content for `(s1, s4)` is now `[c1, c2, c3]` (c4 pruned).
380
-
The frozen set `[c1, c2, c3, c4]`no longer matches → `A.cancel('canonical content
381
-
changed')`. Epoch N still complete on L1 → reconcile constructs`EpochSession` **B** with
382
-
the same spec `{full, N, s1, s4}` but checkpoints `[c1, c2, c3]`.
372
+
1.**chain-pruned arrives, target c3.**The store cancels and removes c4 (its last block is
373
+
above the prune target). Reconcile fires: `EpochSession` A's frozen set `[c1, c2, c3, c4]`
374
+
includes the now-cancelled c4, so it no longer matches the store's `[c1, c2, c3]` →
375
+
`A.cancel('canonical content changed')`. Epoch N still complete on L1 → reconcile constructs
376
+
`EpochSession`**B** with the same spec `{full, N, s1, s4}` but checkpoints `[c1, c2, c3]`.
383
377
384
378
2.**`EpochSession` B starts top-tree proving over [c1, c2, c3].**
385
379
386
-
3.**chain-checkpointed arrives, target c4_re (same content key as old c4).** The
387
-
store finds the existing `CheckpointProver` at `(c4.number, s4, c4.archive.root)`
388
-
and calls `markCanonical()`. The sub-tree work that never stopped is visible to
389
-
`EpochSession`s again. (A re-add with *different* content would have a different archive
390
-
root and so get a fresh `CheckpointProver` instead.)
380
+
3.**chain-checkpointed arrives, target c4_re (same content key as old c4).** The old c4
381
+
prover was removed on the prune, so the store constructs a **fresh**`CheckpointProver` for
382
+
c4_re and starts its sub-tree work from scratch. (Its block-rollup jobs are content-addressed
383
+
in the proving broker, so any the old c4 already completed are reused rather than re-proved.)
391
384
392
-
4.**Reconcile fires.**`EpochSession` B's canonical content for `(s1, s4)` is now `[c1, c2,
393
-
c3, c4]`, doesn't match its frozen `[c1, c2, c3]` → `B.cancel(...)`. Construct
394
-
`EpochSession`**C** with same spec but checkpoints `[c1, c2, c3, c4]`.
385
+
4.**Reconcile fires.**`EpochSession` B's content for `(s1, s4)` is now `[c1, c2, c3, c4_re]`,
386
+
doesn't match its frozen `[c1, c2, c3]` → `B.cancel(...)`. Construct`EpochSession`**C** with
387
+
the same spec but checkpoints `[c1, c2, c3, c4_re]`.
395
388
396
-
5.**`EpochSession` C reuses the long-lived c1..c4`CheckpointProver` instances.** Sub-tree
397
-
work may already be complete; only the top-tree is recomputed. The chonk cache
389
+
5.**`EpochSession` C reuses the long-lived c1..c3`CheckpointProver` instances and the fresh
390
+
c4_re.** Only c4_re's witnesses are regenerated; the top-tree is recomputed. The chonk cache
398
391
survived the reorg because no epoch in this range has expired yet.
399
392
400
393
@@ -466,19 +459,19 @@ Keying by tx hash makes the cache survive any reorg up to finality; releasing on
466
459
finality means we don't grow the cache indefinitely while still keeping every
467
460
reorg-relevant proof.
468
461
469
-
### Why does the slot watcher only reap pruned `CheckpointProver`s?
462
+
### Why is a pruned `CheckpointProver` removed rather than kept for a possible re-add?
470
463
471
-
Canonical `CheckpointProver`s can't be reaped on a slot heuristic — they're still part of the
472
-
proven-chain story. Pruned `CheckpointProver`s, on the other hand, are only kept around in
473
-
case the chain re-adds the same content; once the synced slot has moved past, that
474
-
re-add is impossible, and the `CheckpointProver` can go. Finality is the right signal for
475
-
canonical reaping, because finality is the only state that rules out future reorgs.
464
+
A prover's sub-tree work forks world-state per block, and an L1 prune of a base block faults
465
+
those in-flight reads — so the work cannot survive the prune, and there is nothing to preserve
466
+
by keeping the prover around. Removing it on prune and rebuilding on re-add is therefore both
467
+
correct and simpler; the expensive block-rollup proofs are still reused when content re-appears,
468
+
because the proving broker is content-addressed independently of the prover's lifetime.
476
469
477
470
## Configuration
478
471
479
472
| Env var | Description |
480
473
|---|---|
481
-
|`PROVER_NODE_POLLING_INTERVAL_MS`| Polling interval for the L2BlockStream, the checkpoint-store slot watcher, and the SessionManager periodic tick. Default 1000 ms. |
474
+
|`PROVER_NODE_POLLING_INTERVAL_MS`| Polling interval for the L2BlockStream and the SessionManager periodic tick. Default 1000 ms. |
482
475
|`PROVER_NODE_MAX_PENDING_JOBS`| Cap on the number of non-terminal `EpochSession`s (full + partial). When at limit, reconcile defers opening new full `EpochSession`s; explicit `startProof` calls throw. |
483
476
|`PROVER_NODE_EPOCH_PROVING_DELAY_MS`| Optional sleep at the start of each `EpochSession`, before the TopTreeJob is constructed. Used in tests to give late events time to land. |
484
477
|`TX_GATHERING_TIMEOUT_MS`| Per-block tx gather deadline used by each `CheckpointProver`. |
0 commit comments