@aztec/prover-node 5.0.0-nightly.20260616 → 5.0.0-nightly.20260618
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.
- package/dest/checkpoint-store.d.ts +10 -6
- package/dest/checkpoint-store.d.ts.map +1 -1
- package/dest/checkpoint-store.js +10 -5
- package/dest/prover-node.d.ts +24 -10
- package/dest/prover-node.d.ts.map +1 -1
- package/dest/prover-node.js +150 -40
- package/package.json +23 -23
- package/src/checkpoint-store.ts +11 -6
- package/src/prover-node.ts +167 -44
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
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
|
|
46
|
-
* `
|
|
47
|
-
*
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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"}
|
package/dest/checkpoint-store.js
CHANGED
|
@@ -79,13 +79,18 @@ import { CheckpointProver } from './job/checkpoint-prover.js';
|
|
|
79
79
|
return prover;
|
|
80
80
|
}
|
|
81
81
|
/**
|
|
82
|
-
* Marks every canonical prover
|
|
83
|
-
* `
|
|
84
|
-
*
|
|
85
|
-
|
|
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
|
-
|
|
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
|
}
|
package/dest/prover-node.d.ts
CHANGED
|
@@ -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
|
|
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
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
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
|
|
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,
|
|
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":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"prover-node.d.ts","sourceRoot":"","sources":["../src/prover-node.ts"],"names":[],"mappings":"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"}
|
package/dest/prover-node.js
CHANGED
|
@@ -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.
|
|
540
|
+
await this.processCheckpointJump(event.checkpoint.number);
|
|
532
541
|
break;
|
|
533
542
|
case 'chain-pruned':
|
|
534
|
-
await this.handlePruneEvent(event.
|
|
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
|
-
/**
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
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
|
-
|
|
560
|
-
|
|
561
|
-
|
|
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,
|
|
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
|
-
/**
|
|
591
|
-
|
|
592
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
-
|
|
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
|
|
807
|
-
*
|
|
808
|
-
*
|
|
809
|
-
*
|
|
810
|
-
|
|
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.
|
|
3
|
+
"version": "5.0.0-nightly.20260618",
|
|
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.
|
|
60
|
-
"@aztec/bb-prover": "5.0.0-nightly.
|
|
61
|
-
"@aztec/blob-client": "5.0.0-nightly.
|
|
62
|
-
"@aztec/blob-lib": "5.0.0-nightly.
|
|
63
|
-
"@aztec/constants": "5.0.0-nightly.
|
|
64
|
-
"@aztec/epoch-cache": "5.0.0-nightly.
|
|
65
|
-
"@aztec/ethereum": "5.0.0-nightly.
|
|
66
|
-
"@aztec/foundation": "5.0.0-nightly.
|
|
67
|
-
"@aztec/kv-store": "5.0.0-nightly.
|
|
68
|
-
"@aztec/l1-artifacts": "5.0.0-nightly.
|
|
69
|
-
"@aztec/native": "5.0.0-nightly.
|
|
70
|
-
"@aztec/node-keystore": "5.0.0-nightly.
|
|
71
|
-
"@aztec/node-lib": "5.0.0-nightly.
|
|
72
|
-
"@aztec/noir-protocol-circuits-types": "5.0.0-nightly.
|
|
73
|
-
"@aztec/p2p": "5.0.0-nightly.
|
|
74
|
-
"@aztec/protocol-contracts": "5.0.0-nightly.
|
|
75
|
-
"@aztec/prover-client": "5.0.0-nightly.
|
|
76
|
-
"@aztec/sequencer-client": "5.0.0-nightly.
|
|
77
|
-
"@aztec/simulator": "5.0.0-nightly.
|
|
78
|
-
"@aztec/stdlib": "5.0.0-nightly.
|
|
79
|
-
"@aztec/telemetry-client": "5.0.0-nightly.
|
|
80
|
-
"@aztec/world-state": "5.0.0-nightly.
|
|
59
|
+
"@aztec/archiver": "5.0.0-nightly.20260618",
|
|
60
|
+
"@aztec/bb-prover": "5.0.0-nightly.20260618",
|
|
61
|
+
"@aztec/blob-client": "5.0.0-nightly.20260618",
|
|
62
|
+
"@aztec/blob-lib": "5.0.0-nightly.20260618",
|
|
63
|
+
"@aztec/constants": "5.0.0-nightly.20260618",
|
|
64
|
+
"@aztec/epoch-cache": "5.0.0-nightly.20260618",
|
|
65
|
+
"@aztec/ethereum": "5.0.0-nightly.20260618",
|
|
66
|
+
"@aztec/foundation": "5.0.0-nightly.20260618",
|
|
67
|
+
"@aztec/kv-store": "5.0.0-nightly.20260618",
|
|
68
|
+
"@aztec/l1-artifacts": "5.0.0-nightly.20260618",
|
|
69
|
+
"@aztec/native": "5.0.0-nightly.20260618",
|
|
70
|
+
"@aztec/node-keystore": "5.0.0-nightly.20260618",
|
|
71
|
+
"@aztec/node-lib": "5.0.0-nightly.20260618",
|
|
72
|
+
"@aztec/noir-protocol-circuits-types": "5.0.0-nightly.20260618",
|
|
73
|
+
"@aztec/p2p": "5.0.0-nightly.20260618",
|
|
74
|
+
"@aztec/protocol-contracts": "5.0.0-nightly.20260618",
|
|
75
|
+
"@aztec/prover-client": "5.0.0-nightly.20260618",
|
|
76
|
+
"@aztec/sequencer-client": "5.0.0-nightly.20260618",
|
|
77
|
+
"@aztec/simulator": "5.0.0-nightly.20260618",
|
|
78
|
+
"@aztec/stdlib": "5.0.0-nightly.20260618",
|
|
79
|
+
"@aztec/telemetry-client": "5.0.0-nightly.20260618",
|
|
80
|
+
"@aztec/world-state": "5.0.0-nightly.20260618",
|
|
81
81
|
"source-map-support": "^0.5.21",
|
|
82
82
|
"tslib": "^2.4.0",
|
|
83
83
|
"viem": "npm:@aztec/viem@2.38.2"
|
package/src/checkpoint-store.ts
CHANGED
|
@@ -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
|
|
101
|
-
* `
|
|
102
|
-
*
|
|
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
|
|
108
|
+
public markPrunedAboveBlock(targetBlockNumber: BlockNumber): CheckpointProver[] {
|
|
105
109
|
const affected: CheckpointProver[] = [];
|
|
106
110
|
for (const prover of this.provers.values()) {
|
|
107
|
-
|
|
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
|
}
|
package/src/prover-node.ts
CHANGED
|
@@ -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.
|
|
235
|
+
await this.processCheckpointJump(event.checkpoint.number);
|
|
223
236
|
break;
|
|
224
237
|
case 'chain-pruned':
|
|
225
|
-
await this.handlePruneEvent(event.
|
|
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
|
-
/**
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
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
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
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,
|
|
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
|
-
/**
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
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 {
|
|
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
|
-
|
|
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
|
|
556
|
-
*
|
|
557
|
-
*
|
|
558
|
-
*
|
|
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
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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) {
|