@aztec/prover-node 5.0.0-nightly.20260615 → 5.0.0-nightly.20260617

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import type { CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
1
+ import type { BlockNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
2
2
  import { type LoggerBindings } from '@aztec/foundation/log';
3
3
  import type { L2BlockSource } from '@aztec/stdlib/block';
4
4
  import type { Checkpoint } from '@aztec/stdlib/checkpoint';
@@ -42,11 +42,15 @@ export declare class CheckpointStore {
42
42
  */
43
43
  addOrUpdate(checkpoint: Checkpoint, data: RegisterCheckpointData): Promise<CheckpointProver>;
44
44
  /**
45
- * Marks every canonical prover whose checkpoint number is strictly greater than
46
- * `prunedNumber` as pruned. Sub-tree work keeps running so a re-add of the same
47
- * content can pick it up. Returns the affected provers.
45
+ * Marks every canonical prover that holds a block above the prune target as pruned. A checkpoint is orphaned by a
46
+ * prune to block `targetBlockNumber` iff its last block sits above the target — including a checkpoint whose range
47
+ * straddles the target (partially orphaned), which block-range marking catches without boundary ambiguity. Keying
48
+ * off the surviving block number (rather than a checkpoint number) is correct even when the source has already
49
+ * re-checkpointed past the divergence: the prune event reports the highest surviving block, which by construction
50
+ * survives on the source, whereas the source's current checkpointed tip can sit above the prune target.
51
+ * Sub-tree work keeps running so a re-add of the same content can pick it up. Returns the affected provers.
48
52
  */
49
- markPrunedAfter(prunedNumber: CheckpointNumber): CheckpointProver[];
53
+ markPrunedAboveBlock(targetBlockNumber: BlockNumber): CheckpointProver[];
50
54
  /**
51
55
  * Drops canonical (non-pruned) provers whose epoch is at or below the supplied expired
52
56
  * epoch. Once an epoch's proof-submission window has closed, its proof can no longer be
@@ -80,4 +84,4 @@ export declare class CheckpointStore {
80
84
  }
81
85
  /** Sub-set of `L1RollupConstants` actually consumed by the store's slot helpers. */
82
86
  export type CheckpointStoreL1Constants = Pick<L1RollupConstants, 'epochDuration'>;
83
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlY2twb2ludC1zdG9yZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NoZWNrcG9pbnQtc3RvcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsZ0JBQWdCLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2pHLE9BQU8sRUFBZSxLQUFLLGNBQWMsRUFBZ0IsTUFBTSx1QkFBdUIsQ0FBQztBQUV2RixPQUFPLEtBQUssRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN6RCxPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsS0FBSyxpQkFBaUIsRUFBd0MsTUFBTSw2QkFBNkIsQ0FBQztBQUUzRyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsS0FBSyxvQkFBb0IsRUFBRSxLQUFLLG9CQUFvQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFcEgsOEdBQThHO0FBQzlHLE1BQU0sTUFBTSxzQkFBc0IsR0FBRyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsWUFBWSxHQUFHLGFBQWEsQ0FBQyxDQUFDO0FBRTlGLG1GQUFtRjtBQUNuRixNQUFNLE1BQU0sdUJBQXVCLEdBQUcsQ0FBQyxJQUFJLEVBQUUsb0JBQW9CLEVBQUUsSUFBSSxFQUFFLG9CQUFvQixLQUFLLGdCQUFnQixDQUFDO0FBRW5IOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxxQkFBYSxlQUFlO0lBTXhCLE9BQU8sQ0FBQyxRQUFRLENBQUMsYUFBYTtJQUM5QixPQUFPLENBQUMsUUFBUSxDQUFDLFVBQVU7SUFDM0IsT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPO0lBRXhCLE9BQU8sQ0FBQyxRQUFRLENBQUMsZUFBZTtJQVRsQyxPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBdUM7SUFDL0QsT0FBTyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQWlCO0lBQzdDLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFTO0lBRTdCLFlBQ21CLGFBQWEsRUFBRSxJQUFJLENBQUMsYUFBYSxFQUFFLHVCQUF1QixHQUFHLGdCQUFnQixDQUFDLEVBQzlFLFVBQVUsRUFBRSxJQUFJLENBQUMsb0JBQW9CLEVBQUUsS0FBSyxDQUFDLEVBQzdDLE9BQU8sRUFBRTtRQUFFLHlCQUF5QixFQUFFLE1BQU0sQ0FBQTtLQUFFLEVBQy9ELFFBQVEsQ0FBQyxFQUFFLGNBQWMsRUFDUixlQUFlLEdBQUUsdUJBQTBFLEVBUTdHO0lBRU0sS0FBSyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FHNUI7SUFFWSxJQUFJLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQVNqQztJQUVEOzs7O09BSUc7SUFDVSxXQUFXLENBQUMsVUFBVSxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsc0JBQXNCLEdBQUcsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBMEJ4RztJQUVEOzs7O09BSUc7SUFDSSxlQUFlLENBQUMsWUFBWSxFQUFFLGdCQUFnQixHQUFHLGdCQUFnQixFQUFFLENBU3pFO0lBRUQ7Ozs7T0FJRztJQUNJLFdBQVcsQ0FBQyxZQUFZLEVBQUUsV0FBVyxHQUFHLElBQUksQ0FvQmxEO0lBRUQsNkRBQTZEO0lBQ3RELEdBQUcsQ0FBQyxFQUFFLEVBQUUsTUFBTSxHQUFHLGdCQUFnQixHQUFHLFNBQVMsQ0FFbkQ7SUFFRCxrR0FBa0c7SUFDM0YsZUFBZSxDQUFDLFVBQVUsRUFBRSxVQUFVLEdBQUcsZ0JBQWdCLEdBQUcsU0FBUyxDQUUzRTtJQUVELHNGQUFzRjtJQUMvRSxPQUFPLElBQUksZ0JBQWdCLEVBQUUsQ0FFbkM7SUFFRCxnRkFBZ0Y7SUFDekUsYUFBYSxJQUFJLGdCQUFnQixFQUFFLENBSXpDO0lBRUQ7OztPQUdHO0lBQ1UscUJBQXFCLENBQUMsS0FBSyxFQUFFLFdBQVcsR0FBRyxPQUFPLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxDQUlsRjtJQUVELG1HQUFtRztJQUM1Rix3QkFBd0IsQ0FBQyxRQUFRLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxVQUFVLEdBQUcsZ0JBQWdCLEVBQUUsQ0FFNUY7SUFFRDs7Ozs7OztPQU9HO0lBQ0gsVUFBZ0Isa0JBQWtCLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQXNCbEQ7Q0FDRjtBQUVELG9GQUFvRjtBQUNwRixNQUFNLE1BQU0sMEJBQTBCLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixFQUFFLGVBQWUsQ0FBQyxDQUFDIn0=
87
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlY2twb2ludC1zdG9yZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NoZWNrcG9pbnQtc3RvcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsV0FBVyxFQUFvQixXQUFXLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDOUcsT0FBTyxFQUFlLEtBQUssY0FBYyxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBRXZGLE9BQU8sS0FBSyxFQUFFLGFBQWEsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3pELE9BQU8sS0FBSyxFQUFFLFVBQVUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzNELE9BQU8sRUFBRSxLQUFLLGlCQUFpQixFQUF3QyxNQUFNLDZCQUE2QixDQUFDO0FBRTNHLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxLQUFLLG9CQUFvQixFQUFFLEtBQUssb0JBQW9CLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUVwSCw4R0FBOEc7QUFDOUcsTUFBTSxNQUFNLHNCQUFzQixHQUFHLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxZQUFZLEdBQUcsYUFBYSxDQUFDLENBQUM7QUFFOUYsbUZBQW1GO0FBQ25GLE1BQU0sTUFBTSx1QkFBdUIsR0FBRyxDQUFDLElBQUksRUFBRSxvQkFBb0IsRUFBRSxJQUFJLEVBQUUsb0JBQW9CLEtBQUssZ0JBQWdCLENBQUM7QUFFbkg7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILHFCQUFhLGVBQWU7SUFNeEIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxhQUFhO0lBQzlCLE9BQU8sQ0FBQyxRQUFRLENBQUMsVUFBVTtJQUMzQixPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU87SUFFeEIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxlQUFlO0lBVGxDLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUF1QztJQUMvRCxPQUFPLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBaUI7SUFDN0MsT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQVM7SUFFN0IsWUFDbUIsYUFBYSxFQUFFLElBQUksQ0FBQyxhQUFhLEVBQUUsdUJBQXVCLEdBQUcsZ0JBQWdCLENBQUMsRUFDOUUsVUFBVSxFQUFFLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxLQUFLLENBQUMsRUFDN0MsT0FBTyxFQUFFO1FBQUUseUJBQXlCLEVBQUUsTUFBTSxDQUFBO0tBQUUsRUFDL0QsUUFBUSxDQUFDLEVBQUUsY0FBYyxFQUNSLGVBQWUsR0FBRSx1QkFBMEUsRUFRN0c7SUFFTSxLQUFLLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUc1QjtJQUVZLElBQUksSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBU2pDO0lBRUQ7Ozs7T0FJRztJQUNVLFdBQVcsQ0FBQyxVQUFVLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxzQkFBc0IsR0FBRyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0EwQnhHO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSSxvQkFBb0IsQ0FBQyxpQkFBaUIsRUFBRSxXQUFXLEdBQUcsZ0JBQWdCLEVBQUUsQ0FVOUU7SUFFRDs7OztPQUlHO0lBQ0ksV0FBVyxDQUFDLFlBQVksRUFBRSxXQUFXLEdBQUcsSUFBSSxDQW9CbEQ7SUFFRCw2REFBNkQ7SUFDdEQsR0FBRyxDQUFDLEVBQUUsRUFBRSxNQUFNLEdBQUcsZ0JBQWdCLEdBQUcsU0FBUyxDQUVuRDtJQUVELGtHQUFrRztJQUMzRixlQUFlLENBQUMsVUFBVSxFQUFFLFVBQVUsR0FBRyxnQkFBZ0IsR0FBRyxTQUFTLENBRTNFO0lBRUQsc0ZBQXNGO0lBQy9FLE9BQU8sSUFBSSxnQkFBZ0IsRUFBRSxDQUVuQztJQUVELGdGQUFnRjtJQUN6RSxhQUFhLElBQUksZ0JBQWdCLEVBQUUsQ0FJekM7SUFFRDs7O09BR0c7SUFDVSxxQkFBcUIsQ0FBQyxLQUFLLEVBQUUsV0FBVyxHQUFHLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLENBSWxGO0lBRUQsbUdBQW1HO0lBQzVGLHdCQUF3QixDQUFDLFFBQVEsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLFVBQVUsR0FBRyxnQkFBZ0IsRUFBRSxDQUU1RjtJQUVEOzs7Ozs7O09BT0c7SUFDSCxVQUFnQixrQkFBa0IsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBc0JsRDtDQUNGO0FBRUQsb0ZBQW9GO0FBQ3BGLE1BQU0sTUFBTSwwQkFBMEIsR0FBRyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsZUFBZSxDQUFDLENBQUMifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"checkpoint-store.d.ts","sourceRoot":"","sources":["../src/checkpoint-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AACjG,OAAO,EAAe,KAAK,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AAEvF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,KAAK,iBAAiB,EAAwC,MAAM,6BAA6B,CAAC;AAE3G,OAAO,EAAE,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,KAAK,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAEpH,8GAA8G;AAC9G,MAAM,MAAM,sBAAsB,GAAG,IAAI,CAAC,oBAAoB,EAAE,YAAY,GAAG,aAAa,CAAC,CAAC;AAE9F,mFAAmF;AACnF,MAAM,MAAM,uBAAuB,GAAG,CAAC,IAAI,EAAE,oBAAoB,EAAE,IAAI,EAAE,oBAAoB,KAAK,gBAAgB,CAAC;AAEnH;;;;;;;;;;;;;GAaG;AACH,qBAAa,eAAe;IAMxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAExB,OAAO,CAAC,QAAQ,CAAC,eAAe;IATlC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAiB;IAC7C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAE7B,YACmB,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,uBAAuB,GAAG,gBAAgB,CAAC,EAC9E,UAAU,EAAE,IAAI,CAAC,oBAAoB,EAAE,KAAK,CAAC,EAC7C,OAAO,EAAE;QAAE,yBAAyB,EAAE,MAAM,CAAA;KAAE,EAC/D,QAAQ,CAAC,EAAE,cAAc,EACR,eAAe,GAAE,uBAA0E,EAQ7G;IAEM,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAG5B;IAEY,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CASjC;IAED;;;;OAIG;IACU,WAAW,CAAC,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,sBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA0BxG;IAED;;;;OAIG;IACI,eAAe,CAAC,YAAY,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CASzE;IAED;;;;OAIG;IACI,WAAW,CAAC,YAAY,EAAE,WAAW,GAAG,IAAI,CAoBlD;IAED,6DAA6D;IACtD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAEnD;IAED,kGAAkG;IAC3F,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,gBAAgB,GAAG,SAAS,CAE3E;IAED,sFAAsF;IAC/E,OAAO,IAAI,gBAAgB,EAAE,CAEnC;IAED,gFAAgF;IACzE,aAAa,IAAI,gBAAgB,EAAE,CAIzC;IAED;;;OAGG;IACU,qBAAqB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAIlF;IAED,mGAAmG;IAC5F,wBAAwB,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,GAAG,gBAAgB,EAAE,CAE5F;IAED;;;;;;;OAOG;IACH,UAAgB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAsBlD;CACF;AAED,oFAAoF;AACpF,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAC"}
1
+ {"version":3,"file":"checkpoint-store.d.ts","sourceRoot":"","sources":["../src/checkpoint-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAoB,WAAW,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC9G,OAAO,EAAe,KAAK,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AAEvF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,KAAK,iBAAiB,EAAwC,MAAM,6BAA6B,CAAC;AAE3G,OAAO,EAAE,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,KAAK,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAEpH,8GAA8G;AAC9G,MAAM,MAAM,sBAAsB,GAAG,IAAI,CAAC,oBAAoB,EAAE,YAAY,GAAG,aAAa,CAAC,CAAC;AAE9F,mFAAmF;AACnF,MAAM,MAAM,uBAAuB,GAAG,CAAC,IAAI,EAAE,oBAAoB,EAAE,IAAI,EAAE,oBAAoB,KAAK,gBAAgB,CAAC;AAEnH;;;;;;;;;;;;;GAaG;AACH,qBAAa,eAAe;IAMxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAExB,OAAO,CAAC,QAAQ,CAAC,eAAe;IATlC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAiB;IAC7C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAE7B,YACmB,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,uBAAuB,GAAG,gBAAgB,CAAC,EAC9E,UAAU,EAAE,IAAI,CAAC,oBAAoB,EAAE,KAAK,CAAC,EAC7C,OAAO,EAAE;QAAE,yBAAyB,EAAE,MAAM,CAAA;KAAE,EAC/D,QAAQ,CAAC,EAAE,cAAc,EACR,eAAe,GAAE,uBAA0E,EAQ7G;IAEM,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAG5B;IAEY,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CASjC;IAED;;;;OAIG;IACU,WAAW,CAAC,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,sBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA0BxG;IAED;;;;;;;;OAQG;IACI,oBAAoB,CAAC,iBAAiB,EAAE,WAAW,GAAG,gBAAgB,EAAE,CAU9E;IAED;;;;OAIG;IACI,WAAW,CAAC,YAAY,EAAE,WAAW,GAAG,IAAI,CAoBlD;IAED,6DAA6D;IACtD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAEnD;IAED,kGAAkG;IAC3F,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,gBAAgB,GAAG,SAAS,CAE3E;IAED,sFAAsF;IAC/E,OAAO,IAAI,gBAAgB,EAAE,CAEnC;IAED,gFAAgF;IACzE,aAAa,IAAI,gBAAgB,EAAE,CAIzC;IAED;;;OAGG;IACU,qBAAqB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAIlF;IAED,mGAAmG;IAC5F,wBAAwB,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,GAAG,gBAAgB,EAAE,CAE5F;IAED;;;;;;;OAOG;IACH,UAAgB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAsBlD;CACF;AAED,oFAAoF;AACpF,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAC"}
@@ -79,13 +79,18 @@ import { CheckpointProver } from './job/checkpoint-prover.js';
79
79
  return prover;
80
80
  }
81
81
  /**
82
- * Marks every canonical prover whose checkpoint number is strictly greater than
83
- * `prunedNumber` as pruned. Sub-tree work keeps running so a re-add of the same
84
- * content can pick it up. Returns the affected provers.
85
- */ markPrunedAfter(prunedNumber) {
82
+ * Marks every canonical prover that holds a block above the prune target as pruned. A checkpoint is orphaned by a
83
+ * prune to block `targetBlockNumber` iff its last block sits above the target — including a checkpoint whose range
84
+ * straddles the target (partially orphaned), which block-range marking catches without boundary ambiguity. Keying
85
+ * off the surviving block number (rather than a checkpoint number) is correct even when the source has already
86
+ * re-checkpointed past the divergence: the prune event reports the highest surviving block, which by construction
87
+ * survives on the source, whereas the source's current checkpointed tip can sit above the prune target.
88
+ * Sub-tree work keeps running so a re-add of the same content can pick it up. Returns the affected provers.
89
+ */ markPrunedAboveBlock(targetBlockNumber) {
86
90
  const affected = [];
87
91
  for (const prover of this.provers.values()){
88
- if (prover.checkpoint.number > prunedNumber && !prover.isPruned()) {
92
+ const lastBlockNumber = prover.checkpoint.blocks.at(-1).number;
93
+ if (lastBlockNumber > targetBlockNumber && !prover.isPruned()) {
89
94
  prover.markPruned();
90
95
  affected.push(prover);
91
96
  }
@@ -1,6 +1,6 @@
1
1
  import type { RollupContract } from '@aztec/ethereum/contracts';
2
2
  import type { Delayer } from '@aztec/ethereum/l1-tx-utils';
3
- import { BlockNumber, EpochNumber } from '@aztec/foundation/branded-types';
3
+ import { BlockNumber, CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
4
4
  import { DateProvider } from '@aztec/foundation/timer';
5
5
  import type { EpochProverFactory } from '@aztec/prover-client';
6
6
  import { ChonkCache } from '@aztec/prover-client/orchestrator';
@@ -63,6 +63,15 @@ export declare class ProverNode implements L2BlockStreamEventHandler, ProverNode
63
63
  * submission deadline. Protected so tests can verify the start() seeding.
64
64
  */
65
65
  protected lastExpiredEpoch: EpochNumber | undefined;
66
+ /**
67
+ * Highest checkpoint number whose proving-side handling has completed (or that was legitimately skipped).
68
+ * The catch-up loop walks from here to each `chain-checkpointed` tip event. Seeded at start() from the last
69
+ * checkpoint of the last fully-proven epoch (or 0), so a restart reprocesses the partially-proven epoch rather
70
+ * than trusting a checkpointed tip that may sit ahead of unproven checkpoints. Clamped down on a prune.
71
+ */
72
+ protected lastProcessedCheckpoint: CheckpointNumber;
73
+ /** Periodic tick that runs the epoch-expiry sweep during idle periods when no block-stream events arrive. */
74
+ private expiryTicker;
66
75
  readonly tracer: Tracer;
67
76
  protected publishingService: ProofPublishingService | undefined;
68
77
  constructor(prover: EpochProverManager & EpochProverFactory, publisherFactory: ProverPublisherFactory, l2BlockSource: L2BlockSource & Partial<Service>, l1ToL2MessageSource: L1ToL2MessageSource, contractDataSource: ContractDataSource, worldState: WorldStateSynchronizer, p2pClient: {
@@ -93,7 +102,8 @@ export declare class ProverNode implements L2BlockStreamEventHandler, ProverNode
93
102
  /** Returns the underlying prover instance. */
94
103
  getProver(): EpochProverManager & EpochProverFactory;
95
104
  handleBlockStreamEvent(event: L2BlockStreamEvent): Promise<void>;
96
- private handleCheckpointEvent;
105
+ private processCheckpointJump;
106
+ private registerCheckpoint;
97
107
  private collectRegisterData;
98
108
  private handlePruneEvent;
99
109
  private isEpochPastProofSubmissionWindow;
@@ -128,18 +138,22 @@ export declare class ProverNode implements L2BlockStreamEventHandler, ProverNode
128
138
  /** Protected for direct unit-test access. */
129
139
  protected isProvenBlockLastOfItsEpoch(provenBlockNumber: BlockNumber, provenEpoch: EpochNumber, l1Constants: Pick<L1RollupConstants, 'epochDuration'>): Promise<boolean>;
130
140
  /**
131
- * Resolves the L2BlockStream's starting block and the last fully-proven epoch in one
132
- * pass. The starting block is the first block of the next unproven epoch (or the start
133
- * of the partially-proven epoch if the proven tip falls mid-epoch). The fully-proven
134
- * epoch is `provenEpoch` when the proven tip is the last block of its epoch, otherwise
135
- * `provenEpoch - 1`, or `undefined` if no block is proven yet.
141
+ * Resolves the last fully-proven epoch from L1 proven state, used to seed the catch-up cursor (via
142
+ * `computeStartingCheckpoint`) and `lastExpiredEpoch`. The fully-proven epoch is `provenEpoch` when the
143
+ * proven tip is the last block of its epoch, otherwise `provenEpoch - 1`, or `undefined` if no block is
144
+ * proven yet (so a restart reprocesses the partially-proven epoch rather than trusting a stale tip).
136
145
  */
137
- protected computeStartupState(): Promise<{
138
- startingBlock: BlockNumber;
146
+ protected resolveLastFullyProvenEpoch(): Promise<{
139
147
  lastFullyProvenEpoch: EpochNumber | undefined;
140
148
  }>;
149
+ /**
150
+ * Resolves the catch-up cursor seed: the last checkpoint of the last fully-proven epoch, or 0 if none. Seeding
151
+ * from a checkpoint (rather than a checkpointed tip) guarantees a restart reprocesses every checkpoint of the
152
+ * partially-proven epoch, since the checkpointed tip can sit ahead of the last fully-proven checkpoint.
153
+ */
154
+ protected computeStartingCheckpoint(lastFullyProvenEpoch: EpochNumber | undefined): Promise<CheckpointNumber>;
141
155
  private gatherPreviousBlockHeader;
142
156
  private validateConfig;
143
157
  }
144
158
  export { EpochProvingJobTerminalState };
145
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmVyLW5vZGUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9wcm92ZXItbm9kZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEtBQUssRUFBRSxjQUFjLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsV0FBVyxFQUFvQixXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUk3RixPQUFPLEVBQUUsWUFBWSxFQUFrQixNQUFNLHlCQUF5QixDQUFDO0FBQ3ZFLE9BQU8sS0FBSyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFL0QsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBRS9ELE9BQU8sRUFDTCxLQUFLLGFBQWEsRUFFbEIsS0FBSyxrQkFBa0IsRUFDdkIsS0FBSyx5QkFBeUIsRUFFL0IsTUFBTSxxQkFBcUIsQ0FBQztBQUU3QixPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN4RCxPQUFPLEtBQUssRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxLQUFLLGlCQUFpQixFQUFtRCxNQUFNLDZCQUE2QixDQUFDO0FBQ3RILE9BQU8sRUFDTCxLQUFLLGtCQUFrQixFQUN2QixLQUFLLG9CQUFvQixFQUN6Qiw0QkFBNEIsRUFDNUIsS0FBSyxXQUFXLEVBQ2hCLEtBQUssYUFBYSxFQUNsQixLQUFLLE9BQU8sRUFDWixLQUFLLG9CQUFvQixFQUN6QixLQUFLLHNCQUFzQixFQUU1QixNQUFNLGlDQUFpQyxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxFQUFFLGVBQWUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzlELE9BQU8sS0FBSyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFbkUsT0FBTyxFQUNMLFNBQVMsRUFDVCxLQUFLLGVBQWUsRUFDcEIsS0FBSyxTQUFTLEVBQ2QsS0FBSyxNQUFNLEVBRVosTUFBTSx5QkFBeUIsQ0FBQztBQUdqQyxPQUFPLEVBQUUsZUFBZSxFQUErQixNQUFNLHVCQUF1QixDQUFDO0FBQ3JGLE9BQU8sS0FBSyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzVELE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRTlFLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ3ZFLE9BQU8sS0FBSyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDNUUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRXRELEtBQUssaUJBQWlCLEdBQUcsd0JBQXdCLEdBQUcsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUM7QUFDOUUsS0FBSyxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsZUFBZSxFQUFFLGVBQWUsQ0FBQyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsV0FBVyxHQUFHLGVBQWUsQ0FBQyxDQUFDO0FBU2xIOzs7Ozs7Ozs7R0FTRztBQUNILHFCQUFhLFVBQVcsWUFBVyx5QkFBeUIsRUFBRSxhQUFhLEVBQUUsU0FBUztJQTRCbEYsU0FBUyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsa0JBQWtCLEdBQUcsa0JBQWtCO0lBQ2xFLFNBQVMsQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLEVBQUUsc0JBQXNCO0lBQzNELFNBQVMsQ0FBQyxRQUFRLENBQUMsYUFBYSxFQUFFLGFBQWEsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDO0lBQ2xFLFNBQVMsQ0FBQyxRQUFRLENBQUMsbUJBQW1CLEVBQUUsbUJBQW1CO0lBQzNELFNBQVMsQ0FBQyxRQUFRLENBQUMsa0JBQWtCLEVBQUUsa0JBQWtCO0lBQ3pELFNBQVMsQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLHNCQUFzQjtJQUNyRCxTQUFTLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRTtRQUFFLGFBQWEsSUFBSSxXQUFXLENBQUE7S0FBRSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUM7SUFDakYsU0FBUyxDQUFDLFFBQVEsQ0FBQyxjQUFjLEVBQUUsY0FBYztJQUNqRCxTQUFTLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxTQUFTO0lBRXZDLFNBQVMsQ0FBQyxRQUFRLENBQUMsZUFBZSxFQUFFLGVBQWU7SUFDbkQsT0FBTyxDQUFDLE9BQU8sQ0FBQztJQUNoQixPQUFPLENBQUMsUUFBUSxDQUFDLFlBQVk7SUF2Qy9CLE9BQU8sQ0FBQyxHQUFHLENBQStCO0lBRTFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsZUFBZSxFQUFFLGVBQWUsQ0FBQztJQUNwRCxTQUFTLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxVQUFVLENBQUM7SUFDMUMsU0FBUyxDQUFDLGNBQWMsRUFBRSxjQUFjLEdBQUcsU0FBUyxDQUFDO0lBRXJELE9BQU8sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFvQjtJQUMzQyxPQUFPLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBdUI7SUFDbEQsT0FBTyxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQTJCO0lBRTFELG1FQUFtRTtJQUNuRSxPQUFPLENBQUMsU0FBUyxDQUFvQjtJQUNyQyx1REFBdUQ7SUFDdkQsT0FBTyxDQUFDLFdBQVcsQ0FBNEI7SUFDL0M7Ozs7O09BS0c7SUFDSCxTQUFTLENBQUMsZ0JBQWdCLEVBQUUsV0FBVyxHQUFHLFNBQVMsQ0FBQztJQUVwRCxTQUFnQixNQUFNLEVBQUUsTUFBTSxDQUFDO0lBRS9CLFNBQVMsQ0FBQyxpQkFBaUIsRUFBRSxzQkFBc0IsR0FBRyxTQUFTLENBQUM7SUFFaEUsWUFDcUIsTUFBTSxFQUFFLGtCQUFrQixHQUFHLGtCQUFrQixFQUMvQyxnQkFBZ0IsRUFBRSxzQkFBc0IsRUFDeEMsYUFBYSxFQUFFLGFBQWEsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQy9DLG1CQUFtQixFQUFFLG1CQUFtQixFQUN4QyxrQkFBa0IsRUFBRSxrQkFBa0IsRUFDdEMsVUFBVSxFQUFFLHNCQUFzQixFQUNsQyxTQUFTLEVBQUU7UUFBRSxhQUFhLElBQUksV0FBVyxDQUFBO0tBQUUsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQzlELGNBQWMsRUFBRSxjQUFjLEVBQzlCLFNBQVMsRUFBRSxTQUFTLEVBQ3ZDLE1BQU0sR0FBRSxPQUFPLENBQUMsaUJBQWlCLENBQU0sRUFDcEIsZUFBZSxHQUFFLGVBQXNDLEVBQ2xFLE9BQU8sQ0FBQyxxQkFBUyxFQUNSLFlBQVksR0FBRSxZQUFpQyxFQWdEakU7SUFFTSxXQUFXLHVEQUVqQjtJQUVNLE1BQU07O3lCQUVaO0lBRUQsdURBQXVEO0lBQ2hELFVBQVUsSUFBSSxPQUFPLEdBQUcsU0FBUyxDQUV2QztJQUVELG1EQUFtRDtJQUM1QyxPQUFPLElBQUksT0FBTyxDQUFDO1FBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQztRQUFDLE1BQU0sRUFBRSxvQkFBb0IsQ0FBQztRQUFDLFdBQVcsRUFBRSxXQUFXLENBQUE7S0FBRSxFQUFFLENBQUMsQ0FFcEc7SUFFRCw4REFBOEQ7SUFDdkQsa0JBQWtCLElBQUksZUFBZSxDQUUzQztJQUVELGtFQUFrRTtJQUMzRCxhQUFhLElBQUksVUFBVSxDQUVqQztJQUVELHdEQUF3RDtJQUNqRCxpQkFBaUIsSUFBSSxjQUFjLENBS3pDO0lBRUQsa0NBQWtDO0lBQ3JCLHVCQUF1QixJQUFJLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUdwRTtJQUVELCtCQUErQjtJQUN4QixTQUFTLGtEQUVmO0lBRUQsOENBQThDO0lBQ3ZDLFNBQVMsNENBRWY7SUFJWSxzQkFBc0IsQ0FBQyxLQUFLLEVBQUUsa0JBQWtCLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQXFCNUU7WUFHYSxxQkFBcUI7WUFpQ3JCLG1CQUFtQjtZQXVCbkIsZ0JBQWdCO1lBdUJoQixnQ0FBZ0M7WUFtQmhDLGdCQUFnQjtZQTBCaEIsV0FBVztJQWN6Qjs7T0FFRztJQUNVLFVBQVUsQ0FBQyxXQUFXLEVBQUUsV0FBVyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FLakU7SUFJSyxLQUFLLGtCQThCVjtJQUVLLElBQUksa0JBMEJUO0lBRUQ7Ozs7T0FJRztJQUNILFNBQVMsQ0FBQyxvQkFBb0IsQ0FBQyxpQkFBaUIsRUFBRSxzQkFBc0IsR0FBRyxjQUFjLENBbUJ4RjtJQUVEOzs7O09BSUc7SUFDSSxlQUFlLENBQUMsS0FBSyxFQUFFLGlCQUFpQixHQUFHLElBQUksQ0FLckQ7SUFFRCw4R0FBOEc7SUFDakcsdUJBQXVCLENBQUMsT0FBTyxFQUFFLFlBQVksR0FBRyxPQUFPLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQyxDQWN2RjtJQUtELE9BQU8sQ0FBQyxjQUFjO0lBSXRCOzs7T0FHRztJQUNILFVBQWdCLGtCQUFrQixDQUNoQyxXQUFXLEVBQUUsV0FBVyxFQUN4QixXQUFXLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixFQUFFLGVBQWUsQ0FBQyxHQUNwRCxPQUFPLENBQUMsT0FBTyxDQUFDLENBaUJsQjtJQUVELDZDQUE2QztJQUM3QyxVQUFnQiwyQkFBMkIsQ0FDekMsaUJBQWlCLEVBQUUsV0FBVyxFQUM5QixXQUFXLEVBQUUsV0FBVyxFQUN4QixXQUFXLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixFQUFFLGVBQWUsQ0FBQyxHQUNwRCxPQUFPLENBQUMsT0FBTyxDQUFDLENBTWxCO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsVUFBZ0IsbUJBQW1CLElBQUksT0FBTyxDQUFDO1FBQzdDLGFBQWEsRUFBRSxXQUFXLENBQUM7UUFDM0Isb0JBQW9CLEVBQUUsV0FBVyxHQUFHLFNBQVMsQ0FBQztLQUMvQyxDQUFDLENBdUJEO1lBRWEseUJBQXlCO0lBUXZDLE9BQU8sQ0FBQyxjQUFjO0NBY3ZCO0FBR0QsT0FBTyxFQUFFLDRCQUE0QixFQUFFLENBQUMifQ==
159
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmVyLW5vZGUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9wcm92ZXItbm9kZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEtBQUssRUFBRSxjQUFjLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsV0FBVyxFQUFFLGdCQUFnQixFQUFFLFdBQVcsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBSzdGLE9BQU8sRUFBRSxZQUFZLEVBQWtCLE1BQU0seUJBQXlCLENBQUM7QUFDdkUsT0FBTyxLQUFLLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUUvRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFFL0QsT0FBTyxFQUVMLEtBQUssYUFBYSxFQUVsQixLQUFLLGtCQUFrQixFQUN2QixLQUFLLHlCQUF5QixFQUUvQixNQUFNLHFCQUFxQixDQUFDO0FBRTdCLE9BQU8sS0FBSyxFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3hELE9BQU8sS0FBSyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDakUsT0FBTyxFQUFFLEtBQUssaUJBQWlCLEVBQW1ELE1BQU0sNkJBQTZCLENBQUM7QUFDdEgsT0FBTyxFQUNMLEtBQUssa0JBQWtCLEVBQ3ZCLEtBQUssb0JBQW9CLEVBQ3pCLDRCQUE0QixFQUM1QixLQUFLLFdBQVcsRUFDaEIsS0FBSyxhQUFhLEVBQ2xCLEtBQUssT0FBTyxFQUNaLEtBQUssb0JBQW9CLEVBQ3pCLEtBQUssc0JBQXNCLEVBRTVCLE1BQU0saUNBQWlDLENBQUM7QUFDekMsT0FBTyxLQUFLLEVBQUUsZUFBZSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDOUQsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx5QkFB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
@@ -1 +1 @@
1
- {"version":3,"file":"prover-node.d.ts","sourceRoot":"","sources":["../src/prover-node.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prover-node.d.ts","sourceRoot":"","sources":["../src/prover-node.ts"],"names":[],"mappings":"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"}
@@ -371,10 +371,11 @@ function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
371
371
  return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
372
372
  }
373
373
  var _initProto;
374
- import { BlockNumber, EpochNumber } from '@aztec/foundation/branded-types';
374
+ import { BlockNumber, CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
375
375
  import { assertRequired, compact, pick } from '@aztec/foundation/collection';
376
376
  import { memoize } from '@aztec/foundation/decorators';
377
377
  import { createLogger } from '@aztec/foundation/log';
378
+ import { RunningPromise } from '@aztec/foundation/running-promise';
378
379
  import { DateProvider, executeTimeout } from '@aztec/foundation/timer';
379
380
  import { getLastSiblingPath } from '@aztec/prover-client/helpers';
380
381
  import { ChonkCache } from '@aztec/prover-client/orchestrator';
@@ -440,6 +441,13 @@ import { SessionManager } from './session-manager.js';
440
441
  * event by comparing the archiver's latest synced L2 slot against each epoch's
441
442
  * submission deadline. Protected so tests can verify the start() seeding.
442
443
  */ lastExpiredEpoch;
444
+ /**
445
+ * Highest checkpoint number whose proving-side handling has completed (or that was legitimately skipped).
446
+ * The catch-up loop walks from here to each `chain-checkpointed` tip event. Seeded at start() from the last
447
+ * checkpoint of the last fully-proven epoch (or 0), so a restart reprocesses the partially-proven epoch rather
448
+ * than trusting a checkpointed tip that may sit ahead of unproven checkpoints. Clamped down on a prune.
449
+ */ lastProcessedCheckpoint;
450
+ /** Periodic tick that runs the epoch-expiry sweep during idle periods when no block-stream events arrive. */ expiryTicker;
443
451
  tracer;
444
452
  publishingService;
445
453
  constructor(prover, publisherFactory, l2BlockSource, l1ToL2MessageSource, contractDataSource, worldState, p2pClient, rollupContract, l1Metrics, config = {}, telemetryClient = getTelemetryClient(), delayer, dateProvider = new DateProvider()){
@@ -456,6 +464,7 @@ import { SessionManager } from './session-manager.js';
456
464
  this.delayer = delayer;
457
465
  this.dateProvider = dateProvider;
458
466
  this.log = (_initProto(this), createLogger('prover-node'));
467
+ this.lastProcessedCheckpoint = CheckpointNumber.ZERO;
459
468
  this.config = {
460
469
  proverNodePollingIntervalMs: 1_000,
461
470
  proverNodeMaxPendingJobs: 100,
@@ -528,17 +537,26 @@ import { SessionManager } from './session-manager.js';
528
537
  async handleBlockStreamEvent(event) {
529
538
  switch(event.type){
530
539
  case 'chain-checkpointed':
531
- await this.handleCheckpointEvent(event.checkpoint);
540
+ await this.processCheckpointJump(event.checkpoint.number);
532
541
  break;
533
542
  case 'chain-pruned':
534
- await this.handlePruneEvent(event.checkpointed.checkpoint);
543
+ await this.handlePruneEvent(event.block);
535
544
  break;
536
545
  case 'chain-proven':
537
546
  this.publishingService?.onChainProven(BlockNumber(event.block.number));
538
547
  break;
548
+ // The proposed tip drives only the tips store's walk-back history (recorded below); the prover-node
549
+ // tracks checkpoints, not proposed blocks. `blocks-added` is never emitted in tips-only mode, and
550
+ // `chain-finalized` carries nothing the prover-node acts on.
551
+ case 'chain-proposed':
539
552
  case 'chain-finalized':
540
553
  case 'blocks-added':
541
554
  break;
555
+ default:
556
+ {
557
+ const _ = event;
558
+ break;
559
+ }
542
560
  }
543
561
  // Expiry is driven by the archiver's latest synced L2 slot
544
562
  await this.checkEpochExpiry();
@@ -547,27 +565,87 @@ import { SessionManager } from './session-manager.js';
547
565
  // skips this update, so the event is re-emitted on the next poll rather than skipped (A-1041).
548
566
  await this.tipsStore.handleBlockStreamEvent(event);
549
567
  }
550
- /** Register a new checkpoint with the store and notify the session manager. */ async handleCheckpointEvent(publishedCheckpoint) {
551
- const checkpoint = publishedCheckpoint.checkpoint;
552
- const slotNumber = checkpoint.header.slotNumber;
553
- const l1Constants = await this.getL1Constants();
554
- const epochNumber = getEpochAtSlot(slotNumber, l1Constants);
555
- if (await this.isEpochFullyProven(epochNumber, l1Constants)) {
556
- this.log.debug(`Skipping checkpoint ${checkpoint.number} for already-proven epoch ${epochNumber}`);
568
+ /**
569
+ * Walks every checkpoint between the local cursor and the newly-reported checkpointed tip, registering
570
+ * each one that belongs to an epoch that can still be proven. The block stream now delivers a single thin
571
+ * `chain-checkpointed` tip event per pass rather than one fat event per checkpoint, so this drives the
572
+ * catch-up itself: light metadata first (`getCheckpointsData`) to decide relevance per epoch, then a heavy
573
+ * `getCheckpoints` fetch only for checkpoints in provable epochs.
574
+ *
575
+ * The cursor advances one checkpoint at a time and only after that checkpoint's proving-side handling has
576
+ * fully succeeded, preserving the A-1041 at-least-once semantics: a mid-jump failure leaves the cursor
577
+ * behind so the next pass retries from the first checkpoint that did not complete.
578
+ */ async processCheckpointJump(targetCheckpoint) {
579
+ if (targetCheckpoint <= this.lastProcessedCheckpoint) {
557
580
  return;
558
581
  }
559
- if (await this.isEpochPastProofSubmissionWindow(epochNumber, l1Constants)) {
560
- this.log.debug(`Skipping checkpoint ${checkpoint.number} for epoch ${epochNumber} past its proof-submission window`);
561
- return;
582
+ const l1Constants = await this.getL1Constants();
583
+ // Cap the catch-up at the `(proofSubmissionEpochs + 1) * epochDuration` most recent checkpoints.
584
+ // When the cursor is much further behind (e.g. resyncing after a long time offline), fetching the whole gap could
585
+ // load thousands of checkpoints we cannot act on: anything older than the last two epochs is already past
586
+ // its proof-submission window, so we skip it and jump the cursor forward to the start of the capped range.
587
+ const maxCheckpoints = (l1Constants.proofSubmissionEpochs + 1) * l1Constants.epochDuration;
588
+ let from = CheckpointNumber(this.lastProcessedCheckpoint + 1);
589
+ if (Number(targetCheckpoint - from) + 1 > maxCheckpoints) {
590
+ const cappedFrom = CheckpointNumber(targetCheckpoint - maxCheckpoints + 1);
591
+ this.log.warn(`Skipping unprovable checkpoints during catch-up; the prover node is far behind`, {
592
+ from,
593
+ cappedFrom,
594
+ targetCheckpoint,
595
+ maxCheckpoints
596
+ });
597
+ // Advance the cursor past the skipped checkpoints so they are never retried.
598
+ this.lastProcessedCheckpoint = CheckpointNumber(cappedFrom - 1);
599
+ from = cappedFrom;
600
+ }
601
+ const limit = Number(targetCheckpoint - from) + 1;
602
+ const metadatas = await this.l2BlockSource.getCheckpointsData({
603
+ from,
604
+ limit
605
+ });
606
+ // Per-epoch relevance is cached so a multi-checkpoint epoch resolves it once. Skipping is whole-epoch
607
+ // only: the SessionManager requires an epoch's checkpoints fully covered before it opens a session, so we
608
+ // never drop an individual checkpoint inside an epoch we will prove.
609
+ const epochSkippable = new Map();
610
+ for (const metadata of metadatas){
611
+ const epochNumber = getEpochAtSlot(metadata.header.slotNumber, l1Constants);
612
+ let skippable = epochSkippable.get(epochNumber);
613
+ if (skippable === undefined) {
614
+ skippable = await this.isEpochFullyProven(epochNumber, l1Constants) || await this.isEpochPastProofSubmissionWindow(epochNumber, l1Constants);
615
+ epochSkippable.set(epochNumber, skippable);
616
+ }
617
+ if (skippable) {
618
+ this.log.debug(`Skipping checkpoint ${metadata.checkpointNumber} for unprovable epoch ${epochNumber}`);
619
+ } else {
620
+ await this.registerCheckpoint(metadata.checkpointNumber, epochNumber);
621
+ }
622
+ // Advance only after the checkpoint's handling succeeded (or it was legitimately skipped). registerCheckpoint
623
+ // throws on failure, which leaves the cursor here for the next pass to retry (A-1041).
624
+ this.lastProcessedCheckpoint = metadata.checkpointNumber;
625
+ }
626
+ }
627
+ /** Heavy-fetch a single checkpoint, register it with the store, and notify the session manager. */ async registerCheckpoint(checkpointNumber, epochNumber) {
628
+ const published = await this.l2BlockSource.getCheckpoint({
629
+ number: checkpointNumber
630
+ });
631
+ if (!published) {
632
+ throw new Error(`Checkpoint ${checkpointNumber} not found in block source during catch-up`);
562
633
  }
634
+ const checkpoint = published.checkpoint;
563
635
  this.log.info(`New checkpoint ${checkpoint.number} for epoch ${epochNumber}`, {
564
636
  checkpointNumber: checkpoint.number,
565
637
  epochNumber,
566
- slotNumber
638
+ slotNumber: checkpoint.header.slotNumber
567
639
  });
568
- const registerData = await this.collectRegisterData(checkpoint, publishedCheckpoint.attestations);
640
+ const registerData = await this.collectRegisterData(checkpoint, published.attestations);
569
641
  await this.checkpointStore.addOrUpdate(checkpoint, registerData);
570
642
  await this.sessionManager?.onCheckpointAdded(epochNumber);
643
+ // Tips-only mode delivers no blocks, so record one witness per checkpointed block: a reorg into the checkpoint's
644
+ // range then prunes at the true divergence instead of the nearest sparse tip anchor.
645
+ await this.tipsStore.recordBlockHashes(await Promise.all(checkpoint.blocks.map(async (block)=>({
646
+ number: block.number,
647
+ hash: (await block.header.hash()).toString()
648
+ }))));
571
649
  }
572
650
  /**
573
651
  * Gathers register-time data for a checkpoint: previous block header, L1-to-L2 messages,
@@ -587,11 +665,38 @@ import { SessionManager } from './session-manager.js';
587
665
  previousArchiveSiblingPath
588
666
  };
589
667
  }
590
- /** Mark every prover above the prune threshold as pruned and notify the session manager. */ async handlePruneEvent(prunedCheckpoint) {
591
- this.log.warn(`Chain pruned to checkpoint ${prunedCheckpoint.number}`, {
592
- prunedCheckpoint
668
+ /**
669
+ * Marks every prover orphaned by the prune as pruned, clamps the catch-up cursor below the prune target's
670
+ * checkpoint, and notifies the session manager. Keyed off the prune target block (the highest surviving block)
671
+ * rather than the source's checkpointed tip, which can sit above the target after a re-checkpoint and would leave
672
+ * orphaned provers canonical. Throws (rather than warning) if the cursor floor cannot be resolved, so the pass
673
+ * fails and the prune is retried next iteration.
674
+ */ async handlePruneEvent(prunedToBlock) {
675
+ this.log.warn(`Chain pruned to block ${prunedToBlock.number}`, {
676
+ prunedToBlock
593
677
  });
594
- const affected = this.checkpointStore.markPrunedAfter(prunedCheckpoint.number);
678
+ // Resolve the cursor floor BEFORE marking provers: markPrunedAboveBlock returns only newly-marked provers, so a
679
+ // throw after marking would leave a retry pass with nothing to act on. Resolving first means a throw leaves
680
+ // everything untouched and the next pass retries the whole handler (the tips cursor only advances on success).
681
+ let cursorFloor;
682
+ if (prunedToBlock.number === 0) {
683
+ cursorFloor = CheckpointNumber.ZERO;
684
+ } else {
685
+ const targetData = await this.l2BlockSource.getBlockData({
686
+ number: prunedToBlock.number
687
+ });
688
+ if (targetData === undefined) {
689
+ throw new Error(`No block data found for prune target block ${prunedToBlock.number}; cannot clamp checkpoint cursor`);
690
+ }
691
+ // Clamp to `cpAtTarget - 1`: a mid-checkpoint target leaves that checkpoint partially orphaned and it must be
692
+ // reprocessed. Over-clamping merely re-registers a checkpoint (at-least-once by design — A-1041); under-clamping
693
+ // would permanently skip a rebuilt same-number checkpoint.
694
+ cursorFloor = CheckpointNumber(Math.max(0, Number(targetData.checkpointNumber) - 1));
695
+ }
696
+ const affected = this.checkpointStore.markPrunedAboveBlock(prunedToBlock.number);
697
+ if (this.lastProcessedCheckpoint > cursorFloor) {
698
+ this.lastProcessedCheckpoint = cursorFloor;
699
+ }
595
700
  if (affected.length === 0) {
596
701
  return;
597
702
  }
@@ -689,13 +794,18 @@ import { SessionManager } from './session-manager.js';
689
794
  this.sessionManager.start();
690
795
  // Now that the store + manager exist, arm the live-state observable gauges.
691
796
  this.jobMetrics.observeState(this.checkpointStore, this.sessionManager);
692
- const { startingBlock, lastFullyProvenEpoch } = await this.computeStartupState();
797
+ const { lastFullyProvenEpoch } = await this.resolveLastFullyProvenEpoch();
693
798
  this.lastExpiredEpoch = lastFullyProvenEpoch;
799
+ this.lastProcessedCheckpoint = await this.computeStartingCheckpoint(lastFullyProvenEpoch);
694
800
  this.blockStream = new L2BlockStream(this.l2BlockSource, this.tipsStore, this, this.log, {
695
801
  pollIntervalMS: this.config.proverNodePollingIntervalMs,
696
- startingBlock
802
+ tipsOnly: true
697
803
  });
698
804
  this.blockStream.start();
805
+ // With thin once-per-pass tip events, the expiry sweep no longer fires once per checkpoint; drive it
806
+ // from a periodic tick so epochs still expire during idle/no-event periods.
807
+ this.expiryTicker = new RunningPromise(()=>this.checkEpochExpiry(), this.log, this.config.proverNodePollingIntervalMs);
808
+ this.expiryTicker.start();
699
809
  await this.rewardsMetrics.start();
700
810
  this.l1Metrics.start();
701
811
  this.log.info(`Started Prover Node with prover id ${this.prover.getProverId().toString()}`, this.config);
@@ -704,6 +814,7 @@ import { SessionManager } from './session-manager.js';
704
814
  this.log.info('Stopping ProverNode');
705
815
  this.jobMetrics.stopObservingState();
706
816
  await this.blockStream?.stop();
817
+ await this.expiryTicker?.stop();
707
818
  if (this.sessionManager) {
708
819
  await this.sessionManager.stop();
709
820
  }
@@ -803,18 +914,16 @@ import { SessionManager } from './session-manager.js';
803
914
  return this.l2BlockSource.isEpochComplete(provenEpoch);
804
915
  }
805
916
  /**
806
- * Resolves the L2BlockStream's starting block and the last fully-proven epoch in one
807
- * pass. The starting block is the first block of the next unproven epoch (or the start
808
- * of the partially-proven epoch if the proven tip falls mid-epoch). The fully-proven
809
- * epoch is `provenEpoch` when the proven tip is the last block of its epoch, otherwise
810
- * `provenEpoch - 1`, or `undefined` if no block is proven yet.
811
- */ async computeStartupState() {
917
+ * Resolves the last fully-proven epoch from L1 proven state, used to seed the catch-up cursor (via
918
+ * `computeStartingCheckpoint`) and `lastExpiredEpoch`. The fully-proven epoch is `provenEpoch` when the
919
+ * proven tip is the last block of its epoch, otherwise `provenEpoch - 1`, or `undefined` if no block is
920
+ * proven yet (so a restart reprocesses the partially-proven epoch rather than trusting a stale tip).
921
+ */ async resolveLastFullyProvenEpoch() {
812
922
  const provenBlockNumber = await this.l2BlockSource.getBlockNumber({
813
923
  tag: 'proven'
814
924
  });
815
925
  if (!provenBlockNumber || provenBlockNumber <= 0) {
816
926
  return {
817
- startingBlock: BlockNumber(1),
818
927
  lastFullyProvenEpoch: undefined
819
928
  };
820
929
  }
@@ -824,32 +933,33 @@ import { SessionManager } from './session-manager.js';
824
933
  }))?.header;
825
934
  if (!provenHeader) {
826
935
  return {
827
- startingBlock: BlockNumber(provenBlockNumber + 1),
828
936
  lastFullyProvenEpoch: undefined
829
937
  };
830
938
  }
831
939
  const provenEpoch = getEpochAtSlot(provenHeader.getSlot(), l1Constants);
832
940
  if (await this.isProvenBlockLastOfItsEpoch(BlockNumber(provenBlockNumber), provenEpoch, l1Constants)) {
833
941
  return {
834
- startingBlock: BlockNumber(provenBlockNumber + 1),
835
942
  lastFullyProvenEpoch: provenEpoch
836
943
  };
837
944
  }
838
- const epochCheckpoints = await this.l2BlockSource.getCheckpointsData({
839
- epoch: provenEpoch
840
- });
841
- const firstBlockOfEpoch = epochCheckpoints.length > 0 ? epochCheckpoints[0].startBlock : BlockNumber(provenBlockNumber);
842
- this.log.info(`Starting L2BlockStream at block ${firstBlockOfEpoch} (start of partially-proven epoch ${provenEpoch})`, {
843
- provenBlockNumber,
844
- provenEpoch,
845
- firstBlockOfEpoch
846
- });
847
945
  const lastFullyProvenEpoch = provenEpoch > 0 ? EpochNumber(provenEpoch - 1) : undefined;
848
946
  return {
849
- startingBlock: firstBlockOfEpoch,
850
947
  lastFullyProvenEpoch
851
948
  };
852
949
  }
950
+ /**
951
+ * Resolves the catch-up cursor seed: the last checkpoint of the last fully-proven epoch, or 0 if none. Seeding
952
+ * from a checkpoint (rather than a checkpointed tip) guarantees a restart reprocesses every checkpoint of the
953
+ * partially-proven epoch, since the checkpointed tip can sit ahead of the last fully-proven checkpoint.
954
+ */ async computeStartingCheckpoint(lastFullyProvenEpoch) {
955
+ if (lastFullyProvenEpoch === undefined) {
956
+ return CheckpointNumber.ZERO;
957
+ }
958
+ const checkpoints = await this.l2BlockSource.getCheckpointsData({
959
+ epoch: lastFullyProvenEpoch
960
+ });
961
+ return checkpoints.at(-1)?.checkpointNumber ?? CheckpointNumber.ZERO;
962
+ }
853
963
  async gatherPreviousBlockHeader(previousBlockNumber) {
854
964
  const data = await this.l2BlockSource.getBlockData({
855
965
  number: BlockNumber(previousBlockNumber)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/prover-node",
3
- "version": "5.0.0-nightly.20260615",
3
+ "version": "5.0.0-nightly.20260617",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -56,28 +56,28 @@
56
56
  ]
57
57
  },
58
58
  "dependencies": {
59
- "@aztec/archiver": "5.0.0-nightly.20260615",
60
- "@aztec/bb-prover": "5.0.0-nightly.20260615",
61
- "@aztec/blob-client": "5.0.0-nightly.20260615",
62
- "@aztec/blob-lib": "5.0.0-nightly.20260615",
63
- "@aztec/constants": "5.0.0-nightly.20260615",
64
- "@aztec/epoch-cache": "5.0.0-nightly.20260615",
65
- "@aztec/ethereum": "5.0.0-nightly.20260615",
66
- "@aztec/foundation": "5.0.0-nightly.20260615",
67
- "@aztec/kv-store": "5.0.0-nightly.20260615",
68
- "@aztec/l1-artifacts": "5.0.0-nightly.20260615",
69
- "@aztec/native": "5.0.0-nightly.20260615",
70
- "@aztec/node-keystore": "5.0.0-nightly.20260615",
71
- "@aztec/node-lib": "5.0.0-nightly.20260615",
72
- "@aztec/noir-protocol-circuits-types": "5.0.0-nightly.20260615",
73
- "@aztec/p2p": "5.0.0-nightly.20260615",
74
- "@aztec/protocol-contracts": "5.0.0-nightly.20260615",
75
- "@aztec/prover-client": "5.0.0-nightly.20260615",
76
- "@aztec/sequencer-client": "5.0.0-nightly.20260615",
77
- "@aztec/simulator": "5.0.0-nightly.20260615",
78
- "@aztec/stdlib": "5.0.0-nightly.20260615",
79
- "@aztec/telemetry-client": "5.0.0-nightly.20260615",
80
- "@aztec/world-state": "5.0.0-nightly.20260615",
59
+ "@aztec/archiver": "5.0.0-nightly.20260617",
60
+ "@aztec/bb-prover": "5.0.0-nightly.20260617",
61
+ "@aztec/blob-client": "5.0.0-nightly.20260617",
62
+ "@aztec/blob-lib": "5.0.0-nightly.20260617",
63
+ "@aztec/constants": "5.0.0-nightly.20260617",
64
+ "@aztec/epoch-cache": "5.0.0-nightly.20260617",
65
+ "@aztec/ethereum": "5.0.0-nightly.20260617",
66
+ "@aztec/foundation": "5.0.0-nightly.20260617",
67
+ "@aztec/kv-store": "5.0.0-nightly.20260617",
68
+ "@aztec/l1-artifacts": "5.0.0-nightly.20260617",
69
+ "@aztec/native": "5.0.0-nightly.20260617",
70
+ "@aztec/node-keystore": "5.0.0-nightly.20260617",
71
+ "@aztec/node-lib": "5.0.0-nightly.20260617",
72
+ "@aztec/noir-protocol-circuits-types": "5.0.0-nightly.20260617",
73
+ "@aztec/p2p": "5.0.0-nightly.20260617",
74
+ "@aztec/protocol-contracts": "5.0.0-nightly.20260617",
75
+ "@aztec/prover-client": "5.0.0-nightly.20260617",
76
+ "@aztec/sequencer-client": "5.0.0-nightly.20260617",
77
+ "@aztec/simulator": "5.0.0-nightly.20260617",
78
+ "@aztec/stdlib": "5.0.0-nightly.20260617",
79
+ "@aztec/telemetry-client": "5.0.0-nightly.20260617",
80
+ "@aztec/world-state": "5.0.0-nightly.20260617",
81
81
  "source-map-support": "^0.5.21",
82
82
  "tslib": "^2.4.0",
83
83
  "viem": "npm:@aztec/viem@2.38.2"
@@ -1,4 +1,4 @@
1
- import type { CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
1
+ import type { BlockNumber, CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
2
2
  import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
3
3
  import { RunningPromise } from '@aztec/foundation/promise';
4
4
  import type { L2BlockSource } from '@aztec/stdlib/block';
@@ -97,14 +97,19 @@ export class CheckpointStore {
97
97
  }
98
98
 
99
99
  /**
100
- * Marks every canonical prover whose checkpoint number is strictly greater than
101
- * `prunedNumber` as pruned. Sub-tree work keeps running so a re-add of the same
102
- * content can pick it up. Returns the affected provers.
100
+ * Marks every canonical prover that holds a block above the prune target as pruned. A checkpoint is orphaned by a
101
+ * prune to block `targetBlockNumber` iff its last block sits above the target — including a checkpoint whose range
102
+ * straddles the target (partially orphaned), which block-range marking catches without boundary ambiguity. Keying
103
+ * off the surviving block number (rather than a checkpoint number) is correct even when the source has already
104
+ * re-checkpointed past the divergence: the prune event reports the highest surviving block, which by construction
105
+ * survives on the source, whereas the source's current checkpointed tip can sit above the prune target.
106
+ * Sub-tree work keeps running so a re-add of the same content can pick it up. Returns the affected provers.
103
107
  */
104
- public markPrunedAfter(prunedNumber: CheckpointNumber): CheckpointProver[] {
108
+ public markPrunedAboveBlock(targetBlockNumber: BlockNumber): CheckpointProver[] {
105
109
  const affected: CheckpointProver[] = [];
106
110
  for (const prover of this.provers.values()) {
107
- if (prover.checkpoint.number > prunedNumber && !prover.isPruned()) {
111
+ const lastBlockNumber = prover.checkpoint.blocks.at(-1)!.number;
112
+ if (lastBlockNumber > targetBlockNumber && !prover.isPruned()) {
108
113
  prover.markPruned();
109
114
  affected.push(prover);
110
115
  }
@@ -5,12 +5,14 @@ import { BlockNumber, CheckpointNumber, EpochNumber } from '@aztec/foundation/br
5
5
  import { assertRequired, compact, pick } from '@aztec/foundation/collection';
6
6
  import { memoize } from '@aztec/foundation/decorators';
7
7
  import { createLogger } from '@aztec/foundation/log';
8
+ import { RunningPromise } from '@aztec/foundation/running-promise';
8
9
  import { DateProvider, executeTimeout } from '@aztec/foundation/timer';
9
10
  import type { EpochProverFactory } from '@aztec/prover-client';
10
11
  import { getLastSiblingPath } from '@aztec/prover-client/helpers';
11
12
  import { ChonkCache } from '@aztec/prover-client/orchestrator';
12
13
  import { PublicProcessorFactory } from '@aztec/simulator/server';
13
14
  import {
15
+ type L2BlockId,
14
16
  type L2BlockSource,
15
17
  L2BlockStream,
16
18
  type L2BlockStreamEvent,
@@ -95,6 +97,17 @@ export class ProverNode implements L2BlockStreamEventHandler, ProverNodeApi, Tra
95
97
  */
96
98
  protected lastExpiredEpoch: EpochNumber | undefined;
97
99
 
100
+ /**
101
+ * Highest checkpoint number whose proving-side handling has completed (or that was legitimately skipped).
102
+ * The catch-up loop walks from here to each `chain-checkpointed` tip event. Seeded at start() from the last
103
+ * checkpoint of the last fully-proven epoch (or 0), so a restart reprocesses the partially-proven epoch rather
104
+ * than trusting a checkpointed tip that may sit ahead of unproven checkpoints. Clamped down on a prune.
105
+ */
106
+ protected lastProcessedCheckpoint: CheckpointNumber = CheckpointNumber.ZERO;
107
+
108
+ /** Periodic tick that runs the epoch-expiry sweep during idle periods when no block-stream events arrive. */
109
+ private expiryTicker: RunningPromise | undefined;
110
+
98
111
  public readonly tracer: Tracer;
99
112
 
100
113
  protected publishingService: ProofPublishingService | undefined;
@@ -219,17 +232,25 @@ export class ProverNode implements L2BlockStreamEventHandler, ProverNodeApi, Tra
219
232
  public async handleBlockStreamEvent(event: L2BlockStreamEvent): Promise<void> {
220
233
  switch (event.type) {
221
234
  case 'chain-checkpointed':
222
- await this.handleCheckpointEvent(event.checkpoint);
235
+ await this.processCheckpointJump(event.checkpoint.number);
223
236
  break;
224
237
  case 'chain-pruned':
225
- await this.handlePruneEvent(event.checkpointed.checkpoint);
238
+ await this.handlePruneEvent(event.block);
226
239
  break;
227
240
  case 'chain-proven':
228
241
  this.publishingService?.onChainProven(BlockNumber(event.block.number));
229
242
  break;
243
+ // The proposed tip drives only the tips store's walk-back history (recorded below); the prover-node
244
+ // tracks checkpoints, not proposed blocks. `blocks-added` is never emitted in tips-only mode, and
245
+ // `chain-finalized` carries nothing the prover-node acts on.
246
+ case 'chain-proposed':
230
247
  case 'chain-finalized':
231
248
  case 'blocks-added':
232
249
  break;
250
+ default: {
251
+ const _: never = event;
252
+ break;
253
+ }
233
254
  }
234
255
  // Expiry is driven by the archiver's latest synced L2 slot
235
256
  await this.checkEpochExpiry();
@@ -239,34 +260,92 @@ export class ProverNode implements L2BlockStreamEventHandler, ProverNodeApi, Tra
239
260
  await this.tipsStore.handleBlockStreamEvent(event);
240
261
  }
241
262
 
242
- /** Register a new checkpoint with the store and notify the session manager. */
243
- private async handleCheckpointEvent(publishedCheckpoint: PublishedCheckpoint) {
244
- const checkpoint = publishedCheckpoint.checkpoint;
245
- const slotNumber = checkpoint.header.slotNumber;
246
- const l1Constants = await this.getL1Constants();
247
- const epochNumber = getEpochAtSlot(slotNumber, l1Constants);
248
-
249
- if (await this.isEpochFullyProven(epochNumber, l1Constants)) {
250
- this.log.debug(`Skipping checkpoint ${checkpoint.number} for already-proven epoch ${epochNumber}`);
263
+ /**
264
+ * Walks every checkpoint between the local cursor and the newly-reported checkpointed tip, registering
265
+ * each one that belongs to an epoch that can still be proven. The block stream now delivers a single thin
266
+ * `chain-checkpointed` tip event per pass rather than one fat event per checkpoint, so this drives the
267
+ * catch-up itself: light metadata first (`getCheckpointsData`) to decide relevance per epoch, then a heavy
268
+ * `getCheckpoints` fetch only for checkpoints in provable epochs.
269
+ *
270
+ * The cursor advances one checkpoint at a time and only after that checkpoint's proving-side handling has
271
+ * fully succeeded, preserving the A-1041 at-least-once semantics: a mid-jump failure leaves the cursor
272
+ * behind so the next pass retries from the first checkpoint that did not complete.
273
+ */
274
+ private async processCheckpointJump(targetCheckpoint: CheckpointNumber): Promise<void> {
275
+ if (targetCheckpoint <= this.lastProcessedCheckpoint) {
251
276
  return;
252
277
  }
278
+ const l1Constants = await this.getL1Constants();
253
279
 
254
- if (await this.isEpochPastProofSubmissionWindow(epochNumber, l1Constants)) {
255
- this.log.debug(
256
- `Skipping checkpoint ${checkpoint.number} for epoch ${epochNumber} past its proof-submission window`,
257
- );
258
- return;
280
+ // Cap the catch-up at the `(proofSubmissionEpochs + 1) * epochDuration` most recent checkpoints.
281
+ // When the cursor is much further behind (e.g. resyncing after a long time offline), fetching the whole gap could
282
+ // load thousands of checkpoints we cannot act on: anything older than the last two epochs is already past
283
+ // its proof-submission window, so we skip it and jump the cursor forward to the start of the capped range.
284
+ const maxCheckpoints = (l1Constants.proofSubmissionEpochs + 1) * l1Constants.epochDuration;
285
+ let from = CheckpointNumber(this.lastProcessedCheckpoint + 1);
286
+ if (Number(targetCheckpoint - from) + 1 > maxCheckpoints) {
287
+ const cappedFrom = CheckpointNumber(targetCheckpoint - maxCheckpoints + 1);
288
+ this.log.warn(`Skipping unprovable checkpoints during catch-up; the prover node is far behind`, {
289
+ from,
290
+ cappedFrom,
291
+ targetCheckpoint,
292
+ maxCheckpoints,
293
+ });
294
+ // Advance the cursor past the skipped checkpoints so they are never retried.
295
+ this.lastProcessedCheckpoint = CheckpointNumber(cappedFrom - 1);
296
+ from = cappedFrom;
259
297
  }
298
+ const limit = Number(targetCheckpoint - from) + 1;
299
+ const metadatas = await this.l2BlockSource.getCheckpointsData({ from, limit });
300
+
301
+ // Per-epoch relevance is cached so a multi-checkpoint epoch resolves it once. Skipping is whole-epoch
302
+ // only: the SessionManager requires an epoch's checkpoints fully covered before it opens a session, so we
303
+ // never drop an individual checkpoint inside an epoch we will prove.
304
+ const epochSkippable = new Map<EpochNumber, boolean>();
305
+ for (const metadata of metadatas) {
306
+ const epochNumber = getEpochAtSlot(metadata.header.slotNumber, l1Constants);
307
+ let skippable = epochSkippable.get(epochNumber);
308
+ if (skippable === undefined) {
309
+ skippable =
310
+ (await this.isEpochFullyProven(epochNumber, l1Constants)) ||
311
+ (await this.isEpochPastProofSubmissionWindow(epochNumber, l1Constants));
312
+ epochSkippable.set(epochNumber, skippable);
313
+ }
314
+ if (skippable) {
315
+ this.log.debug(`Skipping checkpoint ${metadata.checkpointNumber} for unprovable epoch ${epochNumber}`);
316
+ } else {
317
+ await this.registerCheckpoint(metadata.checkpointNumber, epochNumber);
318
+ }
319
+ // Advance only after the checkpoint's handling succeeded (or it was legitimately skipped). registerCheckpoint
320
+ // throws on failure, which leaves the cursor here for the next pass to retry (A-1041).
321
+ this.lastProcessedCheckpoint = metadata.checkpointNumber;
322
+ }
323
+ }
260
324
 
325
+ /** Heavy-fetch a single checkpoint, register it with the store, and notify the session manager. */
326
+ private async registerCheckpoint(checkpointNumber: CheckpointNumber, epochNumber: EpochNumber): Promise<void> {
327
+ const published = await this.l2BlockSource.getCheckpoint({ number: checkpointNumber });
328
+ if (!published) {
329
+ throw new Error(`Checkpoint ${checkpointNumber} not found in block source during catch-up`);
330
+ }
331
+ const checkpoint = published.checkpoint;
261
332
  this.log.info(`New checkpoint ${checkpoint.number} for epoch ${epochNumber}`, {
262
333
  checkpointNumber: checkpoint.number,
263
334
  epochNumber,
264
- slotNumber,
335
+ slotNumber: checkpoint.header.slotNumber,
265
336
  });
266
337
 
267
- const registerData = await this.collectRegisterData(checkpoint, publishedCheckpoint.attestations);
338
+ const registerData = await this.collectRegisterData(checkpoint, published.attestations);
268
339
  await this.checkpointStore.addOrUpdate(checkpoint, registerData);
269
340
  await this.sessionManager?.onCheckpointAdded(epochNumber);
341
+
342
+ // Tips-only mode delivers no blocks, so record one witness per checkpointed block: a reorg into the checkpoint's
343
+ // range then prunes at the true divergence instead of the nearest sparse tip anchor.
344
+ await this.tipsStore.recordBlockHashes(
345
+ await Promise.all(
346
+ checkpoint.blocks.map(async block => ({ number: block.number, hash: (await block.header.hash()).toString() })),
347
+ ),
348
+ );
270
349
  }
271
350
 
272
351
  /**
@@ -295,10 +374,41 @@ export class ProverNode implements L2BlockStreamEventHandler, ProverNodeApi, Tra
295
374
  };
296
375
  }
297
376
 
298
- /** Mark every prover above the prune threshold as pruned and notify the session manager. */
299
- private async handlePruneEvent(prunedCheckpoint: { number: CheckpointNumber; hash: string }) {
300
- this.log.warn(`Chain pruned to checkpoint ${prunedCheckpoint.number}`, { prunedCheckpoint });
301
- const affected = this.checkpointStore.markPrunedAfter(prunedCheckpoint.number);
377
+ /**
378
+ * Marks every prover orphaned by the prune as pruned, clamps the catch-up cursor below the prune target's
379
+ * checkpoint, and notifies the session manager. Keyed off the prune target block (the highest surviving block)
380
+ * rather than the source's checkpointed tip, which can sit above the target after a re-checkpoint and would leave
381
+ * orphaned provers canonical. Throws (rather than warning) if the cursor floor cannot be resolved, so the pass
382
+ * fails and the prune is retried next iteration.
383
+ */
384
+ private async handlePruneEvent(prunedToBlock: L2BlockId) {
385
+ this.log.warn(`Chain pruned to block ${prunedToBlock.number}`, { prunedToBlock });
386
+
387
+ // Resolve the cursor floor BEFORE marking provers: markPrunedAboveBlock returns only newly-marked provers, so a
388
+ // throw after marking would leave a retry pass with nothing to act on. Resolving first means a throw leaves
389
+ // everything untouched and the next pass retries the whole handler (the tips cursor only advances on success).
390
+ let cursorFloor: CheckpointNumber;
391
+ if (prunedToBlock.number === 0) {
392
+ cursorFloor = CheckpointNumber.ZERO;
393
+ } else {
394
+ const targetData = await this.l2BlockSource.getBlockData({ number: prunedToBlock.number });
395
+ if (targetData === undefined) {
396
+ throw new Error(
397
+ `No block data found for prune target block ${prunedToBlock.number}; cannot clamp checkpoint cursor`,
398
+ );
399
+ }
400
+ // Clamp to `cpAtTarget - 1`: a mid-checkpoint target leaves that checkpoint partially orphaned and it must be
401
+ // reprocessed. Over-clamping merely re-registers a checkpoint (at-least-once by design — A-1041); under-clamping
402
+ // would permanently skip a rebuilt same-number checkpoint.
403
+ cursorFloor = CheckpointNumber(Math.max(0, Number(targetData.checkpointNumber) - 1));
404
+ }
405
+
406
+ const affected = this.checkpointStore.markPrunedAboveBlock(prunedToBlock.number);
407
+
408
+ if (this.lastProcessedCheckpoint > cursorFloor) {
409
+ this.lastProcessedCheckpoint = cursorFloor;
410
+ }
411
+
302
412
  if (affected.length === 0) {
303
413
  return;
304
414
  }
@@ -409,14 +519,24 @@ export class ProverNode implements L2BlockStreamEventHandler, ProverNodeApi, Tra
409
519
  // Now that the store + manager exist, arm the live-state observable gauges.
410
520
  this.jobMetrics.observeState(this.checkpointStore, this.sessionManager);
411
521
 
412
- const { startingBlock, lastFullyProvenEpoch } = await this.computeStartupState();
522
+ const { lastFullyProvenEpoch } = await this.resolveLastFullyProvenEpoch();
413
523
  this.lastExpiredEpoch = lastFullyProvenEpoch;
524
+ this.lastProcessedCheckpoint = await this.computeStartingCheckpoint(lastFullyProvenEpoch);
414
525
  this.blockStream = new L2BlockStream(this.l2BlockSource, this.tipsStore, this, this.log, {
415
526
  pollIntervalMS: this.config.proverNodePollingIntervalMs,
416
- startingBlock,
527
+ tipsOnly: true,
417
528
  });
418
529
  this.blockStream.start();
419
530
 
531
+ // With thin once-per-pass tip events, the expiry sweep no longer fires once per checkpoint; drive it
532
+ // from a periodic tick so epochs still expire during idle/no-event periods.
533
+ this.expiryTicker = new RunningPromise(
534
+ () => this.checkEpochExpiry(),
535
+ this.log,
536
+ this.config.proverNodePollingIntervalMs,
537
+ );
538
+ this.expiryTicker.start();
539
+
420
540
  await this.rewardsMetrics.start();
421
541
  this.l1Metrics.start();
422
542
  this.log.info(`Started Prover Node with prover id ${this.prover.getProverId().toString()}`, this.config);
@@ -426,6 +546,7 @@ export class ProverNode implements L2BlockStreamEventHandler, ProverNodeApi, Tra
426
546
  this.log.info('Stopping ProverNode');
427
547
  this.jobMetrics.stopObservingState();
428
548
  await this.blockStream?.stop();
549
+ await this.expiryTicker?.stop();
429
550
  if (this.sessionManager) {
430
551
  await this.sessionManager.stop();
431
552
  }
@@ -552,38 +673,40 @@ export class ProverNode implements L2BlockStreamEventHandler, ProverNodeApi, Tra
552
673
  }
553
674
 
554
675
  /**
555
- * Resolves the L2BlockStream's starting block and the last fully-proven epoch in one
556
- * pass. The starting block is the first block of the next unproven epoch (or the start
557
- * of the partially-proven epoch if the proven tip falls mid-epoch). The fully-proven
558
- * epoch is `provenEpoch` when the proven tip is the last block of its epoch, otherwise
559
- * `provenEpoch - 1`, or `undefined` if no block is proven yet.
676
+ * Resolves the last fully-proven epoch from L1 proven state, used to seed the catch-up cursor (via
677
+ * `computeStartingCheckpoint`) and `lastExpiredEpoch`. The fully-proven epoch is `provenEpoch` when the
678
+ * proven tip is the last block of its epoch, otherwise `provenEpoch - 1`, or `undefined` if no block is
679
+ * proven yet (so a restart reprocesses the partially-proven epoch rather than trusting a stale tip).
560
680
  */
561
- protected async computeStartupState(): Promise<{
562
- startingBlock: BlockNumber;
563
- lastFullyProvenEpoch: EpochNumber | undefined;
564
- }> {
681
+ protected async resolveLastFullyProvenEpoch(): Promise<{ lastFullyProvenEpoch: EpochNumber | undefined }> {
565
682
  const provenBlockNumber = await this.l2BlockSource.getBlockNumber({ tag: 'proven' });
566
683
  if (!provenBlockNumber || provenBlockNumber <= 0) {
567
- return { startingBlock: BlockNumber(1), lastFullyProvenEpoch: undefined };
684
+ return { lastFullyProvenEpoch: undefined };
568
685
  }
569
686
  const l1Constants = await this.getL1Constants();
570
687
  const provenHeader = (await this.l2BlockSource.getBlockData({ number: BlockNumber(provenBlockNumber) }))?.header;
571
688
  if (!provenHeader) {
572
- return { startingBlock: BlockNumber(provenBlockNumber + 1), lastFullyProvenEpoch: undefined };
689
+ return { lastFullyProvenEpoch: undefined };
573
690
  }
574
691
  const provenEpoch = getEpochAtSlot(provenHeader.getSlot(), l1Constants);
575
692
  if (await this.isProvenBlockLastOfItsEpoch(BlockNumber(provenBlockNumber), provenEpoch, l1Constants)) {
576
- return { startingBlock: BlockNumber(provenBlockNumber + 1), lastFullyProvenEpoch: provenEpoch };
693
+ return { lastFullyProvenEpoch: provenEpoch };
577
694
  }
578
- const epochCheckpoints = await this.l2BlockSource.getCheckpointsData({ epoch: provenEpoch });
579
- const firstBlockOfEpoch =
580
- epochCheckpoints.length > 0 ? epochCheckpoints[0].startBlock : BlockNumber(provenBlockNumber);
581
- this.log.info(
582
- `Starting L2BlockStream at block ${firstBlockOfEpoch} (start of partially-proven epoch ${provenEpoch})`,
583
- { provenBlockNumber, provenEpoch, firstBlockOfEpoch },
584
- );
585
695
  const lastFullyProvenEpoch = provenEpoch > 0 ? EpochNumber(provenEpoch - 1) : undefined;
586
- return { startingBlock: firstBlockOfEpoch, lastFullyProvenEpoch };
696
+ return { lastFullyProvenEpoch };
697
+ }
698
+
699
+ /**
700
+ * Resolves the catch-up cursor seed: the last checkpoint of the last fully-proven epoch, or 0 if none. Seeding
701
+ * from a checkpoint (rather than a checkpointed tip) guarantees a restart reprocesses every checkpoint of the
702
+ * partially-proven epoch, since the checkpointed tip can sit ahead of the last fully-proven checkpoint.
703
+ */
704
+ protected async computeStartingCheckpoint(lastFullyProvenEpoch: EpochNumber | undefined): Promise<CheckpointNumber> {
705
+ if (lastFullyProvenEpoch === undefined) {
706
+ return CheckpointNumber.ZERO;
707
+ }
708
+ const checkpoints = await this.l2BlockSource.getCheckpointsData({ epoch: lastFullyProvenEpoch });
709
+ return checkpoints.at(-1)?.checkpointNumber ?? CheckpointNumber.ZERO;
587
710
  }
588
711
 
589
712
  private async gatherPreviousBlockHeader(previousBlockNumber: number) {