@aztec/prover-client 1.0.0-nightly.20250608 → 1.0.0-nightly.20250610
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/block-factory/light.d.ts.map +1 -1
- package/dest/block-factory/light.js +2 -1
- package/dest/mocks/test_context.d.ts +1 -0
- package/dest/mocks/test_context.d.ts.map +1 -1
- package/dest/mocks/test_context.js +3 -0
- package/dest/orchestrator/block-building-helpers.d.ts +7 -7
- package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
- package/dest/orchestrator/block-building-helpers.js +36 -24
- package/dest/orchestrator/block-proving-state.d.ts +10 -2
- package/dest/orchestrator/block-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/block-proving-state.js +55 -18
- package/dest/orchestrator/epoch-proving-state.d.ts +9 -3
- package/dest/orchestrator/epoch-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/epoch-proving-state.js +33 -8
- package/dest/orchestrator/orchestrator.d.ts +3 -1
- package/dest/orchestrator/orchestrator.d.ts.map +1 -1
- package/dest/orchestrator/orchestrator.js +30 -10
- package/dest/prover-client/prover-client.d.ts +1 -1
- package/dest/prover-client/prover-client.d.ts.map +1 -1
- package/dest/prover-client/prover-client.js +2 -0
- package/dest/prover-client/server-epoch-prover.d.ts +3 -1
- package/dest/prover-client/server-epoch-prover.d.ts.map +1 -1
- package/dest/prover-client/server-epoch-prover.js +2 -2
- package/package.json +15 -15
- package/src/block-factory/light.ts +2 -1
- package/src/mocks/test_context.ts +4 -0
- package/src/orchestrator/block-building-helpers.ts +42 -27
- package/src/orchestrator/block-proving-state.ts +69 -14
- package/src/orchestrator/epoch-proving-state.ts +34 -4
- package/src/orchestrator/orchestrator.ts +62 -11
- package/src/prover-client/prover-client.ts +11 -9
- package/src/prover-client/server-epoch-prover.ts +9 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SpongeBlob } from '@aztec/blob-lib';
|
|
1
|
+
import { BatchedBlobAccumulator, SpongeBlob } from '@aztec/blob-lib';
|
|
2
2
|
import {
|
|
3
3
|
type ARCHIVE_HEIGHT,
|
|
4
4
|
BLOBS_PER_BLOCK,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
type RECURSIVE_PROOF_LENGTH,
|
|
10
10
|
} from '@aztec/constants';
|
|
11
11
|
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
12
|
-
import { Fr } from '@aztec/foundation/fields';
|
|
12
|
+
import { BLS12Point, Fr } from '@aztec/foundation/fields';
|
|
13
13
|
import type { Tuple } from '@aztec/foundation/serialize';
|
|
14
14
|
import { type TreeNodeLocation, UnbalancedTreeStore } from '@aztec/foundation/trees';
|
|
15
15
|
import { getVKIndex, getVKSiblingPath, getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
@@ -19,11 +19,11 @@ import type { PublicInputsAndRecursiveProof } from '@aztec/stdlib/interfaces/ser
|
|
|
19
19
|
import { type ParityPublicInputs, RootParityInput, RootParityInputs } from '@aztec/stdlib/parity';
|
|
20
20
|
import {
|
|
21
21
|
type BaseOrMergeRollupPublicInputs,
|
|
22
|
+
BlockConstantData,
|
|
22
23
|
type BlockRootOrBlockMergePublicInputs,
|
|
23
24
|
BlockRootRollupBlobData,
|
|
24
25
|
BlockRootRollupData,
|
|
25
26
|
BlockRootRollupInputs,
|
|
26
|
-
ConstantRollupData,
|
|
27
27
|
EmptyBlockRootRollupInputs,
|
|
28
28
|
MergeRollupInputs,
|
|
29
29
|
PreviousRollupData,
|
|
@@ -34,7 +34,7 @@ import type { AppendOnlyTreeSnapshot, MerkleTreeId } from '@aztec/stdlib/trees';
|
|
|
34
34
|
import { type BlockHeader, type GlobalVariables, StateReference } from '@aztec/stdlib/tx';
|
|
35
35
|
import { VkData } from '@aztec/stdlib/vks';
|
|
36
36
|
|
|
37
|
-
import { buildBlobHints, buildHeaderFromCircuitOutputs } from './block-building-helpers.js';
|
|
37
|
+
import { accumulateBlobs, buildBlobHints, buildHeaderFromCircuitOutputs } from './block-building-helpers.js';
|
|
38
38
|
import type { EpochProvingState } from './epoch-proving-state.js';
|
|
39
39
|
import type { TxProvingState } from './tx-proving-state.js';
|
|
40
40
|
|
|
@@ -56,6 +56,9 @@ export class BlockProvingState {
|
|
|
56
56
|
public blockRootRollupStarted: boolean = false;
|
|
57
57
|
public block: L2Block | undefined;
|
|
58
58
|
public spongeBlobState: SpongeBlob | undefined;
|
|
59
|
+
public startBlobAccumulator: BatchedBlobAccumulator | undefined;
|
|
60
|
+
public endBlobAccumulator: BatchedBlobAccumulator | undefined;
|
|
61
|
+
public blobsHash: Buffer | undefined;
|
|
59
62
|
public totalNumTxs: number;
|
|
60
63
|
private txs: TxProvingState[] = [];
|
|
61
64
|
public error: string | undefined;
|
|
@@ -64,6 +67,7 @@ export class BlockProvingState {
|
|
|
64
67
|
public readonly index: number,
|
|
65
68
|
public readonly globalVariables: GlobalVariables,
|
|
66
69
|
public readonly newL1ToL2Messages: Fr[],
|
|
70
|
+
public readonly l1ToL2MessageTreeSnapshot: AppendOnlyTreeSnapshot,
|
|
67
71
|
private readonly l1ToL2MessageSubtreeSiblingPath: Tuple<Fr, typeof L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH>,
|
|
68
72
|
private readonly l1ToL2MessageTreeSnapshotAfterInsertion: AppendOnlyTreeSnapshot,
|
|
69
73
|
private readonly lastArchiveSnapshot: AppendOnlyTreeSnapshot,
|
|
@@ -74,6 +78,9 @@ export class BlockProvingState {
|
|
|
74
78
|
) {
|
|
75
79
|
this.baseParityProvingOutputs = Array.from({ length: NUM_BASE_PARITY_PER_ROOT_PARITY }).map(_ => undefined);
|
|
76
80
|
this.totalNumTxs = 0;
|
|
81
|
+
if (this.blockNumber == parentEpoch.firstBlockNumber) {
|
|
82
|
+
this.startBlobAccumulator = BatchedBlobAccumulator.newWithChallenges(parentEpoch.finalBlobBatchingChallenges);
|
|
83
|
+
}
|
|
77
84
|
}
|
|
78
85
|
|
|
79
86
|
public get blockNumber() {
|
|
@@ -97,7 +104,6 @@ export class BlockProvingState {
|
|
|
97
104
|
if (!this.spongeBlobState) {
|
|
98
105
|
throw new Error(`Invalid block proving state, call startNewBlock before adding transactions.`);
|
|
99
106
|
}
|
|
100
|
-
|
|
101
107
|
const txIndex = this.txs.length;
|
|
102
108
|
this.txs[txIndex] = tx;
|
|
103
109
|
return txIndex;
|
|
@@ -146,6 +152,30 @@ export class BlockProvingState {
|
|
|
146
152
|
this.blockRootProvingOutput = provingOutput;
|
|
147
153
|
}
|
|
148
154
|
|
|
155
|
+
public setBlock(block: L2Block) {
|
|
156
|
+
this.block = block;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
public setStartBlobAccumulator(accumulator: BatchedBlobAccumulator) {
|
|
160
|
+
this.startBlobAccumulator = accumulator;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
public setEndBlobAccumulator(accumulator: BatchedBlobAccumulator) {
|
|
164
|
+
this.endBlobAccumulator = accumulator;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
public async accumulateBlobs() {
|
|
168
|
+
if (!this.block || !this.startBlobAccumulator) {
|
|
169
|
+
// We only want to accumulate once we have all txs, so we wait until the block is set.
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const endBlobAccumulator = await accumulateBlobs(
|
|
173
|
+
this.allTxs.map(t => t.processedTx),
|
|
174
|
+
this.startBlobAccumulator,
|
|
175
|
+
);
|
|
176
|
+
this.setEndBlobAccumulator(endBlobAccumulator);
|
|
177
|
+
}
|
|
178
|
+
|
|
149
179
|
// Returns the complete set of transaction proving state objects
|
|
150
180
|
public get allTxs() {
|
|
151
181
|
return this.txs;
|
|
@@ -183,8 +213,9 @@ export class BlockProvingState {
|
|
|
183
213
|
const data = this.#getBlockRootRollupData(proverId);
|
|
184
214
|
|
|
185
215
|
if (this.totalNumTxs === 0) {
|
|
186
|
-
const constants =
|
|
216
|
+
const constants = BlockConstantData.from({
|
|
187
217
|
lastArchive: this.lastArchiveSnapshot,
|
|
218
|
+
lastL1ToL2: this.l1ToL2MessageTreeSnapshot,
|
|
188
219
|
globalVariables: this.globalVariables,
|
|
189
220
|
vkTreeRoot: getVKTreeRoot(),
|
|
190
221
|
protocolContractTreeRoot,
|
|
@@ -202,6 +233,7 @@ export class BlockProvingState {
|
|
|
202
233
|
|
|
203
234
|
const previousRollupData = await Promise.all(nonEmptyProofs.map(p => this.#getPreviousRollupData(p!)));
|
|
204
235
|
const blobData = await this.#getBlockRootRollupBlobData();
|
|
236
|
+
this.blobsHash = blobData.blobsHash.toBuffer();
|
|
205
237
|
|
|
206
238
|
if (previousRollupData.length === 1) {
|
|
207
239
|
return {
|
|
@@ -225,21 +257,29 @@ export class BlockProvingState {
|
|
|
225
257
|
throw new Error('Root parity is not ready.');
|
|
226
258
|
}
|
|
227
259
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
260
|
+
if (!this.blockRootProvingOutput || !this.endBlobAccumulator) {
|
|
261
|
+
throw new Error('Block root not ready for padding.');
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Use the new block header, archive and l1toL2 of the current block as the previous header, archive and l1toL2 of the next padding block.
|
|
265
|
+
const previousBlockHeader = await this.buildHeaderFromProvingOutputs();
|
|
266
|
+
const lastArchive = this.blockRootProvingOutput!.inputs.newArchive;
|
|
267
|
+
const lastL1ToL2 = this.l1ToL2MessageTreeSnapshotAfterInsertion;
|
|
231
268
|
|
|
232
269
|
const data = BlockRootRollupData.from({
|
|
233
270
|
l1ToL2Roots: this.#getRootParityData(this.rootParityProvingOutput!),
|
|
234
271
|
l1ToL2MessageSubtreeSiblingPath: this.l1ToL2MessageSubtreeSiblingPath,
|
|
235
272
|
previousArchiveSiblingPath: this.lastArchiveSiblingPath,
|
|
236
273
|
newArchiveSiblingPath: this.newArchiveSiblingPath,
|
|
237
|
-
previousBlockHeader
|
|
274
|
+
previousBlockHeader,
|
|
275
|
+
startBlobAccumulator: this.endBlobAccumulator.toBlobAccumulatorPublicInputs(),
|
|
276
|
+
finalBlobChallenges: this.endBlobAccumulator.finalBlobChallenges,
|
|
238
277
|
proverId,
|
|
239
278
|
});
|
|
240
279
|
|
|
241
|
-
const constants =
|
|
242
|
-
lastArchive
|
|
280
|
+
const constants = BlockConstantData.from({
|
|
281
|
+
lastArchive,
|
|
282
|
+
lastL1ToL2,
|
|
243
283
|
globalVariables: this.globalVariables,
|
|
244
284
|
vkTreeRoot: getVKTreeRoot(),
|
|
245
285
|
protocolContractTreeRoot,
|
|
@@ -285,10 +325,18 @@ export class BlockProvingState {
|
|
|
285
325
|
}
|
|
286
326
|
const endState = new StateReference(this.l1ToL2MessageTreeSnapshotAfterInsertion, endPartialState);
|
|
287
327
|
|
|
328
|
+
// TODO(MW): cleanup
|
|
329
|
+
if (!this.blobsHash) {
|
|
330
|
+
this.blobsHash = (
|
|
331
|
+
await buildBlobHints(this.txs.map(txProvingState => txProvingState.processedTx.txEffect))
|
|
332
|
+
).blobsHash.toBuffer();
|
|
333
|
+
}
|
|
334
|
+
|
|
288
335
|
return buildHeaderFromCircuitOutputs(
|
|
289
336
|
previousRollupData.map(d => d.baseOrMergeRollupPublicInputs),
|
|
290
337
|
this.rootParityProvingOutput!.inputs,
|
|
291
338
|
this.blockRootProvingOutput!.inputs,
|
|
339
|
+
this.blobsHash,
|
|
292
340
|
endState,
|
|
293
341
|
);
|
|
294
342
|
}
|
|
@@ -300,7 +348,12 @@ export class BlockProvingState {
|
|
|
300
348
|
// Returns true if we have sufficient inputs to execute the block root rollup
|
|
301
349
|
public isReadyForBlockRootRollup() {
|
|
302
350
|
const childProofs = this.#getChildProofsForBlockRoot();
|
|
303
|
-
return
|
|
351
|
+
return (
|
|
352
|
+
this.block !== undefined &&
|
|
353
|
+
this.rootParityProvingOutput !== undefined &&
|
|
354
|
+
this.endBlobAccumulator !== undefined &&
|
|
355
|
+
childProofs.every(p => !!p)
|
|
356
|
+
);
|
|
304
357
|
}
|
|
305
358
|
|
|
306
359
|
// Returns true if we have sufficient root parity inputs to execute the root parity circuit
|
|
@@ -329,6 +382,8 @@ export class BlockProvingState {
|
|
|
329
382
|
previousArchiveSiblingPath: this.lastArchiveSiblingPath,
|
|
330
383
|
newArchiveSiblingPath: this.newArchiveSiblingPath,
|
|
331
384
|
previousBlockHeader: this.previousBlockHeader,
|
|
385
|
+
startBlobAccumulator: this.startBlobAccumulator!.toBlobAccumulatorPublicInputs(),
|
|
386
|
+
finalBlobChallenges: this.startBlobAccumulator!.finalBlobChallenges,
|
|
332
387
|
proverId,
|
|
333
388
|
});
|
|
334
389
|
}
|
|
@@ -338,7 +393,7 @@ export class BlockProvingState {
|
|
|
338
393
|
const { blobFields, blobCommitments, blobsHash } = await buildBlobHints(txEffects);
|
|
339
394
|
return BlockRootRollupBlobData.from({
|
|
340
395
|
blobFields: padArrayEnd(blobFields, Fr.ZERO, FIELDS_PER_BLOB * BLOBS_PER_BLOCK),
|
|
341
|
-
blobCommitments: padArrayEnd(blobCommitments,
|
|
396
|
+
blobCommitments: padArrayEnd(blobCommitments, BLS12Point.ZERO, BLOBS_PER_BLOCK),
|
|
342
397
|
blobsHash,
|
|
343
398
|
});
|
|
344
399
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { BatchedBlob, type FinalBlobBatchingChallenges } from '@aztec/blob-lib';
|
|
1
2
|
import type {
|
|
2
3
|
ARCHIVE_HEIGHT,
|
|
3
4
|
L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH,
|
|
@@ -48,6 +49,7 @@ export class EpochProvingState {
|
|
|
48
49
|
| PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs, typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH>
|
|
49
50
|
| undefined;
|
|
50
51
|
private rootRollupProvingOutput: PublicInputsAndRecursiveProof<RootRollupPublicInputs> | undefined;
|
|
52
|
+
private finalBatchedBlob: BatchedBlob | undefined;
|
|
51
53
|
private provingStateLifecycle = PROVING_STATE_LIFECYCLE.PROVING_STATE_CREATED;
|
|
52
54
|
|
|
53
55
|
// Map from tx hash to tube proof promise. Used when kickstarting tube proofs before tx processing.
|
|
@@ -59,6 +61,7 @@ export class EpochProvingState {
|
|
|
59
61
|
public readonly epochNumber: number,
|
|
60
62
|
public readonly firstBlockNumber: number,
|
|
61
63
|
public readonly totalNumBlocks: number,
|
|
64
|
+
public readonly finalBlobBatchingChallenges: FinalBlobBatchingChallenges,
|
|
62
65
|
private completionCallback: (result: ProvingResult) => void,
|
|
63
66
|
private rejectionCallback: (reason: string) => void,
|
|
64
67
|
) {
|
|
@@ -70,6 +73,7 @@ export class EpochProvingState {
|
|
|
70
73
|
public startNewBlock(
|
|
71
74
|
globalVariables: GlobalVariables,
|
|
72
75
|
l1ToL2Messages: Fr[],
|
|
76
|
+
l1ToL2MessageTreeSnapshot: AppendOnlyTreeSnapshot,
|
|
73
77
|
l1ToL2MessageSubtreeSiblingPath: Tuple<Fr, typeof L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH>,
|
|
74
78
|
l1ToL2MessageTreeSnapshotAfterInsertion: AppendOnlyTreeSnapshot,
|
|
75
79
|
lastArchiveSnapshot: AppendOnlyTreeSnapshot,
|
|
@@ -82,6 +86,7 @@ export class EpochProvingState {
|
|
|
82
86
|
index,
|
|
83
87
|
globalVariables,
|
|
84
88
|
l1ToL2Messages,
|
|
89
|
+
l1ToL2MessageTreeSnapshot,
|
|
85
90
|
l1ToL2MessageSubtreeSiblingPath,
|
|
86
91
|
l1ToL2MessageTreeSnapshotAfterInsertion,
|
|
87
92
|
lastArchiveSnapshot,
|
|
@@ -143,6 +148,31 @@ export class EpochProvingState {
|
|
|
143
148
|
this.paddingBlockRootProvingOutput = proof;
|
|
144
149
|
}
|
|
145
150
|
|
|
151
|
+
public setFinalBatchedBlob(batchedBlob: BatchedBlob) {
|
|
152
|
+
this.finalBatchedBlob = batchedBlob;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
public async setBlobAccumulators(toBlock?: number) {
|
|
156
|
+
let previousAccumulator;
|
|
157
|
+
const end = toBlock ? toBlock - this.firstBlockNumber : this.blocks.length;
|
|
158
|
+
// Accumulate blobs as far as we can for this epoch.
|
|
159
|
+
for (let i = 0; i <= end; i++) {
|
|
160
|
+
const block = this.blocks[i];
|
|
161
|
+
if (!block || !block.block) {
|
|
162
|
+
// If the block proving state does not have a .block property, it may be awaiting more txs.
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
if (!block.startBlobAccumulator) {
|
|
166
|
+
// startBlobAccumulator always exists for firstBlockNumber, so the below should never assign an undefined:
|
|
167
|
+
block.setStartBlobAccumulator(previousAccumulator!);
|
|
168
|
+
}
|
|
169
|
+
if (block.startBlobAccumulator && !block.endBlobAccumulator) {
|
|
170
|
+
await block.accumulateBlobs();
|
|
171
|
+
}
|
|
172
|
+
previousAccumulator = block.endBlobAccumulator;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
146
176
|
public getParentLocation(location: TreeNodeLocation) {
|
|
147
177
|
return this.blockRootOrMergeProvingOutputs.getParentLocation(location);
|
|
148
178
|
}
|
|
@@ -156,7 +186,7 @@ export class EpochProvingState {
|
|
|
156
186
|
return new BlockMergeRollupInputs([this.#getPreviousRollupData(left), this.#getPreviousRollupData(right)]);
|
|
157
187
|
}
|
|
158
188
|
|
|
159
|
-
public getRootRollupInputs(
|
|
189
|
+
public getRootRollupInputs() {
|
|
160
190
|
const [left, right] = this.#getChildProofsForRoot();
|
|
161
191
|
if (!left || !right) {
|
|
162
192
|
throw new Error('At lease one child is not ready.');
|
|
@@ -164,7 +194,6 @@ export class EpochProvingState {
|
|
|
164
194
|
|
|
165
195
|
return RootRollupInputs.from({
|
|
166
196
|
previousRollupData: [this.#getPreviousRollupData(left), this.#getPreviousRollupData(right)],
|
|
167
|
-
proverId,
|
|
168
197
|
});
|
|
169
198
|
}
|
|
170
199
|
|
|
@@ -181,14 +210,15 @@ export class EpochProvingState {
|
|
|
181
210
|
return this.blocks.find(block => block?.blockNumber === blockNumber);
|
|
182
211
|
}
|
|
183
212
|
|
|
184
|
-
public getEpochProofResult(): { proof: Proof; publicInputs: RootRollupPublicInputs } {
|
|
185
|
-
if (!this.rootRollupProvingOutput) {
|
|
213
|
+
public getEpochProofResult(): { proof: Proof; publicInputs: RootRollupPublicInputs; batchedBlobInputs: BatchedBlob } {
|
|
214
|
+
if (!this.rootRollupProvingOutput || !this.finalBatchedBlob) {
|
|
186
215
|
throw new Error('Unable to get epoch proof result. Root rollup is not ready.');
|
|
187
216
|
}
|
|
188
217
|
|
|
189
218
|
return {
|
|
190
219
|
proof: this.rootRollupProvingOutput.proof.binaryProof,
|
|
191
220
|
publicInputs: this.rootRollupProvingOutput.inputs,
|
|
221
|
+
batchedBlobInputs: this.finalBatchedBlob,
|
|
192
222
|
};
|
|
193
223
|
}
|
|
194
224
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FinalBlobBatchingChallenges } from '@aztec/blob-lib';
|
|
1
2
|
import {
|
|
2
3
|
L1_TO_L2_MSG_SUBTREE_HEIGHT,
|
|
3
4
|
L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH,
|
|
@@ -107,14 +108,26 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
107
108
|
return Promise.resolve();
|
|
108
109
|
}
|
|
109
110
|
|
|
110
|
-
public startNewEpoch(
|
|
111
|
+
public startNewEpoch(
|
|
112
|
+
epochNumber: number,
|
|
113
|
+
firstBlockNumber: number,
|
|
114
|
+
totalNumBlocks: number,
|
|
115
|
+
finalBlobBatchingChallenges: FinalBlobBatchingChallenges,
|
|
116
|
+
) {
|
|
111
117
|
const { promise: _promise, resolve, reject } = promiseWithResolvers<ProvingResult>();
|
|
112
118
|
const promise = _promise.catch((reason): ProvingResult => ({ status: 'failure', reason }));
|
|
113
119
|
if (totalNumBlocks <= 0 || !Number.isInteger(totalNumBlocks)) {
|
|
114
120
|
throw new Error(`Invalid number of blocks for epoch (got ${totalNumBlocks})`);
|
|
115
121
|
}
|
|
116
122
|
logger.info(`Starting epoch ${epochNumber} with ${totalNumBlocks} blocks`);
|
|
117
|
-
this.provingState = new EpochProvingState(
|
|
123
|
+
this.provingState = new EpochProvingState(
|
|
124
|
+
epochNumber,
|
|
125
|
+
firstBlockNumber,
|
|
126
|
+
totalNumBlocks,
|
|
127
|
+
finalBlobBatchingChallenges,
|
|
128
|
+
resolve,
|
|
129
|
+
reject,
|
|
130
|
+
);
|
|
118
131
|
this.provingPromise = promise;
|
|
119
132
|
}
|
|
120
133
|
|
|
@@ -145,8 +158,12 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
145
158
|
this.dbs.set(globalVariables.blockNumber.toNumber(), db);
|
|
146
159
|
|
|
147
160
|
// we start the block by enqueueing all of the base parity circuits
|
|
148
|
-
const {
|
|
149
|
-
|
|
161
|
+
const {
|
|
162
|
+
l1ToL2MessageTreeSnapshot,
|
|
163
|
+
l1ToL2MessageSubtreeSiblingPath,
|
|
164
|
+
l1ToL2MessageTreeSnapshotAfterInsertion,
|
|
165
|
+
baseParityInputs,
|
|
166
|
+
} = await this.prepareBaseParityInputs(l1ToL2Messages, db);
|
|
150
167
|
|
|
151
168
|
// Get archive snapshot before this block lands
|
|
152
169
|
const lastArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
|
|
@@ -156,6 +173,7 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
156
173
|
const blockProvingState = this.provingState!.startNewBlock(
|
|
157
174
|
globalVariables,
|
|
158
175
|
l1ToL2Messages,
|
|
176
|
+
l1ToL2MessageTreeSnapshot,
|
|
159
177
|
l1ToL2MessageSubtreeSiblingPath,
|
|
160
178
|
l1ToL2MessageTreeSnapshotAfterInsertion,
|
|
161
179
|
lastArchive,
|
|
@@ -184,7 +202,7 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
184
202
|
logger.warn(`Provided no txs to orchestrator addTxs.`);
|
|
185
203
|
return;
|
|
186
204
|
}
|
|
187
|
-
const blockNumber = txs[0].
|
|
205
|
+
const blockNumber = txs[0].globalVariables.blockNumber.toNumber();
|
|
188
206
|
const provingState = this.provingState?.getBlockProvingStateByBlockNumber(blockNumber!);
|
|
189
207
|
if (!provingState) {
|
|
190
208
|
throw new Error(`Block proving state for ${blockNumber} not found`);
|
|
@@ -272,6 +290,9 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
272
290
|
logger.verbose(`Block ${blockNumber} completed. Assembling header.`);
|
|
273
291
|
await this.buildBlock(provingState, expectedHeader);
|
|
274
292
|
|
|
293
|
+
logger.debug(`Accumulating blobs for ${blockNumber}`);
|
|
294
|
+
await this.provingState?.setBlobAccumulators(blockNumber);
|
|
295
|
+
|
|
275
296
|
// If the proofs were faster than the block building, then we need to try the block root rollup again here
|
|
276
297
|
await this.checkAndEnqueueBlockRootRollup(provingState);
|
|
277
298
|
return provingState.block!;
|
|
@@ -319,7 +340,7 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
319
340
|
await this.verifyBuiltBlockAgainstSyncedState(l2Block, newArchive);
|
|
320
341
|
|
|
321
342
|
logger.verbose(`Orchestrator finalised block ${l2Block.number}`);
|
|
322
|
-
provingState.
|
|
343
|
+
provingState.setBlock(l2Block);
|
|
323
344
|
}
|
|
324
345
|
|
|
325
346
|
// Flagged as protected to disable in certain unit tests
|
|
@@ -358,6 +379,15 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
358
379
|
throw new Error(`Epoch proving failed: ${result.reason}`);
|
|
359
380
|
}
|
|
360
381
|
|
|
382
|
+
// TODO(MW): Move this? Requires async and don't want to force root methods to be async
|
|
383
|
+
// TODO(MW): EpochProvingState uses this.blocks.filter(b => !!b).length as total blocks, use this below:
|
|
384
|
+
const finalBlock = this.provingState.blocks[this.provingState.totalNumBlocks - 1];
|
|
385
|
+
if (!finalBlock || !finalBlock.endBlobAccumulator) {
|
|
386
|
+
throw new Error(`Epoch's final block not ready for finalise`);
|
|
387
|
+
}
|
|
388
|
+
const finalBatchedBlob = await finalBlock.endBlobAccumulator.finalize();
|
|
389
|
+
this.provingState.setFinalBatchedBlob(finalBatchedBlob);
|
|
390
|
+
|
|
361
391
|
const epochProofResult = this.provingState.getEpochProofResult();
|
|
362
392
|
|
|
363
393
|
pushTestData('epochProofResult', {
|
|
@@ -455,6 +485,8 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
455
485
|
BaseParityInputs.fromSlice(l1ToL2MessagesPadded, i, getVKTreeRoot()),
|
|
456
486
|
);
|
|
457
487
|
|
|
488
|
+
const l1ToL2MessageTreeSnapshot = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, db);
|
|
489
|
+
|
|
458
490
|
const l1ToL2MessageSubtreeSiblingPath = assertLength(
|
|
459
491
|
await getSubtreeSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, L1_TO_L2_MSG_SUBTREE_HEIGHT, db),
|
|
460
492
|
L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH,
|
|
@@ -465,6 +497,7 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
465
497
|
const l1ToL2MessageTreeSnapshotAfterInsertion = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, db);
|
|
466
498
|
|
|
467
499
|
return {
|
|
500
|
+
l1ToL2MessageTreeSnapshot,
|
|
468
501
|
l1ToL2MessageSubtreeSiblingPath,
|
|
469
502
|
l1ToL2MessageTreeSnapshotAfterInsertion,
|
|
470
503
|
baseParityInputs,
|
|
@@ -489,7 +522,13 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
489
522
|
// We build the base rollup inputs using a mock proof and verification key.
|
|
490
523
|
// These will be overwritten later once we have proven the tube circuit and any public kernels
|
|
491
524
|
const [ms, hints] = await elapsed(
|
|
492
|
-
insertSideEffectsAndBuildBaseRollupHints(
|
|
525
|
+
insertSideEffectsAndBuildBaseRollupHints(
|
|
526
|
+
tx,
|
|
527
|
+
provingState.globalVariables,
|
|
528
|
+
provingState.l1ToL2MessageTreeSnapshot,
|
|
529
|
+
db,
|
|
530
|
+
provingState.spongeBlobState,
|
|
531
|
+
),
|
|
493
532
|
);
|
|
494
533
|
|
|
495
534
|
this.metrics.recordBaseRollupInputs(ms);
|
|
@@ -687,6 +726,17 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
687
726
|
provingState.reject(`New archive root mismatch.`);
|
|
688
727
|
}
|
|
689
728
|
|
|
729
|
+
const endBlobAccumulator = provingState.endBlobAccumulator!;
|
|
730
|
+
const circuitEndBlobAccumulatorState = result.inputs.blobPublicInputs.endBlobAccumulator;
|
|
731
|
+
if (!circuitEndBlobAccumulatorState.equals(endBlobAccumulator.toBlobAccumulatorPublicInputs())) {
|
|
732
|
+
logger.error(
|
|
733
|
+
`Blob accumulator state mismatch.\nCircuit: ${inspect(circuitEndBlobAccumulatorState)}\nComputed: ${inspect(
|
|
734
|
+
endBlobAccumulator.toBlobAccumulatorPublicInputs(),
|
|
735
|
+
)}`,
|
|
736
|
+
);
|
|
737
|
+
provingState.reject(`Blob accumulator state mismatch.`);
|
|
738
|
+
}
|
|
739
|
+
|
|
690
740
|
logger.debug(`Completed ${rollupType} proof for block ${provingState.block!.number}`);
|
|
691
741
|
// validatePartialState(result.inputs.end, tx.treeSnapshots); // TODO(palla/prover)
|
|
692
742
|
|
|
@@ -770,7 +820,6 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
770
820
|
}
|
|
771
821
|
|
|
772
822
|
const inputs = provingState.getBlockMergeRollupInputs(location);
|
|
773
|
-
|
|
774
823
|
this.deferredProving(
|
|
775
824
|
provingState,
|
|
776
825
|
wrapCallbackInSpan(
|
|
@@ -825,7 +874,7 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
825
874
|
|
|
826
875
|
logger.debug(`Preparing root rollup`);
|
|
827
876
|
|
|
828
|
-
const inputs = provingState.getRootRollupInputs(
|
|
877
|
+
const inputs = provingState.getRootRollupInputs();
|
|
829
878
|
|
|
830
879
|
this.deferredProving(
|
|
831
880
|
provingState,
|
|
@@ -859,15 +908,17 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
859
908
|
}
|
|
860
909
|
|
|
861
910
|
private async checkAndEnqueueBlockRootRollup(provingState: BlockProvingState) {
|
|
911
|
+
const blockNumber = provingState.blockNumber;
|
|
912
|
+
// Accumulate as far as we can, in case blocks came in out of order and we are behind:
|
|
913
|
+
await this.provingState?.setBlobAccumulators(blockNumber);
|
|
862
914
|
if (!provingState.isReadyForBlockRootRollup()) {
|
|
863
|
-
logger.debug('Not ready for root rollup');
|
|
915
|
+
logger.debug('Not ready for block root rollup');
|
|
864
916
|
return;
|
|
865
917
|
}
|
|
866
918
|
if (provingState.blockRootRollupStarted) {
|
|
867
919
|
logger.debug('Block root rollup already started');
|
|
868
920
|
return;
|
|
869
921
|
}
|
|
870
|
-
const blockNumber = provingState.blockNumber;
|
|
871
922
|
|
|
872
923
|
// TODO(palla/prover): This closes the fork only on the happy path. If this epoch orchestrator
|
|
873
924
|
// is aborted and never reaches this point, it will leak the fork. We need to add a global cleanup,
|
|
@@ -3,15 +3,16 @@ import { times } from '@aztec/foundation/collection';
|
|
|
3
3
|
import { Fr } from '@aztec/foundation/fields';
|
|
4
4
|
import { createLogger } from '@aztec/foundation/log';
|
|
5
5
|
import { NativeACVMSimulator } from '@aztec/simulator/server';
|
|
6
|
-
import
|
|
7
|
-
ActualProverConfig,
|
|
8
|
-
EpochProver,
|
|
9
|
-
EpochProverManager,
|
|
10
|
-
ForkMerkleTreeOperations,
|
|
11
|
-
ProvingJobBroker,
|
|
12
|
-
ProvingJobConsumer,
|
|
13
|
-
ProvingJobProducer,
|
|
14
|
-
ServerCircuitProver,
|
|
6
|
+
import {
|
|
7
|
+
type ActualProverConfig,
|
|
8
|
+
type EpochProver,
|
|
9
|
+
type EpochProverManager,
|
|
10
|
+
type ForkMerkleTreeOperations,
|
|
11
|
+
type ProvingJobBroker,
|
|
12
|
+
type ProvingJobConsumer,
|
|
13
|
+
type ProvingJobProducer,
|
|
14
|
+
type ServerCircuitProver,
|
|
15
|
+
tryStop,
|
|
15
16
|
} from '@aztec/stdlib/interfaces/server';
|
|
16
17
|
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
|
|
17
18
|
|
|
@@ -87,6 +88,7 @@ export class ProverClient implements EpochProverManager {
|
|
|
87
88
|
}
|
|
88
89
|
this.running = false;
|
|
89
90
|
await this.stopAgents();
|
|
91
|
+
await tryStop(this.orchestratorClient);
|
|
90
92
|
}
|
|
91
93
|
|
|
92
94
|
/**
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { BatchedBlob, FinalBlobBatchingChallenges } from '@aztec/blob-lib';
|
|
1
2
|
import type { Fr } from '@aztec/foundation/fields';
|
|
2
3
|
import type { L2Block } from '@aztec/stdlib/block';
|
|
3
4
|
import type { EpochProver } from '@aztec/stdlib/interfaces/server';
|
|
@@ -15,8 +16,13 @@ export class ServerEpochProver implements EpochProver {
|
|
|
15
16
|
private orchestrator: ProvingOrchestrator,
|
|
16
17
|
) {}
|
|
17
18
|
|
|
18
|
-
startNewEpoch(
|
|
19
|
-
|
|
19
|
+
startNewEpoch(
|
|
20
|
+
epochNumber: number,
|
|
21
|
+
firstBlockNumber: number,
|
|
22
|
+
totalNumBlocks: number,
|
|
23
|
+
finalBlobBatchingChallenges: FinalBlobBatchingChallenges,
|
|
24
|
+
): void {
|
|
25
|
+
this.orchestrator.startNewEpoch(epochNumber, firstBlockNumber, totalNumBlocks, finalBlobBatchingChallenges);
|
|
20
26
|
this.facade.start();
|
|
21
27
|
}
|
|
22
28
|
startTubeCircuits(txs: Tx[]): Promise<void> {
|
|
@@ -25,7 +31,7 @@ export class ServerEpochProver implements EpochProver {
|
|
|
25
31
|
setBlockCompleted(blockNumber: number, expectedBlockHeader?: BlockHeader): Promise<L2Block> {
|
|
26
32
|
return this.orchestrator.setBlockCompleted(blockNumber, expectedBlockHeader);
|
|
27
33
|
}
|
|
28
|
-
finaliseEpoch(): Promise<{ publicInputs: RootRollupPublicInputs; proof: Proof }> {
|
|
34
|
+
finaliseEpoch(): Promise<{ publicInputs: RootRollupPublicInputs; proof: Proof; batchedBlobInputs: BatchedBlob }> {
|
|
29
35
|
return this.orchestrator.finaliseEpoch();
|
|
30
36
|
}
|
|
31
37
|
cancel(): void {
|