@aztec/prover-node 0.0.1-commit.993d52e → 0.0.1-commit.9a89641
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/README.md +572 -0
- package/dest/actions/download-epoch-proving-job.js +1 -1
- package/dest/actions/rerun-epoch-proving-job.d.ts +14 -4
- package/dest/actions/rerun-epoch-proving-job.d.ts.map +1 -1
- package/dest/actions/rerun-epoch-proving-job.js +244 -24
- package/dest/actions/upload-epoch-proof-failure.d.ts +2 -2
- package/dest/actions/upload-epoch-proof-failure.d.ts.map +1 -1
- package/dest/bin/run-failed-epoch.js +1 -3
- package/dest/checkpoint-store.d.ts +95 -0
- package/dest/checkpoint-store.d.ts.map +1 -0
- package/dest/checkpoint-store.js +178 -0
- package/dest/config.d.ts +4 -2
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +10 -3
- package/dest/factory.d.ts +4 -1
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +28 -12
- package/dest/index.d.ts +2 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -0
- package/dest/job/checkpoint-prover.d.ts +165 -0
- package/dest/job/checkpoint-prover.d.ts.map +1 -0
- package/dest/job/checkpoint-prover.js +405 -0
- package/dest/job/epoch-session.d.ts +160 -0
- package/dest/job/epoch-session.d.ts.map +1 -0
- package/dest/job/epoch-session.js +744 -0
- package/dest/job/top-tree-job.d.ts +82 -0
- package/dest/job/top-tree-job.d.ts.map +1 -0
- package/dest/job/top-tree-job.js +152 -0
- package/dest/metrics.d.ts +40 -3
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +101 -4
- package/dest/monitors/epoch-monitor.d.ts +1 -1
- package/dest/monitors/epoch-monitor.d.ts.map +1 -1
- package/dest/monitors/epoch-monitor.js +11 -9
- package/dest/proof-publishing-service.d.ts +161 -0
- package/dest/proof-publishing-service.d.ts.map +1 -0
- package/dest/proof-publishing-service.js +335 -0
- package/dest/prover-node-publisher.d.ts +25 -15
- package/dest/prover-node-publisher.d.ts.map +1 -1
- package/dest/prover-node-publisher.js +201 -62
- package/dest/prover-node.d.ts +134 -67
- package/dest/prover-node.d.ts.map +1 -1
- package/dest/prover-node.js +539 -218
- package/dest/prover-publisher-factory.d.ts +4 -2
- package/dest/prover-publisher-factory.d.ts.map +1 -1
- package/dest/prover-publisher-factory.js +4 -3
- package/dest/session-manager.d.ts +158 -0
- package/dest/session-manager.d.ts.map +1 -0
- package/dest/session-manager.js +492 -0
- package/dest/test/index.d.ts +7 -6
- package/dest/test/index.d.ts.map +1 -1
- package/package.json +24 -22
- package/src/actions/download-epoch-proving-job.ts +1 -1
- package/src/actions/rerun-epoch-proving-job.ts +190 -31
- package/src/actions/upload-epoch-proof-failure.ts +1 -1
- package/src/bin/run-failed-epoch.ts +1 -2
- package/src/checkpoint-store.ts +212 -0
- package/src/config.ts +14 -3
- package/src/factory.ts +26 -12
- package/src/index.ts +1 -0
- package/src/job/checkpoint-prover.ts +538 -0
- package/src/job/epoch-session.ts +462 -0
- package/src/job/top-tree-job.ts +227 -0
- package/src/metrics.ts +123 -10
- package/src/monitors/epoch-monitor.ts +5 -6
- package/src/proof-publishing-service.ts +427 -0
- package/src/prover-node-publisher.ts +236 -78
- package/src/prover-node.ts +622 -243
- package/src/prover-publisher-factory.ts +6 -3
- package/src/session-manager.ts +592 -0
- package/src/test/index.ts +6 -6
- package/dest/job/epoch-proving-job.d.ts +0 -63
- package/dest/job/epoch-proving-job.d.ts.map +0 -1
- package/dest/job/epoch-proving-job.js +0 -752
- package/src/job/epoch-proving-job.ts +0 -449
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
|
|
2
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
3
|
+
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
4
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
|
+
import { promiseWithResolvers } from '@aztec/foundation/promise';
|
|
6
|
+
import { Timer } from '@aztec/foundation/timer';
|
|
7
|
+
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
8
|
+
import { protocolContractsHash } from '@aztec/protocol-contracts';
|
|
9
|
+
import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
|
|
10
|
+
import { CheckpointConstantData } from '@aztec/stdlib/rollup';
|
|
11
|
+
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
12
|
+
/**
|
|
13
|
+
* Self-contained per-checkpoint prover, content-addressed by
|
|
14
|
+
* `(checkpoint number, slot number, checkpoint archive root)`.
|
|
15
|
+
*
|
|
16
|
+
* The store creates a CheckpointProver once per content-key. Keying on the checkpoint's
|
|
17
|
+
* own archive root (its post-state) means two checkpoints are "the same" iff they
|
|
18
|
+
* produce the same archive — so a reorg branch, or a replacement built on the same
|
|
19
|
+
* predecessor but with different content, keys to a distinct prover.
|
|
20
|
+
*
|
|
21
|
+
* The prover eagerly starts its own tx gather and sub-tree work in the constructor, so
|
|
22
|
+
* callers only need to call `whenBlockProofsReady()` to obtain the resulting block-rollup
|
|
23
|
+
* proofs.
|
|
24
|
+
*
|
|
25
|
+
* A CheckpointProver does not survive a prune: its sub-tree work forks world-state per
|
|
26
|
+
* block, and an L1 prune of a base block faults those reads. The store therefore cancels and
|
|
27
|
+
* discards a prover when its checkpoint is pruned, and a re-add (even of identical content)
|
|
28
|
+
* constructs a fresh prover.
|
|
29
|
+
*
|
|
30
|
+
* `cancel()` is idempotent. It aborts the gather + sub-tree, rejects the block-proof
|
|
31
|
+
* promise, and exposes a `whenDone()` that resolves once teardown has unwound.
|
|
32
|
+
*/ export class CheckpointProver {
|
|
33
|
+
deps;
|
|
34
|
+
id;
|
|
35
|
+
checkpoint;
|
|
36
|
+
epochNumber;
|
|
37
|
+
slotNumber;
|
|
38
|
+
attestations;
|
|
39
|
+
previousBlockHeader;
|
|
40
|
+
l1ToL2Messages;
|
|
41
|
+
previousArchiveSiblingPath;
|
|
42
|
+
/** Resolved by the sub-tree on success, rejected on cancel/failure. */ blockProofs;
|
|
43
|
+
// Three independent lifecycle facts — deliberately not collapsed into one status enum, because several
|
|
44
|
+
// combinations are legal and relied on: a prover can be `completed` and then `cancelled` (routine
|
|
45
|
+
// teardown of an already-proven checkpoint), or `completed` and then `failed` (block proving was
|
|
46
|
+
// enqueued, but the sub-tree subsequently faulted). Only `failed` + `cancelled` is excluded — a cancel
|
|
47
|
+
// is not a failure (enforced in `failBlockProofs`).
|
|
48
|
+
/** Block-level proving was fully *enqueued* (a progress marker; the sub-tree may still be proving). */ completed;
|
|
49
|
+
/** Block proofs rejected for a genuine (non-cancel) reason — a sub-tree or prune-induced fork fault. */ failed;
|
|
50
|
+
/** The prover was torn down (prune / reap / shutdown). */ cancelled;
|
|
51
|
+
subTree;
|
|
52
|
+
abortController;
|
|
53
|
+
/** Tracks the eager gather+execute task so `cancel()` and `whenDone()` can await its unwind. */ runPromise;
|
|
54
|
+
/** Tracks the cancel-driven teardown so `whenDone()` can await it. */ cancelPromise;
|
|
55
|
+
/** Tracks the success-driven sub-tree teardown (once block proofs are captured) so `whenDone()` can await it. */ teardownPromise;
|
|
56
|
+
constructor(args, deps){
|
|
57
|
+
this.deps = deps;
|
|
58
|
+
this.blockProofs = promiseWithResolvers();
|
|
59
|
+
this.completed = false;
|
|
60
|
+
this.failed = false;
|
|
61
|
+
this.cancelled = false;
|
|
62
|
+
this.abortController = new AbortController();
|
|
63
|
+
this.checkpoint = args.checkpoint;
|
|
64
|
+
this.epochNumber = args.epochNumber;
|
|
65
|
+
this.slotNumber = args.checkpoint.header.slotNumber;
|
|
66
|
+
this.attestations = args.attestations;
|
|
67
|
+
this.previousBlockHeader = args.previousBlockHeader;
|
|
68
|
+
this.l1ToL2Messages = args.l1ToL2Messages;
|
|
69
|
+
this.previousArchiveSiblingPath = args.previousArchiveSiblingPath;
|
|
70
|
+
this.id = CheckpointProver.idFor(args.checkpoint);
|
|
71
|
+
// Mark blockProofs as observed so a cancel that lands before any consumer awaits
|
|
72
|
+
// does not surface as an unhandled rejection.
|
|
73
|
+
this.blockProofs.promise.catch(()=>{});
|
|
74
|
+
deps.log.info(`Created CheckpointProver ${this.id}`, {
|
|
75
|
+
checkpointNumber: this.checkpoint.number,
|
|
76
|
+
epochNumber: this.epochNumber,
|
|
77
|
+
slotNumber: this.slotNumber,
|
|
78
|
+
blockCount: this.checkpoint.blocks.length,
|
|
79
|
+
l1ToL2MessageCount: this.l1ToL2Messages.length,
|
|
80
|
+
archiveRoot: this.checkpoint.archive.root.toString()
|
|
81
|
+
});
|
|
82
|
+
// Kick off the eager gather + sub-tree pipeline.
|
|
83
|
+
this.runPromise = this.gatherAndExecute();
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Stable content-addressed identifier: `${checkpoint number}:${slot}:${archive root}`.
|
|
87
|
+
* The archive root is the checkpoint's post-state, so it distinguishes any two
|
|
88
|
+
* checkpoints that differ in history or content while collapsing identical re-adds.
|
|
89
|
+
*/ static idFor(checkpoint) {
|
|
90
|
+
return `${checkpoint.number}:${checkpoint.header.slotNumber}:${checkpoint.archive.root.toString()}`;
|
|
91
|
+
}
|
|
92
|
+
isCancelled() {
|
|
93
|
+
return this.cancelled;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* True once this prover's block proofs have rejected for a genuine (non-cancel) reason — a sub-tree
|
|
97
|
+
* proving fault or a prune-induced world-state fork fault. A failed prover cannot produce its block
|
|
98
|
+
* proofs, so the reconciler must not build (or rebuild) an EpochSession over it; it is cleared only by
|
|
99
|
+
* a prune/re-add replacing it with a fresh prover, or by expiry reaping it.
|
|
100
|
+
*/ isFailed() {
|
|
101
|
+
return this.failed;
|
|
102
|
+
}
|
|
103
|
+
/** AbortSignal that fires on cancel — for callers that want to wire their own tasks. */ getAbortSignal() {
|
|
104
|
+
return this.abortController.signal;
|
|
105
|
+
}
|
|
106
|
+
/** Promise that resolves with the block-rollup proofs for this checkpoint (or rejects on cancel/failure). */ whenBlockProofsReady() {
|
|
107
|
+
return this.blockProofs.promise;
|
|
108
|
+
}
|
|
109
|
+
/** Resolves when all in-flight work for this prover has fully unwound. */ async whenDone() {
|
|
110
|
+
await this.runPromise.catch(()=>{});
|
|
111
|
+
// `runPromise` resolves once block-level proving is *enqueued*, but the sub-tree's proofs (and the
|
|
112
|
+
// success-driven teardown they trigger) land later, on the `getSubTreeResult()` callback. Awaiting
|
|
113
|
+
// `blockProofs` here bridges that gap: on success the callback resolves `blockProofs` and then
|
|
114
|
+
// synchronously sets `teardownPromise` before this await resumes, so the teardown is observable
|
|
115
|
+
// below; on failure/cancel `blockProofs` rejects and teardown is driven by the `finally`/cancel
|
|
116
|
+
// paths already awaited via `runPromise`/`cancelPromise`.
|
|
117
|
+
await this.blockProofs.promise.catch(()=>{});
|
|
118
|
+
if (this.cancelPromise) {
|
|
119
|
+
await this.cancelPromise;
|
|
120
|
+
}
|
|
121
|
+
if (this.teardownPromise) {
|
|
122
|
+
await this.teardownPromise;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
async gatherAndExecute() {
|
|
126
|
+
try {
|
|
127
|
+
const txs = await this.gatherTxs();
|
|
128
|
+
if (this.cancelled) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
await this.executeCheckpoint(txs);
|
|
132
|
+
} catch (err) {
|
|
133
|
+
if (this.cancelled) {
|
|
134
|
+
this.deps.log.debug(`CheckpointProver ${this.id} cancelled during gather/execute`, {
|
|
135
|
+
checkpointNumber: this.checkpoint.number
|
|
136
|
+
});
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
this.deps.log.error(`Error in CheckpointProver ${this.id}`, err, {
|
|
140
|
+
checkpointNumber: this.checkpoint.number
|
|
141
|
+
});
|
|
142
|
+
this.failBlockProofs(err instanceof Error ? err : new Error(String(err)));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Rejects the block-proof promise and, unless this is a cancellation, records the prover as failed so
|
|
147
|
+
* the reconciler won't build an EpochSession over it. First rejection wins, so a later duplicate reject
|
|
148
|
+
* (e.g. the executeCheckpoint `finally`) is a harmless no-op.
|
|
149
|
+
*/ failBlockProofs(err) {
|
|
150
|
+
if (!this.cancelled && !this.failed) {
|
|
151
|
+
this.failed = true;
|
|
152
|
+
// Notify the owner so it can upload a post-mortem for this checkpoint. Fire-and-forget: the
|
|
153
|
+
// callback must not block the prover's teardown, and a throw in it must not mask the rejection.
|
|
154
|
+
try {
|
|
155
|
+
this.deps.onFailed?.(this);
|
|
156
|
+
} catch (err) {
|
|
157
|
+
this.deps.log.error(`Error in CheckpointProver onFailed callback for ${this.id}`, err);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
this.blockProofs.reject(err);
|
|
161
|
+
}
|
|
162
|
+
/** Fetches every tx in this checkpoint from the tx pool (by hash, via the block tx effects). */ async fetchTxs() {
|
|
163
|
+
const deadline = new Date(this.deps.dateProvider.now() + this.deps.txGatheringTimeoutMs);
|
|
164
|
+
const txsByBlock = await Promise.all(this.checkpoint.blocks.map((block)=>this.deps.txProvider.getTxsForBlock(block, {
|
|
165
|
+
deadline
|
|
166
|
+
})));
|
|
167
|
+
const txs = txsByBlock.flatMap(({ txs })=>txs);
|
|
168
|
+
const missingTxs = txsByBlock.flatMap(({ missingTxs })=>missingTxs);
|
|
169
|
+
return {
|
|
170
|
+
txs: new Map(txs.map((tx)=>[
|
|
171
|
+
tx.getTxHash().toString(),
|
|
172
|
+
tx
|
|
173
|
+
])),
|
|
174
|
+
missingTxs
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
async gatherTxs() {
|
|
178
|
+
const { txs, missingTxs } = await this.fetchTxs();
|
|
179
|
+
if (missingTxs.length > 0) {
|
|
180
|
+
throw new Error(`Txs not found for checkpoint ${this.checkpoint.number}: ${missingTxs.map((hash)=>hash.toString()).join(', ')}`);
|
|
181
|
+
}
|
|
182
|
+
return txs;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Re-fetches this checkpoint's txs from the tx pool for a post-mortem failure upload.
|
|
186
|
+
*
|
|
187
|
+
* The prover does not cache txs on the heap — they are consumed during proving and dropped — so the
|
|
188
|
+
* durable pool (which keeps a mined tx until L1 finality, with A-1274's retention margin covering a
|
|
189
|
+
* lagging prover) is the source of truth, read back by hash here. Best-effort: any tx the pool can
|
|
190
|
+
* no longer supply is logged and omitted rather than failing the upload, since a partial post-mortem
|
|
191
|
+
* snapshot is still useful for diagnosis.
|
|
192
|
+
*/ async getTxsForUpload() {
|
|
193
|
+
const { txs, missingTxs } = await this.fetchTxs();
|
|
194
|
+
if (missingTxs.length > 0) {
|
|
195
|
+
this.deps.log.warn(`Missing ${missingTxs.length} tx(s) re-fetching checkpoint ${this.checkpoint.number} for failure upload`, {
|
|
196
|
+
checkpointNumber: this.checkpoint.number,
|
|
197
|
+
missingTxCount: missingTxs.length
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
return txs;
|
|
201
|
+
}
|
|
202
|
+
async executeCheckpoint(txs) {
|
|
203
|
+
const signal = this.abortController.signal;
|
|
204
|
+
const checkpointTimer = new Timer();
|
|
205
|
+
let subTreeStarted = false;
|
|
206
|
+
try {
|
|
207
|
+
// Test hook: force a sub-tree failure to exercise the checkpoint failure/upload path.
|
|
208
|
+
if (this.deps.checkpointProveOverride) {
|
|
209
|
+
await this.deps.checkpointProveOverride();
|
|
210
|
+
}
|
|
211
|
+
// The gathered txs are consumed locally below (public processing + sub-tree) and then dropped.
|
|
212
|
+
// They are deliberately not retained on the instance: the tx pool is the durable source and
|
|
213
|
+
// `getTxsForUpload` re-fetches them by hash if a post-mortem upload needs them.
|
|
214
|
+
const { chainId, version } = this.checkpoint.blocks[0].header.globalVariables;
|
|
215
|
+
const checkpointConstants = CheckpointConstantData.from({
|
|
216
|
+
chainId,
|
|
217
|
+
version,
|
|
218
|
+
vkTreeRoot: getVKTreeRoot(),
|
|
219
|
+
protocolContractsHash: protocolContractsHash,
|
|
220
|
+
proverId: this.deps.proverId.toField(),
|
|
221
|
+
slotNumber: this.checkpoint.header.slotNumber,
|
|
222
|
+
coinbase: this.checkpoint.header.coinbase,
|
|
223
|
+
feeRecipient: this.checkpoint.header.feeRecipient,
|
|
224
|
+
gasFees: this.checkpoint.header.gasFees
|
|
225
|
+
});
|
|
226
|
+
this.deps.log.info(`Starting processing checkpoint ${this.checkpoint.number}`, {
|
|
227
|
+
checkpointNumber: this.checkpoint.number,
|
|
228
|
+
checkpointHash: this.checkpoint.hash().toString(),
|
|
229
|
+
blockCount: this.checkpoint.blocks.length
|
|
230
|
+
});
|
|
231
|
+
this.subTree = await this.deps.proverFactory.createCheckpointSubTreeOrchestrator(this.deps.chonkCache, this.epochNumber, checkpointConstants, this.l1ToL2Messages, this.checkpoint.blocks.length, this.previousBlockHeader);
|
|
232
|
+
subTreeStarted = true;
|
|
233
|
+
// Bridge the sub-tree's result onto blockProofs.
|
|
234
|
+
void this.subTree.getSubTreeResult().then((result)=>{
|
|
235
|
+
this.deps.log.info(`Sub-tree block proofs ready for checkpoint ${this.checkpoint.number}`, {
|
|
236
|
+
checkpointNumber: this.checkpoint.number,
|
|
237
|
+
blockProofCount: result.blockProofOutputs.length
|
|
238
|
+
});
|
|
239
|
+
// Spans processing + proving (from executeCheckpoint start, after tx gathering) to proofs ready.
|
|
240
|
+
this.deps.metrics.recordCheckpointProving(checkpointTimer.ms());
|
|
241
|
+
this.blockProofs.resolve(result.blockProofOutputs);
|
|
242
|
+
// Release the sub-tree orchestrator now that its output is captured. The block-proof outputs
|
|
243
|
+
// survive via the resolved promise; everything else the sub-tree held — per-tx AVM inputs, and
|
|
244
|
+
// the base/merge/parity proof trees — is dead once proving completes, yet the prover is retained
|
|
245
|
+
// for the whole proof-submission window. Dropping it here is what stops that retention from
|
|
246
|
+
// accumulating across every proven checkpoint. Post-completion consumers (the top-tree job, a
|
|
247
|
+
// rebuilt EpochSession, failure upload) read only `whenBlockProofsReady()` and this prover's own
|
|
248
|
+
// fields (`checkpoint`, `txs`, headers, sibling paths), never the sub-tree.
|
|
249
|
+
this.teardownPromise = this.teardownSubTree();
|
|
250
|
+
}, (err)=>this.failBlockProofs(err instanceof Error ? err : new Error(String(err))));
|
|
251
|
+
if (signal.aborted) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
const allTxs = this.checkpoint.blocks.flatMap((block)=>block.body.txEffects.map((txEffect)=>txs.get(txEffect.txHash.toString())));
|
|
255
|
+
const publicTxs = allTxs.filter((tx)=>tx?.data.forPublic);
|
|
256
|
+
if (publicTxs.length > 0) {
|
|
257
|
+
await this.subTree.startChonkVerifierCircuits(publicTxs);
|
|
258
|
+
if (signal.aborted) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
for(let blockIndex = 0; blockIndex < this.checkpoint.blocks.length; blockIndex++){
|
|
263
|
+
const blockTimer = new Timer();
|
|
264
|
+
const block = this.checkpoint.blocks[blockIndex];
|
|
265
|
+
const globalVariables = block.header.globalVariables;
|
|
266
|
+
const blockTxs = this.getTxsForBlock(block, txs);
|
|
267
|
+
await this.subTree.startNewBlock(block.number, globalVariables.timestamp, blockTxs.length);
|
|
268
|
+
if (signal.aborted) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
const db = await this.createFork(BlockNumber(block.number - 1), blockIndex === 0 ? this.l1ToL2Messages : undefined);
|
|
272
|
+
try {
|
|
273
|
+
if (signal.aborted) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const config = PublicSimulatorConfig.from({
|
|
277
|
+
proverId: this.deps.proverId.toField(),
|
|
278
|
+
skipFeeEnforcement: false,
|
|
279
|
+
collectDebugLogs: false,
|
|
280
|
+
collectHints: true,
|
|
281
|
+
collectPublicInputs: true,
|
|
282
|
+
collectStatistics: false
|
|
283
|
+
});
|
|
284
|
+
const publicProcessor = this.deps.publicProcessorFactory.create(db, globalVariables, config);
|
|
285
|
+
const processed = await this.processTxs(publicProcessor, blockTxs);
|
|
286
|
+
if (signal.aborted) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
await this.subTree.addTxs(processed);
|
|
290
|
+
} finally{
|
|
291
|
+
await db.close();
|
|
292
|
+
}
|
|
293
|
+
if (signal.aborted) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
await this.subTree.setBlockCompleted(block.number, block.header);
|
|
297
|
+
this.deps.metrics.recordBlockProcessing(blockTimer.ms());
|
|
298
|
+
if (signal.aborted) {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
this.completed = true;
|
|
303
|
+
const numTxs = this.checkpoint.blocks.reduce((acc, block)=>acc + block.body.txEffects.length, 0);
|
|
304
|
+
this.deps.metrics.recordCheckpointProcessing(checkpointTimer.ms(), this.checkpoint.blocks.length, numTxs);
|
|
305
|
+
this.deps.log.info(`Finished enqueueing block-level proving for checkpoint ${this.checkpoint.number} in ${checkpointTimer.ms()}ms`, {
|
|
306
|
+
checkpointNumber: this.checkpoint.number,
|
|
307
|
+
blockCount: this.checkpoint.blocks.length,
|
|
308
|
+
durationMs: checkpointTimer.ms()
|
|
309
|
+
});
|
|
310
|
+
} finally{
|
|
311
|
+
if (!this.completed) {
|
|
312
|
+
if (subTreeStarted) {
|
|
313
|
+
await this.teardownSubTree();
|
|
314
|
+
}
|
|
315
|
+
this.failBlockProofs(new Error(`Checkpoint ${this.id} did not complete block processing`));
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Mark cancelled. Idempotent. Aborts in-flight work, rejects the block-proof promise,
|
|
321
|
+
* and kicks off a background teardown of the sub-tree. The teardown promise is exposed
|
|
322
|
+
* via `whenDone()`.
|
|
323
|
+
*
|
|
324
|
+
* `routine` distinguishes a post-finalize teardown (sub-tree already proven, fires
|
|
325
|
+
* once at prover exit) from a real abort (reorg, prune, deadline). Behaviour is
|
|
326
|
+
* identical either way; the flag only adjusts log verbosity.
|
|
327
|
+
*/ cancel({ routine = false } = {}) {
|
|
328
|
+
if (this.cancelled) {
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
this.cancelled = true;
|
|
332
|
+
// A teardown of a completed prover is routine regardless of the caller's flag —
|
|
333
|
+
// we logged the work as done already, so don't relabel it as a mid-flight cancel.
|
|
334
|
+
if (routine || this.completed) {
|
|
335
|
+
this.deps.log.verbose(`Tearing down CheckpointProver ${this.id}`, {
|
|
336
|
+
checkpointNumber: this.checkpoint.number,
|
|
337
|
+
wasCompleted: this.completed
|
|
338
|
+
});
|
|
339
|
+
} else {
|
|
340
|
+
this.deps.log.info(`Cancelling in-flight CheckpointProver ${this.id}`, {
|
|
341
|
+
checkpointNumber: this.checkpoint.number,
|
|
342
|
+
wasCompleted: this.completed
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
this.abortController.abort();
|
|
346
|
+
this.blockProofs.reject(new Error(`Checkpoint ${this.id} cancelled`));
|
|
347
|
+
this.cancelPromise = this.runCancel().catch(()=>{});
|
|
348
|
+
}
|
|
349
|
+
async runCancel() {
|
|
350
|
+
if (this.subTree) {
|
|
351
|
+
try {
|
|
352
|
+
this.subTree.cancel();
|
|
353
|
+
} catch (err) {
|
|
354
|
+
this.deps.log.error('Error cancelling sub-tree', err);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
await this.runPromise.catch(()=>{});
|
|
358
|
+
if (this.subTree) {
|
|
359
|
+
await this.teardownSubTree();
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
async teardownSubTree() {
|
|
363
|
+
const { subTree } = this;
|
|
364
|
+
this.subTree = undefined;
|
|
365
|
+
if (subTree) {
|
|
366
|
+
this.deps.log.debug(`Tearing down sub-tree for checkpoint ${this.checkpoint.number}`, {
|
|
367
|
+
checkpointNumber: this.checkpoint.number
|
|
368
|
+
});
|
|
369
|
+
try {
|
|
370
|
+
await subTree.stop();
|
|
371
|
+
} catch (err) {
|
|
372
|
+
this.deps.log.error('Error stopping sub-tree', err);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
getTxsForBlock(block, txs) {
|
|
377
|
+
return block.body.txEffects.map((txEffect)=>txs.get(txEffect.txHash.toString()));
|
|
378
|
+
}
|
|
379
|
+
async processTxs(publicProcessor, txs) {
|
|
380
|
+
// Pass the abort signal so a prune-driven cancel stops the current block's public execution
|
|
381
|
+
// immediately, rather than running it to completion before the next `signal.aborted` check.
|
|
382
|
+
// On abort `process` returns a partial result, the length check below throws, and
|
|
383
|
+
// `gatherAndExecute` swallows it via its `cancelled` guard.
|
|
384
|
+
const [processedTxs, failedTxs] = await publicProcessor.process(txs, {
|
|
385
|
+
deadline: this.deps.deadline,
|
|
386
|
+
signal: this.abortController.signal
|
|
387
|
+
});
|
|
388
|
+
if (failedTxs.length) {
|
|
389
|
+
const failedTxHashes = await Promise.all(failedTxs.map(({ tx })=>tx.getTxHash()));
|
|
390
|
+
throw new Error(`Txs failed processing: ${failedTxs.map(({ error }, index)=>`${failedTxHashes[index]} (${error})`).join(', ')}`);
|
|
391
|
+
}
|
|
392
|
+
if (processedTxs.length !== txs.length) {
|
|
393
|
+
throw new Error(`Failed to process all txs: processed ${processedTxs.length} out of ${txs.length}`);
|
|
394
|
+
}
|
|
395
|
+
return processedTxs;
|
|
396
|
+
}
|
|
397
|
+
async createFork(blockNumber, l1ToL2Messages) {
|
|
398
|
+
const db = await this.deps.dbProvider.fork(blockNumber);
|
|
399
|
+
if (l1ToL2Messages !== undefined) {
|
|
400
|
+
const l1ToL2MessagesPadded = padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 'Too many L1 to L2 messages');
|
|
401
|
+
await db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
|
|
402
|
+
}
|
|
403
|
+
return db;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { BlockNumber, type EpochNumber, type SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
|
+
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
|
+
import { type LoggerBindings } from '@aztec/foundation/log';
|
|
4
|
+
import { type DateProvider } from '@aztec/foundation/timer';
|
|
5
|
+
import type { EpochProverFactory } from '@aztec/prover-client';
|
|
6
|
+
import { type EpochProvingJobState } from '@aztec/stdlib/interfaces/server';
|
|
7
|
+
import { type Traceable, type Tracer } from '@aztec/telemetry-client';
|
|
8
|
+
import type { ProverNodeJobMetrics } from '../metrics.js';
|
|
9
|
+
import type { ProofPublishingService } from '../proof-publishing-service.js';
|
|
10
|
+
import { CheckpointProver } from './checkpoint-prover.js';
|
|
11
|
+
import { type TopTreeProof } from './top-tree-job.js';
|
|
12
|
+
export type { EpochProvingJobState };
|
|
13
|
+
/** Full vs partial — the only behavioural difference is at the L1 submission step. */
|
|
14
|
+
export type SessionKind = 'full' | 'partial';
|
|
15
|
+
/**
|
|
16
|
+
* Identifies what a session proves: a contiguous slot range within an epoch. The
|
|
17
|
+
* concrete prover set the session holds is the *implementation* of the spec — frozen
|
|
18
|
+
* at construction time, derived from the canonical content for `[fromSlot, toSlot]`.
|
|
19
|
+
*
|
|
20
|
+
* Reconciliation in `ProverNode` is uniform across kinds: whenever the canonical
|
|
21
|
+
* content for the slot range changes, the session is cancelled and replaced with a
|
|
22
|
+
* fresh session that **preserves the slot range** but adopts the new checkpoints.
|
|
23
|
+
*
|
|
24
|
+
* Kind affects only the publishing decision (see `EpochSession`).
|
|
25
|
+
*/
|
|
26
|
+
export interface SessionSpec {
|
|
27
|
+
kind: SessionKind;
|
|
28
|
+
epochNumber: EpochNumber;
|
|
29
|
+
fromSlot: SlotNumber;
|
|
30
|
+
toSlot: SlotNumber;
|
|
31
|
+
}
|
|
32
|
+
/** Stable string key for use in maps. */
|
|
33
|
+
export declare function specKey(spec: SessionSpec): string;
|
|
34
|
+
/** Hooks tests use to interpose around the top-tree prove without monkey-patching. */
|
|
35
|
+
export type EpochSessionHooks = {
|
|
36
|
+
beforeTopTreeProve?: () => Promise<void> | void;
|
|
37
|
+
afterTopTreeProve?: () => Promise<void> | void;
|
|
38
|
+
topTreeProveOverride?: (defaultProve: () => Promise<TopTreeProof>) => Promise<TopTreeProof>;
|
|
39
|
+
};
|
|
40
|
+
export type EpochSessionOptions = {
|
|
41
|
+
/**
|
|
42
|
+
* If set, the session sleeps this many ms after `start()` (before the TopTreeJob is
|
|
43
|
+
* constructed). Lets late-arriving events (e.g. a prune) be processed before
|
|
44
|
+
* top-tree proving begins.
|
|
45
|
+
*/
|
|
46
|
+
finalizationDelayMs?: number;
|
|
47
|
+
};
|
|
48
|
+
/** Dependencies an `EpochSession` needs at construction. */
|
|
49
|
+
export type EpochSessionDeps = {
|
|
50
|
+
proverFactory: EpochProverFactory;
|
|
51
|
+
proverId: EthAddress;
|
|
52
|
+
publishingService: Pick<ProofPublishingService, 'submit' | 'withdraw'>;
|
|
53
|
+
metrics: ProverNodeJobMetrics;
|
|
54
|
+
dateProvider: DateProvider;
|
|
55
|
+
/** Optional proving deadline. The session enters `timed-out` if exceeded. */
|
|
56
|
+
deadline: Date | undefined;
|
|
57
|
+
config: EpochSessionOptions;
|
|
58
|
+
bindings?: LoggerBindings;
|
|
59
|
+
hooks?: EpochSessionHooks;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* One attempt at proving and publishing a contiguous slot range. The `SessionSpec` and
|
|
63
|
+
* the prover set are both frozen at construction time; the session does not adapt to
|
|
64
|
+
* reorgs or extensions of canonical content. Instead, `SessionManager` owns the
|
|
65
|
+
* reconciliation loop and replaces invalidated sessions wholesale (cancel + construct
|
|
66
|
+
* a fresh session with the new prover set).
|
|
67
|
+
*
|
|
68
|
+
* Each session does three things in sequence:
|
|
69
|
+
*
|
|
70
|
+
* 1. Run a `TopTreeJob` over its frozen prover subset to produce the epoch proof.
|
|
71
|
+
* 2. Hand the proof to the shared `ProofPublishingService` as a `PublishCandidate`.
|
|
72
|
+
* 3. Translate the service's outcome into a terminal session state.
|
|
73
|
+
*
|
|
74
|
+
* Everything to do with submission — predecessor gating, same-epoch dedup, deadline
|
|
75
|
+
* enforcement, and the L1 transaction itself — is the publishing service's concern.
|
|
76
|
+
* The session is just the producer of one candidate and the observer of its outcome.
|
|
77
|
+
*
|
|
78
|
+
* Lifecycle (happy path):
|
|
79
|
+
*
|
|
80
|
+
* initialized → awaiting-checkpoints → awaiting-root → publishing-proof → completed
|
|
81
|
+
*
|
|
82
|
+
* Terminal states map the publishing outcome: `published` → `completed`, `superseded` →
|
|
83
|
+
* `superseded`, `expired` → `timed-out`, `withdrawn` → `cancelled`. A fault ends the attempt in one
|
|
84
|
+
* of two terminal states depending on its cause: `stopped` if a checkpoint prover under it failed
|
|
85
|
+
* (possibly a prune — the reconciler will rebuild over a fresh prover on re-add), or `failed` if the
|
|
86
|
+
* session's own top-tree/submit work failed while every prover was healthy (a genuine, non-prune
|
|
87
|
+
* failure the reconciler retains and uploads — see `hasFailed()`).
|
|
88
|
+
* Additionally, the session-level deadline fires `cancel('deadline')` and transitions
|
|
89
|
+
* to `timed-out` for the pre-submit window (top-tree proving) — the publishing service
|
|
90
|
+
* handles the post-submit window via the candidate's `deadline`.
|
|
91
|
+
*
|
|
92
|
+
* `cancel()` is idempotent. It marks the session terminal, calls
|
|
93
|
+
* `publishingService.withdraw(uuid)` to drop any queued candidate (an in-flight publish
|
|
94
|
+
* runs to natural completion; the session has already settled), and tears down the
|
|
95
|
+
* top-tree job if proving is still in progress.
|
|
96
|
+
*/
|
|
97
|
+
export declare class EpochSession implements Traceable {
|
|
98
|
+
private readonly spec;
|
|
99
|
+
private readonly deps;
|
|
100
|
+
readonly tracer: Tracer;
|
|
101
|
+
private readonly uuid;
|
|
102
|
+
private readonly log;
|
|
103
|
+
private state;
|
|
104
|
+
private deadlineTimeoutHandler;
|
|
105
|
+
private topTreeJob;
|
|
106
|
+
/** Cancelled top-tree jobs whose teardown is still in flight. Awaited at session stop. */
|
|
107
|
+
private readonly pendingTopTreeCleanups;
|
|
108
|
+
private readonly completionPromise;
|
|
109
|
+
private resolveCompletion;
|
|
110
|
+
/** Stable reference; never mutated after construction. */
|
|
111
|
+
private readonly checkpoints;
|
|
112
|
+
constructor(spec: SessionSpec, checkpoints: readonly CheckpointProver[], deps: EpochSessionDeps);
|
|
113
|
+
getId(): string;
|
|
114
|
+
getSpec(): SessionSpec;
|
|
115
|
+
getState(): EpochProvingJobState;
|
|
116
|
+
getEpochNumber(): EpochNumber;
|
|
117
|
+
getKind(): SessionKind;
|
|
118
|
+
getDeadline(): Date | undefined;
|
|
119
|
+
getCheckpoints(): readonly CheckpointProver[];
|
|
120
|
+
/** Resolves when the session reaches a terminal state. */
|
|
121
|
+
whenDone(): Promise<EpochProvingJobState>;
|
|
122
|
+
/** True if the session is in a terminal state. */
|
|
123
|
+
isTerminal(): boolean;
|
|
124
|
+
/**
|
|
125
|
+
* True if the session ended in its own genuine failure — top-tree proving or L1 submission failed
|
|
126
|
+
* while every checkpoint prover succeeded. Because healthy provers rule out a prune-induced fault,
|
|
127
|
+
* this is a race-free "the epoch could not be proven" signal: the reconciler retains such a (full)
|
|
128
|
+
* session rather than re-proving it, and uploads a post-mortem. A `stopped` session (a checkpoint
|
|
129
|
+
* prover failed under it) is NOT a session failure in this sense.
|
|
130
|
+
*/
|
|
131
|
+
hasFailed(): boolean;
|
|
132
|
+
/** First block this session proves. */
|
|
133
|
+
getStartBlockNumber(): BlockNumber;
|
|
134
|
+
/** Last block this session proves. */
|
|
135
|
+
getEndBlockNumber(): BlockNumber;
|
|
136
|
+
/**
|
|
137
|
+
* Kicks off proving + submission. Fires and forgets — callers should await `whenDone()`.
|
|
138
|
+
* Returns a promise that resolves to the final state for callers that want to wait inline.
|
|
139
|
+
*/
|
|
140
|
+
start(): Promise<EpochProvingJobState>;
|
|
141
|
+
/**
|
|
142
|
+
* Cancels the session. Idempotent. Withdraws any submitted candidate from the
|
|
143
|
+
* publishing service so the in-flight publisher (if any) is interrupted.
|
|
144
|
+
*/
|
|
145
|
+
cancel(reason?: string, { abortJobs }?: {
|
|
146
|
+
abortJobs?: boolean;
|
|
147
|
+
}): Promise<void>;
|
|
148
|
+
private run;
|
|
149
|
+
private submitProof;
|
|
150
|
+
private teardownTopTreeIfNeeded;
|
|
151
|
+
private scheduleDeadlineStop;
|
|
152
|
+
/**
|
|
153
|
+
* Returns a promise that resolves once cancellation has propagated and the state has
|
|
154
|
+
* been flipped from 'cancelled' to 'timed-out'. Protected so unit tests can drive the
|
|
155
|
+
* deadline path without waiting on the real `setTimeout` to fire.
|
|
156
|
+
*/
|
|
157
|
+
protected handleDeadline(): Promise<void>;
|
|
158
|
+
private toTopTreeHooks;
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXBvY2gtc2Vzc2lvbi5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2pvYi9lcG9jaC1zZXNzaW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxXQUFXLEVBQXlCLEtBQUssV0FBVyxFQUFFLEtBQUssVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDeEgsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDaEUsT0FBTyxFQUFlLEtBQUssY0FBYyxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBRXZGLE9BQU8sRUFBRSxLQUFLLFlBQVksRUFBUyxNQUFNLHlCQUF5QixDQUFDO0FBQ25FLE9BQU8sS0FBSyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFL0QsT0FBTyxFQUFFLEtBQUssb0JBQW9CLEVBQWdDLE1BQU0saUNBQWlDLENBQUM7QUFDMUcsT0FBTyxFQUFjLEtBQUssU0FBUyxFQUFFLEtBQUssTUFBTSxFQUFhLE1BQU0seUJBQXlCLENBQUM7QUFJN0YsT0FBTyxLQUFLLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDMUQsT0FBTyxLQUFLLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUM3RSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUMxRCxPQUFPLEVBQW9DLEtBQUssWUFBWSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFeEYsWUFBWSxFQUFFLG9CQUFvQixFQUFFLENBQUM7QUFFckMsd0ZBQXNGO0FBQ3RGLE1BQU0sTUFBTSxXQUFXLEdBQUcsTUFBTSxHQUFHLFNBQVMsQ0FBQztBQUU3Qzs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxXQUFXLFdBQVc7SUFDMUIsSUFBSSxFQUFFLFdBQVcsQ0FBQztJQUNsQixXQUFXLEVBQUUsV0FBVyxDQUFDO0lBQ3pCLFFBQVEsRUFBRSxV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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"epoch-session.d.ts","sourceRoot":"","sources":["../../src/job/epoch-session.ts"],"names":[],"mappings":"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"}
|