Commit c1e6229
authored
fix(prover-node): rebuild pruned checkpoint provers and recover the epoch (#24436)
Resolves A-1290.
## Problem
A `CheckpointProver`'s sub-tree work forks world-state per block. When
an L1 reorg prunes a base block, those fork reads fault and the prover
permanently rejects its one-shot `blockProofs` promise.
The store keeps the prover alive across a prune (`markPruned`) so a
re-add of identical content can reuse its in-flight work. But a prune
that removes the checkpoint also breaks the fork reads, so that reuse
only ever hands back a poisoned prover: a re-add or a full
`EpochSession` recreate re-references the same rejected `blockProofs`
and fails immediately. The affected node then silently abandons the
epoch until a process restart (a healthy prover elsewhere still proves
it, so it's not a network stall).
## Fix
**Drop the reuse machinery — a pruned prover cannot survive, so rebuild
instead of reuse.**
- `CheckpointStore.cancelAndRemoveAboveBlock` cancels and **removes**
orphaned provers (replacing `markPrunedAboveBlock`); a re-add builds a
fresh prover with a fresh `blockProofs`.
- Removed the `pruned` flag / `markPruned` / `markCanonical` from
`CheckpointProver`, and the `SlotWatcher` that only reaped lingering
pruned provers.
- `listCanonical` / `addOrUpdate` simplified — every prover in the store
is now canonical.
**Recover the epoch by rebuilding on re-add, rather than trying to
prevent the terminal state.**
A prune unwinds world-state as soon as it's detected — before the
prover-node cancels the affected session — so a checkpoint prover
mid-fork faults while still live and its session goes terminal `failed`.
That race is inherent (the world-state rejection and the prover being
cancelled are unordered), so instead of trying to reclassify it as a
cancellation, we make the terminal state harmless:
- `SessionManager.openFullSessionIfReady` no longer treats a terminal
session as "already open" — it drops it and rebuilds. So re-adding an
epoch's checkpoints reopens a fresh live session over fresh provers, via
the checkpoint/prune triggers (ungated by the tick high-water mark).
This reopen depends on the store no longer holding the poisoned prover:
with the reuse machinery gone the rebuilt session gets a fresh prover
with a healthy `blockProofs`, so it can actually prove rather than
re-inheriting the rejected one.
- `runSession` skips the failure-upload when the session's checkpoints
no longer match canonical content — a prune-invalidated failure isn't a
genuine proving failure, so it no longer emits a spurious post-mortem
upload / alert.
The only non-recovered case is "content pruned and never re-added"
(chain stops publishing that epoch's checkpoints) — there's nothing to
prove on this node then, so abandoning the epoch is correct.
**Cancel the pruned prover's in-flight work promptly.**
`CheckpointProver` now threads its abort signal into
`PublicProcessor.process`, so a prune-driven cancel stops the current
block's public execution immediately instead of running it to completion
before the next `signal.aborted` check. This is independent of the
recovery logic above — it just avoids wasting CPU re-executing a block
whose checkpoint is being discarded. The in-flight block has not yet
enqueued a broker proof, so aborting it loses no reusable work.
### Note: broker-level proof reuse is unaffected
Removing the `CheckpointProver`-level reuse does not waste proving work.
The expensive part — the SNARK proofs — is cached in the proving broker,
content-addressed by job id, independent of world-state.
`cancelJobsOnStop` defaults to `false`, so cancelling a prover does not
abort its broker jobs; on an identical re-add the fresh prover
regenerates identical inputs, and the broker dedups against the cached
jobs/results (bounded by the broker's per-epoch cleanup). The reuse we
deleted was witness-generation reuse, whose world-state forks cannot
survive a prune anyway.
## Testing
- `session-manager.test.ts`: pins the retry/recovery invariant — the
periodic tick does not re-attempt a failed epoch (gated by
`lastTickEpoch`), but a checkpoint re-add recovers it (ungated); a
`failed` session's epoch is reopened once its checkpoints are re-added;
a genuine proving failure still uploads a post-mortem; a failure
coinciding with a canonical content change (prune) skips the upload.
(Red/green verified for both the gate and the upload suppression.)
- `checkpoint-store.test.ts` / `prover-node.test.ts`: pruned provers are
cancelled and removed (not flagged); a re-add builds a fresh prover.
- `checkpoint-prover.test.ts`: cancelling a prover mid-block aborts the
signal its public execution is running under (red/green verified).
- Full prover-node suite passes (166 tests); package typechecks clean;
lint OK.
- Updated `optimistic.parallel.test.ts` (the e2e that spawned this
issue) to the cancelled+removed semantics.
## Notes
- No operator/contract-dev-facing config or API changed, so no changelog
entry.
- The terminal `failed` state is not prevented, only recovered from: the
world-state unwind and the prover cancellation are unordered, so the
failure can't be reliably reclassified from the session side. Recovering
on re-add is deterministic and needs no such race to be won.1 parent 2c4d593 commit c1e6229
12 files changed
Lines changed: 408 additions & 410 deletions
File tree
- yarn-project
- end-to-end/src/single-node/proving
- prover-node
- src
- job
Lines changed: 9 additions & 11 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
338 | 338 | | |
339 | 339 | | |
340 | 340 | | |
341 | | - | |
342 | | - | |
343 | | - | |
344 | | - | |
345 | | - | |
346 | | - | |
347 | | - | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
348 | 346 | | |
349 | 347 | | |
350 | 348 | | |
351 | 349 | | |
352 | 350 | | |
353 | 351 | | |
354 | | - | |
| 352 | + | |
355 | 353 | | |
356 | | - | |
| 354 | + | |
357 | 355 | | |
358 | 356 | | |
359 | 357 | | |
| |||
383 | 381 | | |
384 | 382 | | |
385 | 383 | | |
386 | | - | |
| 384 | + | |
387 | 385 | | |
388 | 386 | | |
389 | 387 | | |
| |||
875 | 873 | | |
876 | 874 | | |
877 | 875 | | |
878 | | - | |
| 876 | + | |
879 | 877 | | |
880 | 878 | | |
881 | 879 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
38 | | - | |
39 | 38 | | |
40 | 39 | | |
41 | 40 | | |
| |||
56 | 55 | | |
57 | 56 | | |
58 | 57 | | |
59 | | - | |
60 | | - | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
61 | 61 | | |
62 | 62 | | |
63 | 63 | | |
| |||
81 | 81 | | |
82 | 82 | | |
83 | 83 | | |
84 | | - | |
85 | | - | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
86 | 88 | | |
87 | 89 | | |
88 | 90 | | |
89 | 91 | | |
90 | 92 | | |
91 | 93 | | |
92 | | - | |
| 94 | + | |
| 95 | + | |
93 | 96 | | |
94 | 97 | | |
95 | | - | |
96 | | - | |
97 | | - | |
98 | | - | |
99 | | - | |
100 | | - | |
101 | 98 | | |
102 | 99 | | |
103 | | - | |
104 | | - | |
105 | | - | |
106 | | - | |
107 | | - | |
108 | | - | |
109 | | - | |
110 | | - | |
111 | | - | |
112 | | - | |
113 | | - | |
114 | | - | |
115 | | - | |
116 | | - | |
117 | | - | |
118 | | - | |
119 | | - | |
120 | | - | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
121 | 116 | | |
122 | 117 | | |
123 | 118 | | |
| |||
288 | 283 | | |
289 | 284 | | |
290 | 285 | | |
291 | | - | |
292 | | - | |
| 286 | + | |
| 287 | + | |
293 | 288 | | |
294 | 289 | | |
295 | 290 | | |
| |||
306 | 301 | | |
307 | 302 | | |
308 | 303 | | |
309 | | - | |
310 | | - | |
311 | | - | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
312 | 307 | | |
313 | 308 | | |
314 | 309 | | |
| |||
371 | 366 | | |
372 | 367 | | |
373 | 368 | | |
374 | | - | |
375 | | - | |
376 | | - | |
| 369 | + | |
| 370 | + | |
377 | 371 | | |
378 | | - | |
379 | | - | |
380 | | - | |
381 | | - | |
382 | | - | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
383 | 377 | | |
384 | 378 | | |
385 | 379 | | |
386 | | - | |
387 | | - | |
388 | | - | |
389 | | - | |
390 | | - | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
391 | 384 | | |
392 | | - | |
393 | | - | |
394 | | - | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
395 | 388 | | |
396 | | - | |
397 | | - | |
| 389 | + | |
| 390 | + | |
398 | 391 | | |
399 | 392 | | |
400 | 393 | | |
| |||
466 | 459 | | |
467 | 460 | | |
468 | 461 | | |
469 | | - | |
| 462 | + | |
470 | 463 | | |
471 | | - | |
472 | | - | |
473 | | - | |
474 | | - | |
475 | | - | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
476 | 469 | | |
477 | 470 | | |
478 | 471 | | |
479 | 472 | | |
480 | 473 | | |
481 | | - | |
| 474 | + | |
482 | 475 | | |
483 | 476 | | |
484 | 477 | | |
| |||
0 commit comments