@aztec/prover-client 0.55.1 → 0.56.0
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/mocks/fixtures.d.ts.map +1 -1
- package/dest/mocks/fixtures.js +6 -27
- package/dest/mocks/test_context.d.ts +4 -5
- package/dest/mocks/test_context.d.ts.map +1 -1
- package/dest/mocks/test_context.js +7 -9
- package/dest/orchestrator/block-building-helpers.d.ts +12 -3
- package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
- package/dest/orchestrator/block-building-helpers.js +34 -32
- package/dest/orchestrator/{proving-state.d.ts → block-proving-state.d.ts} +17 -13
- package/dest/orchestrator/block-proving-state.d.ts.map +1 -0
- package/dest/orchestrator/block-proving-state.js +170 -0
- package/dest/orchestrator/epoch-proving-state.d.ts +57 -0
- package/dest/orchestrator/epoch-proving-state.d.ts.map +1 -0
- package/dest/orchestrator/epoch-proving-state.js +151 -0
- package/dest/orchestrator/orchestrator.d.ts +32 -11
- package/dest/orchestrator/orchestrator.d.ts.map +1 -1
- package/dest/orchestrator/orchestrator.js +246 -139
- package/dest/orchestrator/tx-proving-state.d.ts +3 -2
- package/dest/orchestrator/tx-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/tx-proving-state.js +54 -26
- package/dest/prover-agent/memory-proving-queue.d.ts +11 -5
- package/dest/prover-agent/memory-proving-queue.d.ts.map +1 -1
- package/dest/prover-agent/memory-proving-queue.js +16 -6
- package/dest/prover-agent/prover-agent.d.ts.map +1 -1
- package/dest/prover-agent/prover-agent.js +10 -10
- package/dest/prover-agent/rpc.d.ts.map +1 -1
- package/dest/prover-agent/rpc.js +6 -2
- package/dest/test/mock_prover.d.ts +4 -2
- package/dest/test/mock_prover.d.ts.map +1 -1
- package/dest/test/mock_prover.js +9 -3
- package/package.json +12 -11
- package/src/mocks/fixtures.ts +5 -49
- package/src/mocks/test_context.ts +7 -12
- package/src/orchestrator/block-building-helpers.ts +90 -57
- package/src/orchestrator/{proving-state.ts → block-proving-state.ts} +42 -40
- package/src/orchestrator/epoch-proving-state.ts +232 -0
- package/src/orchestrator/orchestrator.ts +410 -244
- package/src/orchestrator/tx-proving-state.ts +63 -27
- package/src/prover-agent/memory-proving-queue.ts +30 -16
- package/src/prover-agent/prover-agent.ts +11 -9
- package/src/prover-agent/rpc.ts +6 -0
- package/src/test/mock_prover.ts +23 -1
- package/dest/orchestrator/proving-state.d.ts.map +0 -1
- package/dest/orchestrator/proving-state.js +0 -170
|
@@ -1,40 +1,38 @@
|
|
|
1
1
|
import {
|
|
2
|
+
BlockProofError,
|
|
2
3
|
Body,
|
|
3
4
|
EncryptedNoteTxL2Logs,
|
|
4
5
|
EncryptedTxL2Logs,
|
|
5
6
|
L2Block,
|
|
6
7
|
MerkleTreeId,
|
|
8
|
+
PROVING_STATUS,
|
|
7
9
|
type PaddingProcessedTx,
|
|
8
10
|
type ProcessedTx,
|
|
9
|
-
|
|
11
|
+
type ProvingBlockResult,
|
|
12
|
+
ProvingRequestType,
|
|
13
|
+
type ProvingResult,
|
|
14
|
+
type ProvingTicket,
|
|
15
|
+
type PublicInputsAndRecursiveProof,
|
|
16
|
+
type ServerCircuitProver,
|
|
10
17
|
Tx,
|
|
11
18
|
type TxEffect,
|
|
12
19
|
UnencryptedTxL2Logs,
|
|
13
20
|
makeEmptyProcessedTx,
|
|
14
21
|
makePaddingProcessedTx,
|
|
15
|
-
|
|
22
|
+
mapProvingRequestTypeToCircuitName,
|
|
16
23
|
toTxEffect,
|
|
17
24
|
} from '@aztec/circuit-types';
|
|
18
|
-
import {
|
|
19
|
-
BlockProofError,
|
|
20
|
-
type BlockProver,
|
|
21
|
-
PROVING_STATUS,
|
|
22
|
-
type ProvingBlockResult,
|
|
23
|
-
type ProvingResult,
|
|
24
|
-
type ProvingTicket,
|
|
25
|
-
type PublicInputsAndRecursiveProof,
|
|
26
|
-
type ServerCircuitProver,
|
|
27
|
-
} from '@aztec/circuit-types/interfaces';
|
|
25
|
+
import { type EpochProver } from '@aztec/circuit-types/interfaces';
|
|
28
26
|
import { type CircuitName } from '@aztec/circuit-types/stats';
|
|
29
27
|
import {
|
|
30
28
|
AvmCircuitInputs,
|
|
31
29
|
type BaseOrMergeRollupPublicInputs,
|
|
32
30
|
BaseParityInputs,
|
|
33
31
|
type BaseRollupInputs,
|
|
34
|
-
|
|
32
|
+
type BlockRootOrBlockMergePublicInputs,
|
|
33
|
+
BlockRootRollupInputs,
|
|
35
34
|
Fr,
|
|
36
35
|
type GlobalVariables,
|
|
37
|
-
Header,
|
|
38
36
|
type KernelCircuitPublicInputs,
|
|
39
37
|
L1_TO_L2_MSG_SUBTREE_HEIGHT,
|
|
40
38
|
L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH,
|
|
@@ -48,9 +46,9 @@ import {
|
|
|
48
46
|
type RecursiveProof,
|
|
49
47
|
type RootParityInput,
|
|
50
48
|
RootParityInputs,
|
|
51
|
-
StateReference,
|
|
52
49
|
type TUBE_PROOF_LENGTH,
|
|
53
50
|
TubeInputs,
|
|
51
|
+
type VMCircuitPublicInputs,
|
|
54
52
|
type VerificationKeyAsFields,
|
|
55
53
|
VerificationKeyData,
|
|
56
54
|
makeEmptyProof,
|
|
@@ -58,7 +56,6 @@ import {
|
|
|
58
56
|
} from '@aztec/circuits.js';
|
|
59
57
|
import { makeTuple } from '@aztec/foundation/array';
|
|
60
58
|
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
61
|
-
import { sha256Trunc } from '@aztec/foundation/crypto';
|
|
62
59
|
import { AbortError } from '@aztec/foundation/error';
|
|
63
60
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
64
61
|
import { promiseWithResolvers } from '@aztec/foundation/promise';
|
|
@@ -73,16 +70,21 @@ import { inspect } from 'util';
|
|
|
73
70
|
|
|
74
71
|
import {
|
|
75
72
|
buildBaseRollupInput,
|
|
73
|
+
buildHeaderFromCircuitOutputs,
|
|
74
|
+
buildHeaderFromTxEffects,
|
|
75
|
+
createBlockMergeRollupInputs,
|
|
76
76
|
createMergeRollupInputs,
|
|
77
|
-
|
|
77
|
+
getPreviousRollupDataFromPublicInputs,
|
|
78
|
+
getRootRollupInput,
|
|
79
|
+
getRootTreeSiblingPath,
|
|
78
80
|
getSubtreeSiblingPath,
|
|
79
81
|
getTreeSnapshot,
|
|
80
|
-
validateBlockRootOutput,
|
|
81
82
|
validatePartialState,
|
|
82
83
|
validateTx,
|
|
83
84
|
} from './block-building-helpers.js';
|
|
85
|
+
import { type BlockProvingState, type MergeRollupInputData } from './block-proving-state.js';
|
|
86
|
+
import { type BlockMergeRollupInputData, EpochProvingState, type TreeSnapshots } from './epoch-proving-state.js';
|
|
84
87
|
import { ProvingOrchestratorMetrics } from './orchestrator_metrics.js';
|
|
85
|
-
import { type MergeRollupInputData, ProvingState, type TreeSnapshots } from './proving-state.js';
|
|
86
88
|
import { TX_PROVING_CODE, type TxProvingInstruction, TxProvingState } from './tx-proving-state.js';
|
|
87
89
|
|
|
88
90
|
const logger = createDebugLogger('aztec:prover:proving-orchestrator');
|
|
@@ -101,8 +103,8 @@ const logger = createDebugLogger('aztec:prover:proving-orchestrator');
|
|
|
101
103
|
/**
|
|
102
104
|
* The orchestrator, managing the flow of recursive proving operations required to build the rollup proof tree.
|
|
103
105
|
*/
|
|
104
|
-
export class ProvingOrchestrator implements
|
|
105
|
-
private provingState:
|
|
106
|
+
export class ProvingOrchestrator implements EpochProver {
|
|
107
|
+
private provingState: EpochProvingState | undefined = undefined;
|
|
106
108
|
private pendingProvingJobs: AbortController[] = [];
|
|
107
109
|
private paddingTx: PaddingProcessedTx | undefined = undefined;
|
|
108
110
|
|
|
@@ -132,6 +134,23 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
132
134
|
this.paddingTx = undefined;
|
|
133
135
|
}
|
|
134
136
|
|
|
137
|
+
@trackSpan('ProvingOrchestrator.startNewEpoch', (epochNumber, totalNumBlocks) => ({
|
|
138
|
+
[Attributes.EPOCH_SIZE]: totalNumBlocks,
|
|
139
|
+
[Attributes.EPOCH_NUMBER]: epochNumber,
|
|
140
|
+
}))
|
|
141
|
+
public startNewEpoch(epochNumber: number, totalNumBlocks: number): ProvingTicket {
|
|
142
|
+
const { promise: _promise, resolve, reject } = promiseWithResolvers<ProvingResult>();
|
|
143
|
+
const promise = _promise.catch(
|
|
144
|
+
(reason): ProvingResult => ({
|
|
145
|
+
status: PROVING_STATUS.FAILURE,
|
|
146
|
+
reason,
|
|
147
|
+
}),
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
this.provingState = new EpochProvingState(epochNumber, totalNumBlocks, resolve, reject);
|
|
151
|
+
return { provingPromise: promise };
|
|
152
|
+
}
|
|
153
|
+
|
|
135
154
|
/**
|
|
136
155
|
* Starts off a new block
|
|
137
156
|
* @param numTxs - The total number of transactions in the block. Must be a power of 2
|
|
@@ -149,6 +168,15 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
149
168
|
globalVariables: GlobalVariables,
|
|
150
169
|
l1ToL2Messages: Fr[],
|
|
151
170
|
): Promise<ProvingTicket> {
|
|
171
|
+
// If no proving state, assume we only care about proving this block and initialize a 1-block epoch
|
|
172
|
+
if (!this.provingState) {
|
|
173
|
+
this.startNewEpoch(globalVariables.blockNumber.toNumber(), 1);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (!this.provingState?.isAcceptingBlocks()) {
|
|
177
|
+
throw new Error(`Epoch not accepting further blocks`);
|
|
178
|
+
}
|
|
179
|
+
|
|
152
180
|
if (!Number.isInteger(numTxs) || numTxs < 2) {
|
|
153
181
|
throw new Error(`Length of txs for the block should be at least two (got ${numTxs})`);
|
|
154
182
|
}
|
|
@@ -163,11 +191,10 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
163
191
|
);
|
|
164
192
|
}
|
|
165
193
|
|
|
166
|
-
// Cancel any currently proving block before starting a new one
|
|
167
|
-
this.cancelBlock();
|
|
168
194
|
logger.info(
|
|
169
195
|
`Starting block ${globalVariables.blockNumber} for slot ${globalVariables.slotNumber} with ${numTxs} transactions`,
|
|
170
196
|
);
|
|
197
|
+
|
|
171
198
|
// we start the block by enqueueing all of the base parity circuits
|
|
172
199
|
let baseParityInputs: BaseParityInputs[] = [];
|
|
173
200
|
let l1ToL2MessagesPadded: Tuple<Fr, typeof NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP>;
|
|
@@ -197,36 +224,39 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
197
224
|
|
|
198
225
|
// Update the local trees to include the new l1 to l2 messages
|
|
199
226
|
await this.db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
|
|
227
|
+
const messageTreeSnapshotAfterInsertion = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, this.db);
|
|
228
|
+
|
|
229
|
+
// Get archive snapshot before this block lands
|
|
230
|
+
const startArchiveSnapshot = await getTreeSnapshot(MerkleTreeId.ARCHIVE, this.db);
|
|
231
|
+
const newArchiveSiblingPath = await getRootTreeSiblingPath(MerkleTreeId.ARCHIVE, this.db);
|
|
232
|
+
const previousBlockHash = await this.db.getLeafValue(
|
|
233
|
+
MerkleTreeId.ARCHIVE,
|
|
234
|
+
BigInt(startArchiveSnapshot.nextAvailableLeafIndex - 1),
|
|
235
|
+
);
|
|
200
236
|
|
|
201
237
|
const { promise: _promise, resolve, reject } = promiseWithResolvers<ProvingResult>();
|
|
202
|
-
const promise = _promise.catch(
|
|
203
|
-
(reason): ProvingResult => ({
|
|
204
|
-
status: PROVING_STATUS.FAILURE,
|
|
205
|
-
reason,
|
|
206
|
-
}),
|
|
207
|
-
);
|
|
238
|
+
const promise = _promise.catch((reason): ProvingResult => ({ status: PROVING_STATUS.FAILURE, reason }));
|
|
208
239
|
|
|
209
|
-
|
|
240
|
+
this.provingState!.startNewBlock(
|
|
210
241
|
numTxs,
|
|
211
|
-
resolve,
|
|
212
|
-
reject,
|
|
213
242
|
globalVariables,
|
|
214
243
|
l1ToL2MessagesPadded,
|
|
215
|
-
baseParityInputs.length,
|
|
216
244
|
messageTreeSnapshot,
|
|
217
245
|
newL1ToL2MessageTreeRootSiblingPath,
|
|
246
|
+
messageTreeSnapshotAfterInsertion,
|
|
247
|
+
startArchiveSnapshot,
|
|
248
|
+
newArchiveSiblingPath,
|
|
249
|
+
previousBlockHash!,
|
|
250
|
+
resolve,
|
|
251
|
+
reject,
|
|
218
252
|
);
|
|
219
253
|
|
|
254
|
+
// Enqueue base parity circuits for the block
|
|
220
255
|
for (let i = 0; i < baseParityInputs.length; i++) {
|
|
221
|
-
this.enqueueBaseParityCircuit(provingState
|
|
256
|
+
this.enqueueBaseParityCircuit(this.provingState!.currentBlock!, baseParityInputs[i], i);
|
|
222
257
|
}
|
|
223
258
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
const ticket: ProvingTicket = {
|
|
227
|
-
provingPromise: promise,
|
|
228
|
-
};
|
|
229
|
-
return ticket;
|
|
259
|
+
return { provingPromise: promise };
|
|
230
260
|
}
|
|
231
261
|
|
|
232
262
|
/**
|
|
@@ -237,11 +267,12 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
237
267
|
[Attributes.TX_HASH]: tx.hash.toString(),
|
|
238
268
|
}))
|
|
239
269
|
public async addNewTx(tx: ProcessedTx): Promise<void> {
|
|
240
|
-
|
|
270
|
+
const provingState = this?.provingState?.currentBlock;
|
|
271
|
+
if (!provingState) {
|
|
241
272
|
throw new Error(`Invalid proving state, call startNewBlock before adding transactions`);
|
|
242
273
|
}
|
|
243
274
|
|
|
244
|
-
if (!
|
|
275
|
+
if (!provingState.isAcceptingTransactions()) {
|
|
245
276
|
throw new Error(`Rollup not accepting further transactions`);
|
|
246
277
|
}
|
|
247
278
|
|
|
@@ -254,34 +285,43 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
254
285
|
return;
|
|
255
286
|
}
|
|
256
287
|
|
|
257
|
-
const [inputs, treeSnapshots] = await this.prepareTransaction(tx,
|
|
258
|
-
this.enqueueFirstProofs(inputs, treeSnapshots, tx,
|
|
288
|
+
const [inputs, treeSnapshots] = await this.prepareTransaction(tx, provingState);
|
|
289
|
+
this.enqueueFirstProofs(inputs, treeSnapshots, tx, provingState);
|
|
290
|
+
|
|
291
|
+
if (provingState.transactionsReceived === provingState.totalNumTxs) {
|
|
292
|
+
logger.verbose(
|
|
293
|
+
`All transactions received for block ${provingState.globalVariables.blockNumber}. Assembling header.`,
|
|
294
|
+
);
|
|
295
|
+
await this.buildBlockHeader(provingState);
|
|
296
|
+
}
|
|
259
297
|
}
|
|
260
298
|
|
|
261
299
|
/**
|
|
262
300
|
* Marks the block as full and pads it if required, no more transactions will be accepted.
|
|
301
|
+
* Computes the block header and updates the archive tree.
|
|
263
302
|
*/
|
|
264
303
|
@trackSpan('ProvingOrchestrator.setBlockCompleted', function () {
|
|
265
|
-
|
|
304
|
+
const block = this.provingState?.currentBlock;
|
|
305
|
+
if (!block) {
|
|
266
306
|
return {};
|
|
267
307
|
}
|
|
268
|
-
|
|
269
308
|
return {
|
|
270
|
-
[Attributes.BLOCK_NUMBER]:
|
|
271
|
-
[Attributes.BLOCK_SIZE]:
|
|
272
|
-
[Attributes.BLOCK_TXS_COUNT]:
|
|
309
|
+
[Attributes.BLOCK_NUMBER]: block.globalVariables.blockNumber.toNumber(),
|
|
310
|
+
[Attributes.BLOCK_SIZE]: block.totalNumTxs,
|
|
311
|
+
[Attributes.BLOCK_TXS_COUNT]: block.transactionsReceived,
|
|
273
312
|
};
|
|
274
313
|
})
|
|
275
314
|
public async setBlockCompleted() {
|
|
276
|
-
|
|
315
|
+
const provingState = this.provingState?.currentBlock;
|
|
316
|
+
if (!provingState) {
|
|
277
317
|
throw new Error(`Invalid proving state, call startNewBlock before adding transactions or completing the block`);
|
|
278
318
|
}
|
|
279
319
|
|
|
280
320
|
// we may need to pad the rollup with empty transactions
|
|
281
|
-
const paddingTxCount =
|
|
321
|
+
const paddingTxCount = provingState.totalNumTxs - provingState.transactionsReceived;
|
|
282
322
|
if (paddingTxCount === 0) {
|
|
283
323
|
return;
|
|
284
|
-
} else if (
|
|
324
|
+
} else if (provingState.totalNumTxs > 2) {
|
|
285
325
|
throw new Error(`Block not ready for completion: expecting ${paddingTxCount} more transactions.`);
|
|
286
326
|
}
|
|
287
327
|
|
|
@@ -295,13 +335,13 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
295
335
|
// Then enqueue the proving of all the transactions
|
|
296
336
|
const unprovenPaddingTx = makeEmptyProcessedTx(
|
|
297
337
|
this.db.getInitialHeader(),
|
|
298
|
-
|
|
299
|
-
|
|
338
|
+
provingState.globalVariables.chainId,
|
|
339
|
+
provingState.globalVariables.version,
|
|
300
340
|
getVKTreeRoot(),
|
|
301
341
|
);
|
|
302
342
|
const txInputs: Array<{ inputs: BaseRollupInputs; snapshot: TreeSnapshots }> = [];
|
|
303
343
|
for (let i = 0; i < paddingTxCount; i++) {
|
|
304
|
-
const [inputs, snapshot] = await this.prepareTransaction(unprovenPaddingTx,
|
|
344
|
+
const [inputs, snapshot] = await this.prepareTransaction(unprovenPaddingTx, provingState);
|
|
305
345
|
const txInput = {
|
|
306
346
|
inputs,
|
|
307
347
|
snapshot,
|
|
@@ -310,13 +350,53 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
310
350
|
}
|
|
311
351
|
|
|
312
352
|
// Now enqueue the proving
|
|
313
|
-
this.enqueuePaddingTxs(
|
|
353
|
+
this.enqueuePaddingTxs(provingState, txInputs, unprovenPaddingTx);
|
|
354
|
+
|
|
355
|
+
// And build the block header
|
|
356
|
+
logger.verbose(`Block ${provingState.globalVariables.blockNumber} padded with empty tx(s). Assembling header.`);
|
|
357
|
+
await this.buildBlockHeader(provingState);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
private async buildBlockHeader(provingState: BlockProvingState) {
|
|
361
|
+
// Collect all new nullifiers, commitments, and contracts from all txs in this block to build body
|
|
362
|
+
const gasFees = provingState.globalVariables.gasFees;
|
|
363
|
+
const nonEmptyTxEffects: TxEffect[] = provingState!.allTxs
|
|
364
|
+
.map(txProvingState => toTxEffect(txProvingState.processedTx, gasFees))
|
|
365
|
+
.filter(txEffect => !txEffect.isEmpty());
|
|
366
|
+
const body = new Body(nonEmptyTxEffects);
|
|
367
|
+
|
|
368
|
+
// Given we've applied every change from this block, now assemble the block header
|
|
369
|
+
// and update the archive tree, so we're ready to start processing the next block
|
|
370
|
+
const header = await buildHeaderFromTxEffects(
|
|
371
|
+
body,
|
|
372
|
+
provingState.globalVariables,
|
|
373
|
+
provingState.newL1ToL2Messages,
|
|
374
|
+
this.db,
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
logger.verbose(`Updating archive tree with block ${provingState.blockNumber} header ${header.hash().toString()}`);
|
|
378
|
+
await this.db.updateArchive(header);
|
|
379
|
+
|
|
380
|
+
// Assemble the L2 block
|
|
381
|
+
const newArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, this.db);
|
|
382
|
+
const l2Block = L2Block.fromFields({ archive: newArchive, header, body });
|
|
383
|
+
|
|
384
|
+
if (!l2Block.body.getTxsEffectsHash().equals(header.contentCommitment.txsEffectsHash)) {
|
|
385
|
+
throw new Error(
|
|
386
|
+
`Txs effects hash mismatch, ${l2Block.body
|
|
387
|
+
.getTxsEffectsHash()
|
|
388
|
+
.toString('hex')} == ${header.contentCommitment.txsEffectsHash.toString('hex')} `,
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
logger.verbose(`Orchestrator finalised block ${l2Block.number}`);
|
|
393
|
+
provingState.block = l2Block;
|
|
314
394
|
}
|
|
315
395
|
|
|
316
396
|
// Enqueues the proving of the required padding transactions
|
|
317
397
|
// If the fully proven padding transaction is not available, this will first be proven
|
|
318
398
|
private enqueuePaddingTxs(
|
|
319
|
-
provingState:
|
|
399
|
+
provingState: BlockProvingState,
|
|
320
400
|
txInputs: Array<{ inputs: BaseRollupInputs; snapshot: TreeSnapshots }>,
|
|
321
401
|
unprovenPaddingTx: ProcessedTx,
|
|
322
402
|
) {
|
|
@@ -334,7 +414,7 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
334
414
|
'ProvingOrchestrator.prover.getEmptyPrivateKernelProof',
|
|
335
415
|
{
|
|
336
416
|
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
337
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'private-kernel-empty'
|
|
417
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'private-kernel-empty' satisfies CircuitName,
|
|
338
418
|
},
|
|
339
419
|
signal =>
|
|
340
420
|
this.prover.getEmptyPrivateKernelProof(
|
|
@@ -368,7 +448,7 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
368
448
|
private provePaddingTransactions(
|
|
369
449
|
txInputs: Array<{ inputs: BaseRollupInputs; snapshot: TreeSnapshots }>,
|
|
370
450
|
paddingTx: PaddingProcessedTx,
|
|
371
|
-
provingState:
|
|
451
|
+
provingState: BlockProvingState,
|
|
372
452
|
) {
|
|
373
453
|
// The padding tx contains the proof and vk, generated separately from the base inputs
|
|
374
454
|
// Copy these into the base rollup inputs and enqueue the base rollup proof
|
|
@@ -385,9 +465,9 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
385
465
|
}
|
|
386
466
|
|
|
387
467
|
/**
|
|
388
|
-
* Cancel any further proving
|
|
468
|
+
* Cancel any further proving
|
|
389
469
|
*/
|
|
390
|
-
public
|
|
470
|
+
public cancel() {
|
|
391
471
|
for (const controller of this.pendingProvingJobs) {
|
|
392
472
|
controller.abort();
|
|
393
473
|
}
|
|
@@ -397,133 +477,83 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
397
477
|
|
|
398
478
|
/**
|
|
399
479
|
* Extract the block header from public inputs.
|
|
400
|
-
* TODO(#7346): Refactor this once new batch rollup circuits are integrated
|
|
401
480
|
* @returns The header of this proving state's block.
|
|
402
481
|
*/
|
|
403
|
-
private
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
) {
|
|
409
|
-
throw new Error(`Invalid proving state, a block must be proven before its header can be extracted.`);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
const rootRollupOutputs = this.provingState.blockRootRollupPublicInputs;
|
|
413
|
-
const previousMergeData = this.provingState.getMergeInputs(0).inputs;
|
|
482
|
+
private extractBlockHeaderFromPublicInputs(
|
|
483
|
+
provingState: BlockProvingState,
|
|
484
|
+
rootRollupOutputs: BlockRootOrBlockMergePublicInputs,
|
|
485
|
+
) {
|
|
486
|
+
const previousMergeData = provingState.getMergeInputs(0).inputs;
|
|
414
487
|
|
|
415
488
|
if (!previousMergeData[0] || !previousMergeData[1]) {
|
|
416
489
|
throw new Error(`Invalid proving state, final merge inputs before block root circuit missing.`);
|
|
417
490
|
}
|
|
418
491
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
sha256Trunc(Buffer.concat([previousMergeData[0].outHash.toBuffer(), previousMergeData[1].outHash.toBuffer()])),
|
|
492
|
+
return buildHeaderFromCircuitOutputs(
|
|
493
|
+
[previousMergeData[0], previousMergeData[1]],
|
|
494
|
+
provingState.finalRootParityInput!.publicInputs,
|
|
495
|
+
rootRollupOutputs,
|
|
496
|
+
provingState.messageTreeSnapshotAfterInsertion,
|
|
497
|
+
logger,
|
|
426
498
|
);
|
|
427
|
-
const state = new StateReference(
|
|
428
|
-
await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, this.db),
|
|
429
|
-
previousMergeData[1].end,
|
|
430
|
-
);
|
|
431
|
-
const header = new Header(
|
|
432
|
-
rootRollupOutputs.previousArchive,
|
|
433
|
-
contentCommitment,
|
|
434
|
-
state,
|
|
435
|
-
previousMergeData[0].constants.globalVariables,
|
|
436
|
-
previousMergeData[0].accumulatedFees.add(previousMergeData[1].accumulatedFees),
|
|
437
|
-
);
|
|
438
|
-
if (!header.hash().equals(rootRollupOutputs.endBlockHash)) {
|
|
439
|
-
throw new Error(`Block header mismatch in finalise.`);
|
|
440
|
-
}
|
|
441
|
-
return header;
|
|
442
499
|
}
|
|
443
500
|
|
|
444
501
|
/**
|
|
445
|
-
*
|
|
502
|
+
* Returns the fully proven block. Requires proving to have been completed.
|
|
503
|
+
* @param index - The index of the block to finalise. Defaults to the last block.
|
|
446
504
|
* @returns The fully proven block and proof.
|
|
447
505
|
*/
|
|
448
|
-
|
|
449
|
-
return {
|
|
450
|
-
[Attributes.BLOCK_NUMBER]: this.provingState!.globalVariables.blockNumber.toNumber(),
|
|
451
|
-
[Attributes.BLOCK_TXS_COUNT]: this.provingState!.transactionsReceived,
|
|
452
|
-
[Attributes.BLOCK_SIZE]: this.provingState!.totalNumTxs,
|
|
453
|
-
};
|
|
454
|
-
})
|
|
455
|
-
public async finaliseBlock() {
|
|
506
|
+
public finaliseBlock(index?: number) {
|
|
456
507
|
try {
|
|
457
|
-
|
|
458
|
-
throw new Error(`Invalid proving state, a block must be proven before it can be finalised`);
|
|
459
|
-
}
|
|
460
|
-
if (this.provingState.block) {
|
|
461
|
-
throw new Error('Block already finalised');
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
const rootRollupOutputs = this.provingState.blockRootRollupPublicInputs;
|
|
465
|
-
const header = await this.extractBlockHeader();
|
|
466
|
-
|
|
467
|
-
logger?.debug(`Updating and validating root trees`);
|
|
468
|
-
await this.db.updateArchive(header);
|
|
469
|
-
|
|
470
|
-
await validateBlockRootOutput(rootRollupOutputs, header, this.db);
|
|
471
|
-
|
|
472
|
-
// Collect all new nullifiers, commitments, and contracts from all txs in this block
|
|
473
|
-
const gasFees = this.provingState.globalVariables.gasFees;
|
|
474
|
-
const nonEmptyTxEffects: TxEffect[] = this.provingState!.allTxs.map(txProvingState =>
|
|
475
|
-
toTxEffect(txProvingState.processedTx, gasFees),
|
|
476
|
-
).filter(txEffect => !txEffect.isEmpty());
|
|
477
|
-
const blockBody = new Body(nonEmptyTxEffects);
|
|
478
|
-
|
|
479
|
-
const l2Block = L2Block.fromFields({
|
|
480
|
-
archive: rootRollupOutputs.newArchive,
|
|
481
|
-
header: header,
|
|
482
|
-
body: blockBody,
|
|
483
|
-
});
|
|
508
|
+
const block = this.provingState?.blocks[index ?? this.provingState?.blocks.length - 1];
|
|
484
509
|
|
|
485
|
-
if (!
|
|
486
|
-
|
|
487
|
-
throw new Error(
|
|
488
|
-
`Txs effects hash mismatch, ${l2Block.body
|
|
489
|
-
.getTxsEffectsHash()
|
|
490
|
-
.toString('hex')} == ${header.contentCommitment.txsEffectsHash.toString('hex')} `,
|
|
491
|
-
);
|
|
510
|
+
if (!block || !block.blockRootRollupPublicInputs || !block.finalProof || !block.block) {
|
|
511
|
+
throw new Error(`Invalid proving state, a block must be proven before it can be finalised`);
|
|
492
512
|
}
|
|
493
513
|
|
|
494
|
-
logger.info(`Orchestrator finalised block ${l2Block.number}`);
|
|
495
|
-
|
|
496
|
-
this.provingState.block = l2Block;
|
|
497
|
-
|
|
498
514
|
const blockResult: ProvingBlockResult = {
|
|
499
|
-
proof:
|
|
500
|
-
aggregationObject:
|
|
501
|
-
block:
|
|
515
|
+
proof: block.finalProof,
|
|
516
|
+
aggregationObject: block.finalProof.extractAggregationObject(),
|
|
517
|
+
block: block.block!,
|
|
502
518
|
};
|
|
503
519
|
|
|
504
520
|
pushTestData('blockResults', {
|
|
505
521
|
proverId: this.proverId.toString(),
|
|
506
522
|
vkTreeRoot: getVKTreeRoot().toString(),
|
|
507
|
-
block:
|
|
508
|
-
proof:
|
|
523
|
+
block: blockResult.block.toString(),
|
|
524
|
+
proof: blockResult.proof.toString(),
|
|
509
525
|
aggregationObject: blockResult.aggregationObject.map(x => x.toString()),
|
|
510
526
|
});
|
|
511
527
|
|
|
512
|
-
return blockResult;
|
|
528
|
+
return Promise.resolve(blockResult);
|
|
513
529
|
} catch (err) {
|
|
514
530
|
throw new BlockProofError(
|
|
515
531
|
err && typeof err === 'object' && 'message' in err ? String(err.message) : String(err),
|
|
516
|
-
this.provingState?.allTxs.map(x =>
|
|
532
|
+
this.provingState?.blocks[index ?? this.provingState?.blocks.length - 1]?.allTxs.map(x =>
|
|
533
|
+
Tx.getHash(x.processedTx),
|
|
534
|
+
) ?? [],
|
|
517
535
|
);
|
|
518
536
|
}
|
|
519
537
|
}
|
|
520
538
|
|
|
539
|
+
/**
|
|
540
|
+
* Returns the proof for the current epoch.
|
|
541
|
+
* Requires proving to have been completed.
|
|
542
|
+
*/
|
|
543
|
+
public finaliseEpoch() {
|
|
544
|
+
if (!this.provingState || !this.provingState.rootRollupPublicInputs || !this.provingState.finalProof) {
|
|
545
|
+
throw new Error(`Invalid proving state, an epoch must be proven before it can be finalised`);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
return { proof: this.provingState.finalProof, publicInputs: this.provingState.rootRollupPublicInputs };
|
|
549
|
+
}
|
|
550
|
+
|
|
521
551
|
/**
|
|
522
552
|
* Starts the proving process for the given transaction and adds it to our state
|
|
523
553
|
* @param tx - The transaction whose proving we wish to commence
|
|
524
554
|
* @param provingState - The proving state being worked on
|
|
525
555
|
*/
|
|
526
|
-
private async prepareTransaction(tx: ProcessedTx, provingState:
|
|
556
|
+
private async prepareTransaction(tx: ProcessedTx, provingState: BlockProvingState) {
|
|
527
557
|
const txInputs = await this.prepareBaseRollupInputs(provingState, tx);
|
|
528
558
|
if (!txInputs) {
|
|
529
559
|
// This should not be possible
|
|
@@ -536,7 +566,7 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
536
566
|
inputs: BaseRollupInputs,
|
|
537
567
|
treeSnapshots: TreeSnapshots,
|
|
538
568
|
tx: ProcessedTx,
|
|
539
|
-
provingState:
|
|
569
|
+
provingState: BlockProvingState,
|
|
540
570
|
) {
|
|
541
571
|
const txProvingState = new TxProvingState(tx, inputs, treeSnapshots);
|
|
542
572
|
const txIndex = provingState.addNewTx(txProvingState);
|
|
@@ -557,7 +587,7 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
557
587
|
* @param job - The actual job, returns a promise notifying of the job's completion
|
|
558
588
|
*/
|
|
559
589
|
private deferredProving<T>(
|
|
560
|
-
provingState:
|
|
590
|
+
provingState: EpochProvingState | BlockProvingState | undefined,
|
|
561
591
|
request: (signal: AbortSignal) => Promise<T>,
|
|
562
592
|
callback: (result: T) => void | Promise<void>,
|
|
563
593
|
) {
|
|
@@ -617,7 +647,7 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
617
647
|
[Attributes.TX_HASH]: tx.hash.toString(),
|
|
618
648
|
}))
|
|
619
649
|
private async prepareBaseRollupInputs(
|
|
620
|
-
provingState:
|
|
650
|
+
provingState: BlockProvingState | undefined,
|
|
621
651
|
tx: ProcessedTx,
|
|
622
652
|
): Promise<[BaseRollupInputs, TreeSnapshots] | undefined> {
|
|
623
653
|
if (!provingState?.verifyState()) {
|
|
@@ -655,34 +685,9 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
655
685
|
return [inputs, treeSnapshots];
|
|
656
686
|
}
|
|
657
687
|
|
|
658
|
-
// Stores the intermediate inputs prepared for a merge proof
|
|
659
|
-
private storeMergeInputs(
|
|
660
|
-
provingState: ProvingState,
|
|
661
|
-
currentLevel: bigint,
|
|
662
|
-
currentIndex: bigint,
|
|
663
|
-
mergeInputs: [
|
|
664
|
-
BaseOrMergeRollupPublicInputs,
|
|
665
|
-
RecursiveProof<typeof NESTED_RECURSIVE_PROOF_LENGTH>,
|
|
666
|
-
VerificationKeyAsFields,
|
|
667
|
-
],
|
|
668
|
-
) {
|
|
669
|
-
const [mergeLevel, indexWithinMergeLevel, indexWithinMerge] = provingState.findMergeLevel(
|
|
670
|
-
currentLevel,
|
|
671
|
-
currentIndex,
|
|
672
|
-
);
|
|
673
|
-
const mergeIndex = 2n ** mergeLevel - 1n + indexWithinMergeLevel;
|
|
674
|
-
const ready = provingState.storeMergeInputs(mergeInputs, Number(indexWithinMerge), Number(mergeIndex));
|
|
675
|
-
return {
|
|
676
|
-
ready,
|
|
677
|
-
indexWithinMergeLevel,
|
|
678
|
-
mergeLevel,
|
|
679
|
-
mergeInputData: provingState.getMergeInputs(Number(mergeIndex)),
|
|
680
|
-
};
|
|
681
|
-
}
|
|
682
|
-
|
|
683
688
|
// Executes the base rollup circuit and stored the output as intermediate state for the parent merge/root circuit
|
|
684
689
|
// Executes the next level of merge if all inputs are available
|
|
685
|
-
private enqueueBaseRollup(provingState:
|
|
690
|
+
private enqueueBaseRollup(provingState: BlockProvingState | undefined, index: bigint, tx: TxProvingState) {
|
|
686
691
|
if (!provingState?.verifyState()) {
|
|
687
692
|
logger.debug('Not running base rollup, state invalid');
|
|
688
693
|
return;
|
|
@@ -743,7 +748,7 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
743
748
|
{
|
|
744
749
|
[Attributes.TX_HASH]: tx.processedTx.hash.toString(),
|
|
745
750
|
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
746
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'base-rollup'
|
|
751
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'base-rollup' satisfies CircuitName,
|
|
747
752
|
},
|
|
748
753
|
signal => this.prover.getBaseRollupProof(tx.baseRollupInputs, signal, provingState.epochNumber),
|
|
749
754
|
),
|
|
@@ -762,7 +767,7 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
762
767
|
|
|
763
768
|
// Enqueues the tub circuit for a given transaction index
|
|
764
769
|
// Once completed, will enqueue the next circuit, either a public kernel or the base rollup
|
|
765
|
-
private enqueueTube(provingState:
|
|
770
|
+
private enqueueTube(provingState: BlockProvingState, txIndex: number) {
|
|
766
771
|
if (!provingState?.verifyState()) {
|
|
767
772
|
logger.debug('Not running tube circuit, state invalid');
|
|
768
773
|
return;
|
|
@@ -779,7 +784,7 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
779
784
|
{
|
|
780
785
|
[Attributes.TX_HASH]: txProvingState.processedTx.hash.toString(),
|
|
781
786
|
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
782
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'tube-circuit'
|
|
787
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'tube-circuit' satisfies CircuitName,
|
|
783
788
|
},
|
|
784
789
|
signal =>
|
|
785
790
|
this.prover.getTubeProof(
|
|
@@ -791,14 +796,7 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
791
796
|
result => {
|
|
792
797
|
logger.debug(`Completed tube proof for tx index: ${txIndex}`);
|
|
793
798
|
const nextKernelRequest = txProvingState.getNextPublicKernelFromTubeProof(result.tubeProof, result.tubeVK);
|
|
794
|
-
this.checkAndEnqueueNextTxCircuit(
|
|
795
|
-
provingState,
|
|
796
|
-
txIndex,
|
|
797
|
-
-1,
|
|
798
|
-
result.tubeProof,
|
|
799
|
-
result.tubeVK,
|
|
800
|
-
nextKernelRequest,
|
|
801
|
-
);
|
|
799
|
+
this.checkAndEnqueueNextTxCircuit(provingState, txIndex, result.tubeProof, result.tubeVK, nextKernelRequest);
|
|
802
800
|
},
|
|
803
801
|
);
|
|
804
802
|
}
|
|
@@ -806,7 +804,7 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
806
804
|
// Executes the merge rollup circuit and stored the output as intermediate state for the parent merge/block root circuit
|
|
807
805
|
// Enqueues the next level of merge if all inputs are available
|
|
808
806
|
private enqueueMergeRollup(
|
|
809
|
-
provingState:
|
|
807
|
+
provingState: BlockProvingState,
|
|
810
808
|
level: bigint,
|
|
811
809
|
index: bigint,
|
|
812
810
|
mergeInputData: MergeRollupInputData,
|
|
@@ -823,7 +821,7 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
823
821
|
'ProvingOrchestrator.prover.getMergeRollupProof',
|
|
824
822
|
{
|
|
825
823
|
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
826
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'merge-rollup'
|
|
824
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'merge-rollup' satisfies CircuitName,
|
|
827
825
|
},
|
|
828
826
|
signal => this.prover.getMergeRollupProof(inputs, signal, provingState.epochNumber),
|
|
829
827
|
),
|
|
@@ -838,29 +836,40 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
838
836
|
}
|
|
839
837
|
|
|
840
838
|
// Executes the block root rollup circuit
|
|
841
|
-
private
|
|
839
|
+
private enqueueBlockRootRollup(provingState: BlockProvingState | undefined) {
|
|
842
840
|
if (!provingState?.verifyState()) {
|
|
843
|
-
logger.debug('Not running root rollup, state no longer valid');
|
|
841
|
+
logger.debug('Not running block root rollup, state no longer valid');
|
|
844
842
|
return;
|
|
845
843
|
}
|
|
846
844
|
const mergeInputData = provingState.getMergeInputs(0);
|
|
847
845
|
const rootParityInput = provingState.finalRootParityInput!;
|
|
848
846
|
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
provingState.messageTreeRootSiblingPath,
|
|
860
|
-
this.db,
|
|
861
|
-
this.proverId,
|
|
847
|
+
logger.debug(
|
|
848
|
+
`Enqueuing block root rollup for block ${provingState.blockNumber} with ${provingState.newL1ToL2Messages.length} l1 to l2 msgs`,
|
|
849
|
+
);
|
|
850
|
+
|
|
851
|
+
const previousRollupData: BlockRootRollupInputs['previousRollupData'] = makeTuple(2, i =>
|
|
852
|
+
getPreviousRollupDataFromPublicInputs(
|
|
853
|
+
mergeInputData.inputs[i]!,
|
|
854
|
+
mergeInputData.proofs[i]!,
|
|
855
|
+
mergeInputData.verificationKeys[i]!,
|
|
856
|
+
),
|
|
862
857
|
);
|
|
863
858
|
|
|
859
|
+
const inputs = BlockRootRollupInputs.from({
|
|
860
|
+
previousRollupData,
|
|
861
|
+
l1ToL2Roots: rootParityInput,
|
|
862
|
+
newL1ToL2Messages: provingState.newL1ToL2Messages,
|
|
863
|
+
newL1ToL2MessageTreeRootSiblingPath: provingState.messageTreeRootSiblingPath,
|
|
864
|
+
startL1ToL2MessageTreeSnapshot: provingState.messageTreeSnapshot,
|
|
865
|
+
startArchiveSnapshot: provingState.archiveTreeSnapshot,
|
|
866
|
+
newArchiveSiblingPath: provingState.archiveTreeRootSiblingPath,
|
|
867
|
+
previousBlockHash: provingState.previousBlockHash,
|
|
868
|
+
proverId: this.proverId,
|
|
869
|
+
});
|
|
870
|
+
|
|
871
|
+
const shouldProveEpoch = this.provingState!.totalNumBlocks > 1;
|
|
872
|
+
|
|
864
873
|
this.deferredProving(
|
|
865
874
|
provingState,
|
|
866
875
|
wrapCallbackInSpan(
|
|
@@ -868,25 +877,48 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
868
877
|
'ProvingOrchestrator.prover.getBlockRootRollupProof',
|
|
869
878
|
{
|
|
870
879
|
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
871
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'block-root-rollup'
|
|
880
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'block-root-rollup' satisfies CircuitName,
|
|
872
881
|
},
|
|
873
|
-
signal =>
|
|
882
|
+
signal =>
|
|
883
|
+
shouldProveEpoch
|
|
884
|
+
? this.prover.getBlockRootRollupProof(inputs, signal, provingState.epochNumber)
|
|
885
|
+
: this.prover.getBlockRootRollupFinalProof(inputs, signal, provingState.epochNumber),
|
|
874
886
|
),
|
|
875
887
|
result => {
|
|
888
|
+
const header = this.extractBlockHeaderFromPublicInputs(provingState, result.inputs);
|
|
889
|
+
if (!header.hash().equals(provingState.block!.header.hash())) {
|
|
890
|
+
logger.error(
|
|
891
|
+
`Block header mismatch\nCircuit:${inspect(header)}\nComputed:${inspect(provingState.block!.header)}`,
|
|
892
|
+
);
|
|
893
|
+
provingState.reject(`Block header hash mismatch`);
|
|
894
|
+
}
|
|
895
|
+
|
|
876
896
|
provingState.blockRootRollupPublicInputs = result.inputs;
|
|
877
897
|
provingState.finalProof = result.proof.binaryProof;
|
|
898
|
+
provingState.resolve({ status: PROVING_STATUS.SUCCESS });
|
|
899
|
+
|
|
900
|
+
logger.debug(`Completed proof for block root rollup for ${provingState.block?.number}`);
|
|
901
|
+
// validatePartialState(result.inputs.end, tx.treeSnapshots); // TODO(palla/prover)
|
|
878
902
|
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
903
|
+
// TODO(palla/prover): Remove this once we've dropped the flow for proving single blocks
|
|
904
|
+
if (!shouldProveEpoch) {
|
|
905
|
+
logger.verbose(`Skipping epoch rollup, only one block in epoch`);
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
const currentLevel = this.provingState!.numMergeLevels + 1n;
|
|
910
|
+
this.storeAndExecuteNextBlockMergeLevel(this.provingState!, currentLevel, BigInt(provingState.index), [
|
|
911
|
+
result.inputs,
|
|
912
|
+
result.proof,
|
|
913
|
+
result.verificationKey.keyAsFields,
|
|
914
|
+
]);
|
|
883
915
|
},
|
|
884
916
|
);
|
|
885
917
|
}
|
|
886
918
|
|
|
887
919
|
// Executes the base parity circuit and stores the intermediate state for the root parity circuit
|
|
888
920
|
// Enqueues the root parity circuit if all inputs are available
|
|
889
|
-
private enqueueBaseParityCircuit(provingState:
|
|
921
|
+
private enqueueBaseParityCircuit(provingState: BlockProvingState, inputs: BaseParityInputs, index: number) {
|
|
890
922
|
this.deferredProving(
|
|
891
923
|
provingState,
|
|
892
924
|
wrapCallbackInSpan(
|
|
@@ -894,7 +926,7 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
894
926
|
'ProvingOrchestrator.prover.getBaseParityProof',
|
|
895
927
|
{
|
|
896
928
|
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
897
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'base-parity'
|
|
929
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'base-parity' satisfies CircuitName,
|
|
898
930
|
},
|
|
899
931
|
signal => this.prover.getBaseParityProof(inputs, signal, provingState.epochNumber),
|
|
900
932
|
),
|
|
@@ -915,7 +947,7 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
915
947
|
|
|
916
948
|
// Runs the root parity circuit ans stored the outputs
|
|
917
949
|
// Enqueues the root rollup proof if all inputs are available
|
|
918
|
-
private enqueueRootParityCircuit(provingState:
|
|
950
|
+
private enqueueRootParityCircuit(provingState: BlockProvingState, inputs: RootParityInputs) {
|
|
919
951
|
this.deferredProving(
|
|
920
952
|
provingState,
|
|
921
953
|
wrapCallbackInSpan(
|
|
@@ -923,23 +955,104 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
923
955
|
'ProvingOrchestrator.prover.getRootParityProof',
|
|
924
956
|
{
|
|
925
957
|
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
926
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-parity'
|
|
958
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-parity' satisfies CircuitName,
|
|
927
959
|
},
|
|
928
960
|
signal => this.prover.getRootParityProof(inputs, signal, provingState.epochNumber),
|
|
929
961
|
),
|
|
930
|
-
|
|
962
|
+
rootInput => {
|
|
931
963
|
provingState!.finalRootParityInput = rootInput;
|
|
932
|
-
|
|
964
|
+
this.checkAndEnqueueBlockRootRollup(provingState);
|
|
965
|
+
},
|
|
966
|
+
);
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
// Executes the block merge rollup circuit and stored the output as intermediate state for the parent merge/block root circuit
|
|
970
|
+
// Enqueues the next level of merge if all inputs are available
|
|
971
|
+
private enqueueBlockMergeRollup(
|
|
972
|
+
provingState: EpochProvingState,
|
|
973
|
+
level: bigint,
|
|
974
|
+
index: bigint,
|
|
975
|
+
mergeInputData: BlockMergeRollupInputData,
|
|
976
|
+
) {
|
|
977
|
+
const inputs = createBlockMergeRollupInputs(
|
|
978
|
+
[mergeInputData.inputs[0]!, mergeInputData.proofs[0]!, mergeInputData.verificationKeys[0]!],
|
|
979
|
+
[mergeInputData.inputs[1]!, mergeInputData.proofs[1]!, mergeInputData.verificationKeys[1]!],
|
|
980
|
+
);
|
|
981
|
+
|
|
982
|
+
this.deferredProving(
|
|
983
|
+
provingState,
|
|
984
|
+
wrapCallbackInSpan(
|
|
985
|
+
this.tracer,
|
|
986
|
+
'ProvingOrchestrator.prover.getBlockMergeRollupProof',
|
|
987
|
+
{
|
|
988
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
989
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'block-merge-rollup' satisfies CircuitName,
|
|
990
|
+
},
|
|
991
|
+
signal => this.prover.getBlockMergeRollupProof(inputs, signal, provingState.epochNumber),
|
|
992
|
+
),
|
|
993
|
+
result => {
|
|
994
|
+
this.storeAndExecuteNextBlockMergeLevel(provingState, level, index, [
|
|
995
|
+
result.inputs,
|
|
996
|
+
result.proof,
|
|
997
|
+
result.verificationKey.keyAsFields,
|
|
998
|
+
]);
|
|
999
|
+
},
|
|
1000
|
+
);
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
// Executes the root rollup circuit
|
|
1004
|
+
private enqueueRootRollup(provingState: EpochProvingState | undefined) {
|
|
1005
|
+
if (!provingState?.verifyState()) {
|
|
1006
|
+
logger.debug('Not running root rollup, state no longer valid');
|
|
1007
|
+
return;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
logger.debug(`Preparing root rollup`);
|
|
1011
|
+
const mergeInputData = provingState.getMergeInputs(0);
|
|
1012
|
+
|
|
1013
|
+
const inputs = getRootRollupInput(
|
|
1014
|
+
mergeInputData.inputs[0]!,
|
|
1015
|
+
mergeInputData.proofs[0]!,
|
|
1016
|
+
mergeInputData.verificationKeys[0]!,
|
|
1017
|
+
mergeInputData.inputs[1]!,
|
|
1018
|
+
mergeInputData.proofs[1]!,
|
|
1019
|
+
mergeInputData.verificationKeys[1]!,
|
|
1020
|
+
this.proverId,
|
|
1021
|
+
);
|
|
1022
|
+
|
|
1023
|
+
this.deferredProving(
|
|
1024
|
+
provingState,
|
|
1025
|
+
wrapCallbackInSpan(
|
|
1026
|
+
this.tracer,
|
|
1027
|
+
'ProvingOrchestrator.prover.getRootRollupProof',
|
|
1028
|
+
{
|
|
1029
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
1030
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-rollup' satisfies CircuitName,
|
|
1031
|
+
},
|
|
1032
|
+
signal => this.prover.getRootRollupProof(inputs, signal, provingState.epochNumber),
|
|
1033
|
+
),
|
|
1034
|
+
result => {
|
|
1035
|
+
provingState.rootRollupPublicInputs = result.inputs;
|
|
1036
|
+
provingState.finalProof = result.proof.binaryProof;
|
|
1037
|
+
provingState.resolve({ status: PROVING_STATUS.SUCCESS });
|
|
933
1038
|
},
|
|
934
1039
|
);
|
|
935
1040
|
}
|
|
936
1041
|
|
|
937
|
-
private
|
|
1042
|
+
private checkAndEnqueueBlockRootRollup(provingState: BlockProvingState | undefined) {
|
|
938
1043
|
if (!provingState?.isReadyForBlockRootRollup()) {
|
|
939
1044
|
logger.debug('Not ready for root rollup');
|
|
940
1045
|
return;
|
|
941
1046
|
}
|
|
942
|
-
|
|
1047
|
+
this.enqueueBlockRootRollup(provingState);
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
private checkAndEnqueueRootRollup(provingState: EpochProvingState | undefined) {
|
|
1051
|
+
if (!provingState?.isReadyForRootRollup()) {
|
|
1052
|
+
logger.debug('Not ready for root rollup');
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1055
|
+
this.enqueueRootRollup(provingState);
|
|
943
1056
|
}
|
|
944
1057
|
|
|
945
1058
|
/**
|
|
@@ -950,7 +1063,7 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
950
1063
|
* @param mergeInputData - The inputs to be stored
|
|
951
1064
|
*/
|
|
952
1065
|
private storeAndExecuteNextMergeLevel(
|
|
953
|
-
provingState:
|
|
1066
|
+
provingState: BlockProvingState,
|
|
954
1067
|
currentLevel: bigint,
|
|
955
1068
|
currentIndex: bigint,
|
|
956
1069
|
mergeInputData: [
|
|
@@ -959,19 +1072,68 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
959
1072
|
VerificationKeyAsFields,
|
|
960
1073
|
],
|
|
961
1074
|
) {
|
|
962
|
-
const
|
|
1075
|
+
const [mergeLevel, indexWithinMergeLevel, indexWithinMerge] = provingState.findMergeLevel(
|
|
1076
|
+
currentLevel,
|
|
1077
|
+
currentIndex,
|
|
1078
|
+
);
|
|
1079
|
+
const mergeIndex = 2n ** mergeLevel - 1n + indexWithinMergeLevel;
|
|
1080
|
+
const ready = provingState.storeMergeInputs(mergeInputData, Number(indexWithinMerge), Number(mergeIndex));
|
|
1081
|
+
const nextMergeInputData = provingState.getMergeInputs(Number(mergeIndex));
|
|
1082
|
+
|
|
1083
|
+
// Are we ready to execute the next circuit?
|
|
1084
|
+
if (!ready) {
|
|
1085
|
+
return;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
if (mergeLevel === 0n) {
|
|
1089
|
+
this.checkAndEnqueueBlockRootRollup(provingState);
|
|
1090
|
+
} else {
|
|
1091
|
+
// onto the next merge level
|
|
1092
|
+
this.enqueueMergeRollup(provingState, mergeLevel, indexWithinMergeLevel, nextMergeInputData);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
/**
|
|
1097
|
+
* Stores the inputs to a block merge/root circuit and enqueues the circuit if ready
|
|
1098
|
+
* @param provingState - The proving state being operated on
|
|
1099
|
+
* @param currentLevel - The level of the merge/root circuit
|
|
1100
|
+
* @param currentIndex - The index of the merge/root circuit
|
|
1101
|
+
* @param mergeInputData - The inputs to be stored
|
|
1102
|
+
*/
|
|
1103
|
+
private storeAndExecuteNextBlockMergeLevel(
|
|
1104
|
+
provingState: EpochProvingState,
|
|
1105
|
+
currentLevel: bigint,
|
|
1106
|
+
currentIndex: bigint,
|
|
1107
|
+
mergeInputData: [
|
|
1108
|
+
BlockRootOrBlockMergePublicInputs,
|
|
1109
|
+
RecursiveProof<typeof NESTED_RECURSIVE_PROOF_LENGTH>,
|
|
1110
|
+
VerificationKeyAsFields,
|
|
1111
|
+
],
|
|
1112
|
+
) {
|
|
1113
|
+
const [mergeLevel, indexWithinMergeLevel, indexWithinMerge] = provingState.findMergeLevel(
|
|
1114
|
+
currentLevel,
|
|
1115
|
+
currentIndex,
|
|
1116
|
+
);
|
|
1117
|
+
logger.debug(`Computed merge for ${currentLevel}.${currentIndex} as ${mergeLevel}.${indexWithinMergeLevel}`);
|
|
1118
|
+
if (mergeLevel < 0n) {
|
|
1119
|
+
throw new Error(`Invalid merge level ${mergeLevel}`);
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
const mergeIndex = 2n ** mergeLevel - 1n + indexWithinMergeLevel;
|
|
1123
|
+
const ready = provingState.storeMergeInputs(mergeInputData, Number(indexWithinMerge), Number(mergeIndex));
|
|
1124
|
+
const nextMergeInputData = provingState.getMergeInputs(Number(mergeIndex));
|
|
963
1125
|
|
|
964
1126
|
// Are we ready to execute the next circuit?
|
|
965
|
-
if (!
|
|
1127
|
+
if (!ready) {
|
|
1128
|
+
logger.debug(`Not ready to execute next block merge for level ${mergeLevel} index ${indexWithinMergeLevel}`);
|
|
966
1129
|
return;
|
|
967
1130
|
}
|
|
968
1131
|
|
|
969
|
-
if (
|
|
970
|
-
|
|
971
|
-
void this.checkAndEnqueueBlockRootRollup(provingState);
|
|
1132
|
+
if (mergeLevel === 0n) {
|
|
1133
|
+
this.checkAndEnqueueRootRollup(provingState);
|
|
972
1134
|
} else {
|
|
973
1135
|
// onto the next merge level
|
|
974
|
-
this.
|
|
1136
|
+
this.enqueueBlockMergeRollup(provingState, mergeLevel, indexWithinMergeLevel, nextMergeInputData);
|
|
975
1137
|
}
|
|
976
1138
|
}
|
|
977
1139
|
|
|
@@ -982,7 +1144,7 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
982
1144
|
* @param txIndex - The index of the transaction being proven
|
|
983
1145
|
* @param functionIndex - The index of the function/kernel being proven
|
|
984
1146
|
*/
|
|
985
|
-
private enqueueVM(provingState:
|
|
1147
|
+
private enqueueVM(provingState: BlockProvingState | undefined, txIndex: number, functionIndex: number) {
|
|
986
1148
|
if (!provingState?.verifyState()) {
|
|
987
1149
|
logger.debug(`Not running VM circuit as state is no longer valid`);
|
|
988
1150
|
return;
|
|
@@ -1028,13 +1190,11 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
1028
1190
|
logger.debug(`Proven VM for function index ${functionIndex} of tx index ${txIndex}`);
|
|
1029
1191
|
this.checkAndEnqueuePublicKernelFromVMProof(provingState, txIndex, functionIndex, proofAndVk.proof);
|
|
1030
1192
|
});
|
|
1031
|
-
} else {
|
|
1032
|
-
this.checkAndEnqueuePublicKernelFromVMProof(provingState, txIndex, functionIndex, /*vmProof=*/ makeEmptyProof());
|
|
1033
1193
|
}
|
|
1034
1194
|
}
|
|
1035
1195
|
|
|
1036
1196
|
private checkAndEnqueuePublicKernelFromVMProof(
|
|
1037
|
-
provingState:
|
|
1197
|
+
provingState: BlockProvingState,
|
|
1038
1198
|
txIndex: number,
|
|
1039
1199
|
functionIndex: number,
|
|
1040
1200
|
vmProof: Proof,
|
|
@@ -1055,9 +1215,8 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
1055
1215
|
// This could be either a public kernel or the base rollup
|
|
1056
1216
|
// Alternatively, if we are still waiting on a public VM prof then it will continue waiting
|
|
1057
1217
|
private checkAndEnqueueNextTxCircuit(
|
|
1058
|
-
provingState:
|
|
1218
|
+
provingState: BlockProvingState,
|
|
1059
1219
|
txIndex: number,
|
|
1060
|
-
completedFunctionIndex: number,
|
|
1061
1220
|
proof: RecursiveProof<typeof NESTED_RECURSIVE_PROOF_LENGTH> | RecursiveProof<typeof TUBE_PROOF_LENGTH>,
|
|
1062
1221
|
verificationKey: VerificationKeyData,
|
|
1063
1222
|
nextKernelRequest: TxProvingInstruction,
|
|
@@ -1089,7 +1248,7 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
1089
1248
|
throw new Error(`Error occurred, public function request undefined after kernel proof completed`);
|
|
1090
1249
|
}
|
|
1091
1250
|
|
|
1092
|
-
this.enqueuePublicKernel(provingState, txIndex,
|
|
1251
|
+
this.enqueuePublicKernel(provingState, txIndex, nextKernelRequest.functionIndex!);
|
|
1093
1252
|
}
|
|
1094
1253
|
|
|
1095
1254
|
/**
|
|
@@ -1099,7 +1258,7 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
1099
1258
|
* @param txIndex - The index of the transaction being proven
|
|
1100
1259
|
* @param functionIndex - The index of the function/kernel being proven
|
|
1101
1260
|
*/
|
|
1102
|
-
private enqueuePublicKernel(provingState:
|
|
1261
|
+
private enqueuePublicKernel(provingState: BlockProvingState | undefined, txIndex: number, functionIndex: number) {
|
|
1103
1262
|
if (!provingState?.verifyState()) {
|
|
1104
1263
|
logger.debug(`Not running public kernel circuit as state is no longer valid`);
|
|
1105
1264
|
return;
|
|
@@ -1112,20 +1271,28 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
1112
1271
|
provingState,
|
|
1113
1272
|
wrapCallbackInSpan(
|
|
1114
1273
|
this.tracer,
|
|
1115
|
-
request.type ===
|
|
1274
|
+
request.type === ProvingRequestType.PUBLIC_KERNEL_TAIL
|
|
1116
1275
|
? 'ProvingOrchestrator.prover.getPublicTailProof'
|
|
1117
|
-
:
|
|
1276
|
+
: request.type === ProvingRequestType.PUBLIC_KERNEL_MERGE
|
|
1277
|
+
? 'ProvingOrchestrator.prover.getPublicKernelMergeProof'
|
|
1278
|
+
: 'ProvingOrchestrator.prover.getPublicKernelInnerProof',
|
|
1118
1279
|
{
|
|
1119
1280
|
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
1120
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]:
|
|
1281
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: mapProvingRequestTypeToCircuitName(request.type),
|
|
1121
1282
|
},
|
|
1122
1283
|
(
|
|
1123
1284
|
signal,
|
|
1124
|
-
): Promise<
|
|
1125
|
-
|
|
1126
|
-
|
|
1285
|
+
): Promise<
|
|
1286
|
+
PublicInputsAndRecursiveProof<
|
|
1287
|
+
KernelCircuitPublicInputs | PublicKernelCircuitPublicInputs | VMCircuitPublicInputs
|
|
1288
|
+
>
|
|
1289
|
+
> => {
|
|
1290
|
+
if (request.type === ProvingRequestType.PUBLIC_KERNEL_TAIL) {
|
|
1291
|
+
return this.prover.getPublicTailProof(request.inputs, signal, provingState.epochNumber);
|
|
1292
|
+
} else if (request.type === ProvingRequestType.PUBLIC_KERNEL_MERGE) {
|
|
1293
|
+
return this.prover.getPublicKernelMergeProof(request.inputs, signal, provingState.epochNumber);
|
|
1127
1294
|
} else {
|
|
1128
|
-
return this.prover.
|
|
1295
|
+
return this.prover.getPublicKernelInnerProof(request.inputs, signal, provingState.epochNumber);
|
|
1129
1296
|
}
|
|
1130
1297
|
},
|
|
1131
1298
|
),
|
|
@@ -1138,7 +1305,6 @@ export class ProvingOrchestrator implements BlockProver {
|
|
|
1138
1305
|
this.checkAndEnqueueNextTxCircuit(
|
|
1139
1306
|
provingState,
|
|
1140
1307
|
txIndex,
|
|
1141
|
-
functionIndex,
|
|
1142
1308
|
result.proof,
|
|
1143
1309
|
result.verificationKey,
|
|
1144
1310
|
nextKernelRequest,
|