@aztec/prover-client 0.0.1-commit.6d3c34e → 0.0.1-commit.7035c9bd6

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.
Files changed (92) hide show
  1. package/dest/light/lightweight_checkpoint_builder.d.ts +16 -7
  2. package/dest/light/lightweight_checkpoint_builder.d.ts.map +1 -1
  3. package/dest/light/lightweight_checkpoint_builder.js +64 -24
  4. package/dest/mocks/fixtures.d.ts +1 -1
  5. package/dest/mocks/fixtures.d.ts.map +1 -1
  6. package/dest/mocks/fixtures.js +2 -1
  7. package/dest/mocks/test_context.d.ts +3 -2
  8. package/dest/mocks/test_context.d.ts.map +1 -1
  9. package/dest/mocks/test_context.js +11 -3
  10. package/dest/orchestrator/block-building-helpers.d.ts +5 -5
  11. package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
  12. package/dest/orchestrator/block-building-helpers.js +3 -3
  13. package/dest/orchestrator/block-proving-state.d.ts +4 -1
  14. package/dest/orchestrator/block-proving-state.d.ts.map +1 -1
  15. package/dest/orchestrator/block-proving-state.js +7 -0
  16. package/dest/orchestrator/checkpoint-proving-state.d.ts +17 -4
  17. package/dest/orchestrator/checkpoint-proving-state.d.ts.map +1 -1
  18. package/dest/orchestrator/checkpoint-proving-state.js +37 -4
  19. package/dest/orchestrator/epoch-proving-state.d.ts +7 -6
  20. package/dest/orchestrator/epoch-proving-state.d.ts.map +1 -1
  21. package/dest/orchestrator/epoch-proving-state.js +37 -1
  22. package/dest/orchestrator/orchestrator.d.ts +20 -3
  23. package/dest/orchestrator/orchestrator.d.ts.map +1 -1
  24. package/dest/orchestrator/orchestrator.js +148 -99
  25. package/dest/prover-client/prover-client.d.ts +4 -4
  26. package/dest/prover-client/prover-client.d.ts.map +1 -1
  27. package/dest/prover-client/prover-client.js +15 -10
  28. package/dest/proving_broker/broker_prover_facade.d.ts +4 -3
  29. package/dest/proving_broker/broker_prover_facade.d.ts.map +1 -1
  30. package/dest/proving_broker/broker_prover_facade.js +6 -6
  31. package/dest/proving_broker/config.d.ts +14 -2
  32. package/dest/proving_broker/config.d.ts.map +1 -1
  33. package/dest/proving_broker/config.js +20 -3
  34. package/dest/proving_broker/proof_store/factory.d.ts +2 -5
  35. package/dest/proving_broker/proof_store/factory.d.ts.map +1 -1
  36. package/dest/proving_broker/proof_store/factory.js +7 -30
  37. package/dest/proving_broker/proof_store/file_store_proof_store.d.ts +18 -0
  38. package/dest/proving_broker/proof_store/file_store_proof_store.d.ts.map +1 -0
  39. package/dest/proving_broker/proof_store/file_store_proof_store.js +60 -0
  40. package/dest/proving_broker/proof_store/index.d.ts +2 -2
  41. package/dest/proving_broker/proof_store/index.d.ts.map +1 -1
  42. package/dest/proving_broker/proof_store/index.js +1 -1
  43. package/dest/proving_broker/proving_agent.d.ts +4 -3
  44. package/dest/proving_broker/proving_agent.d.ts.map +1 -1
  45. package/dest/proving_broker/proving_agent.js +4 -4
  46. package/dest/proving_broker/proving_broker.d.ts +7 -4
  47. package/dest/proving_broker/proving_broker.d.ts.map +1 -1
  48. package/dest/proving_broker/proving_broker.js +36 -4
  49. package/dest/proving_broker/proving_broker_instrumentation.d.ts +3 -1
  50. package/dest/proving_broker/proving_broker_instrumentation.d.ts.map +1 -1
  51. package/dest/proving_broker/proving_broker_instrumentation.js +18 -7
  52. package/dest/proving_broker/proving_job_controller.d.ts +4 -3
  53. package/dest/proving_broker/proving_job_controller.d.ts.map +1 -1
  54. package/dest/proving_broker/proving_job_controller.js +6 -3
  55. package/dest/proving_broker/rpc.d.ts +4 -2
  56. package/dest/proving_broker/rpc.d.ts.map +1 -1
  57. package/dest/proving_broker/rpc.js +8 -0
  58. package/dest/test/mock_proof_store.d.ts +3 -3
  59. package/dest/test/mock_proof_store.d.ts.map +1 -1
  60. package/dest/test/mock_prover.d.ts +4 -4
  61. package/package.json +18 -20
  62. package/src/light/lightweight_checkpoint_builder.ts +93 -30
  63. package/src/mocks/fixtures.ts +2 -1
  64. package/src/mocks/test_context.ts +8 -3
  65. package/src/orchestrator/block-building-helpers.ts +3 -3
  66. package/src/orchestrator/block-proving-state.ts +9 -0
  67. package/src/orchestrator/checkpoint-proving-state.ts +51 -5
  68. package/src/orchestrator/epoch-proving-state.ts +59 -9
  69. package/src/orchestrator/orchestrator.ts +158 -108
  70. package/src/prover-client/prover-client.ts +31 -15
  71. package/src/proving_broker/broker_prover_facade.ts +15 -7
  72. package/src/proving_broker/config.ts +23 -1
  73. package/src/proving_broker/proof_store/factory.ts +10 -32
  74. package/src/proving_broker/proof_store/file_store_proof_store.ts +78 -0
  75. package/src/proving_broker/proof_store/index.ts +1 -1
  76. package/src/proving_broker/proving_agent.ts +5 -2
  77. package/src/proving_broker/proving_broker.ts +37 -3
  78. package/src/proving_broker/proving_broker_instrumentation.ts +19 -6
  79. package/src/proving_broker/proving_job_controller.ts +9 -3
  80. package/src/proving_broker/rpc.ts +14 -0
  81. package/dest/block-factory/index.d.ts +0 -2
  82. package/dest/block-factory/index.d.ts.map +0 -1
  83. package/dest/block-factory/index.js +0 -1
  84. package/dest/block-factory/light.d.ts +0 -38
  85. package/dest/block-factory/light.d.ts.map +0 -1
  86. package/dest/block-factory/light.js +0 -106
  87. package/dest/proving_broker/proof_store/gcs_proof_store.d.ts +0 -14
  88. package/dest/proving_broker/proof_store/gcs_proof_store.d.ts.map +0 -1
  89. package/dest/proving_broker/proof_store/gcs_proof_store.js +0 -52
  90. package/src/block-factory/index.ts +0 -1
  91. package/src/block-factory/light.ts +0 -136
  92. package/src/proving_broker/proof_store/gcs_proof_store.ts +0 -76
@@ -10,9 +10,11 @@ import { BlockNumber, EpochNumber } from '@aztec/foundation/branded-types';
10
10
  import { padArrayEnd } from '@aztec/foundation/collection';
11
11
  import { Fr } from '@aztec/foundation/curves/bn254';
12
12
  import { AbortError } from '@aztec/foundation/error';
13
- import { createLogger } from '@aztec/foundation/log';
13
+ import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
14
14
  import { promiseWithResolvers } from '@aztec/foundation/promise';
15
+ import { SerialQueue } from '@aztec/foundation/queue';
15
16
  import { assertLength } from '@aztec/foundation/serialize';
17
+ import { sleep } from '@aztec/foundation/sleep';
16
18
  import { pushTestData } from '@aztec/foundation/testing';
17
19
  import { elapsed } from '@aztec/foundation/timer';
18
20
  import type { TreeNodeLocation } from '@aztec/foundation/trees';
@@ -71,8 +73,6 @@ import { EpochProvingState, type ProvingResult, type TreeSnapshots } from './epo
71
73
  import { ProvingOrchestratorMetrics } from './orchestrator_metrics.js';
72
74
  import { TxProvingState } from './tx-proving-state.js';
73
75
 
74
- const logger = createLogger('prover-client:orchestrator');
75
-
76
76
  /**
77
77
  * Implements an event driven proving scheduler to build the recursive proof tree. The idea being:
78
78
  * 1. Transactions are provided to the scheduler post simulation.
@@ -95,14 +95,21 @@ export class ProvingOrchestrator implements EpochProver {
95
95
  private metrics: ProvingOrchestratorMetrics;
96
96
  // eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
97
97
  private dbs: Map<BlockNumber, MerkleTreeWriteOperations> = new Map();
98
+ private logger: Logger;
99
+ private deferredJobQueue = new SerialQueue();
98
100
 
99
101
  constructor(
100
102
  private dbProvider: ReadonlyWorldStateAccess & ForkMerkleTreeOperations,
101
103
  private prover: ServerCircuitProver,
102
104
  private readonly proverId: EthAddress,
105
+ private readonly cancelJobsOnStop: boolean = false,
106
+ private readonly enqueueConcurrency: number,
103
107
  telemetryClient: TelemetryClient = getTelemetryClient(),
108
+ bindings?: LoggerBindings,
104
109
  ) {
110
+ this.logger = createLogger('prover-client:orchestrator', bindings);
105
111
  this.metrics = new ProvingOrchestratorMetrics(telemetryClient, 'ProvingOrchestrator');
112
+ this.deferredJobQueue.start(this.enqueueConcurrency);
106
113
  }
107
114
 
108
115
  get tracer(): Tracer {
@@ -113,9 +120,15 @@ export class ProvingOrchestrator implements EpochProver {
113
120
  return this.proverId;
114
121
  }
115
122
 
116
- public stop(): Promise<void> {
123
+ public getNumActiveForks() {
124
+ return this.dbs.size;
125
+ }
126
+
127
+ public async stop(): Promise<void> {
128
+ // Grab the old queue before cancel() replaces it, so we can await its draining.
129
+ const oldQueue = this.deferredJobQueue;
117
130
  this.cancel();
118
- return Promise.resolve();
131
+ await oldQueue.cancel();
119
132
  }
120
133
 
121
134
  public startNewEpoch(
@@ -131,7 +144,7 @@ export class ProvingOrchestrator implements EpochProver {
131
144
 
132
145
  const { promise: _promise, resolve, reject } = promiseWithResolvers<ProvingResult>();
133
146
  const promise = _promise.catch((reason): ProvingResult => ({ status: 'failure', reason }));
134
- logger.info(`Starting epoch ${epochNumber} with ${totalNumCheckpoints} checkpoints.`);
147
+ this.logger.info(`Starting epoch ${epochNumber} with ${totalNumCheckpoints} checkpoints.`);
135
148
  this.provingState = new EpochProvingState(
136
149
  epochNumber,
137
150
  totalNumCheckpoints,
@@ -143,6 +156,14 @@ export class ProvingOrchestrator implements EpochProver {
143
156
  this.provingPromise = promise;
144
157
  }
145
158
 
159
+ /**
160
+ * Starts a new checkpoint.
161
+ * @param checkpointIndex - The index of the checkpoint in the epoch.
162
+ * @param constants - The constants for this checkpoint.
163
+ * @param l1ToL2Messages - The set of L1 to L2 messages to be inserted at the beginning of this checkpoint.
164
+ * @param totalNumBlocks - The total number of blocks expected in the checkpoint (must be at least one).
165
+ * @param headerOfLastBlockInPreviousCheckpoint - The header of the last block in the previous checkpoint.
166
+ */
146
167
  public async startNewCheckpoint(
147
168
  checkpointIndex: number,
148
169
  constants: CheckpointConstantData,
@@ -215,7 +236,7 @@ export class ProvingOrchestrator implements EpochProver {
215
236
  }
216
237
 
217
238
  const constants = checkpointProvingState.constants;
218
- logger.info(`Starting block ${blockNumber} for slot ${constants.slotNumber}.`);
239
+ this.logger.info(`Starting block ${blockNumber} for slot ${constants.slotNumber}.`);
219
240
 
220
241
  // Fork the db only when it's not already set. The db for the first block is set in `startNewCheckpoint`.
221
242
  if (!this.dbs.has(blockNumber)) {
@@ -223,7 +244,7 @@ export class ProvingOrchestrator implements EpochProver {
223
244
  const db = await this.dbProvider.fork(BlockNumber(blockNumber - 1));
224
245
  this.dbs.set(blockNumber, db);
225
246
  }
226
- const db = this.dbs.get(blockNumber)!;
247
+ const db = this.getDbForBlock(blockNumber);
227
248
 
228
249
  // Get archive snapshot and sibling path before any txs in this block lands.
229
250
  const lastArchiveTreeSnapshot = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
@@ -255,7 +276,8 @@ export class ProvingOrchestrator implements EpochProver {
255
276
  await endSpongeBlob.absorb(blockEndBlobFields);
256
277
  blockProvingState.setEndSpongeBlob(endSpongeBlob);
257
278
 
258
- // And also try to accumulate the blobs as far as we can:
279
+ // Try to accumulate the out hashes and blobs as far as we can:
280
+ await this.provingState.accumulateCheckpointOutHashes();
259
281
  await this.provingState.setBlobAccumulators();
260
282
  }
261
283
  }
@@ -275,7 +297,7 @@ export class ProvingOrchestrator implements EpochProver {
275
297
  if (!txs.length) {
276
298
  // To avoid an ugly throw below. If we require an empty block, we can just call setBlockCompleted
277
299
  // on a block with no txs. We cannot do that here because we cannot find the blockNumber without any txs.
278
- logger.warn(`Provided no txs to orchestrator addTxs.`);
300
+ this.logger.warn(`Provided no txs to orchestrator addTxs.`);
279
301
  return;
280
302
  }
281
303
 
@@ -295,9 +317,9 @@ export class ProvingOrchestrator implements EpochProver {
295
317
  throw new Error(`Block ${blockNumber} has been initialized with transactions.`);
296
318
  }
297
319
 
298
- logger.info(`Adding ${txs.length} transactions to block ${blockNumber}`);
320
+ this.logger.info(`Adding ${txs.length} transactions to block ${blockNumber}`);
299
321
 
300
- const db = this.dbs.get(blockNumber)!;
322
+ const db = this.getDbForBlock(blockNumber);
301
323
  const lastArchive = provingState.lastArchiveTreeSnapshot;
302
324
  const newL1ToL2MessageTreeSnapshot = provingState.newL1ToL2MessageTreeSnapshot;
303
325
  const spongeBlobState = provingState.getStartSpongeBlob().clone();
@@ -310,7 +332,7 @@ export class ProvingOrchestrator implements EpochProver {
310
332
 
311
333
  validateTx(tx);
312
334
 
313
- logger.debug(`Received transaction: ${tx.hash}`);
335
+ this.logger.debug(`Received transaction: ${tx.hash}`);
314
336
 
315
337
  const startSpongeBlob = spongeBlobState.clone();
316
338
  const [hints, treeSnapshots] = await this.prepareBaseRollupInputs(
@@ -331,10 +353,10 @@ export class ProvingOrchestrator implements EpochProver {
331
353
  const txIndex = provingState.addNewTx(txProvingState);
332
354
  if (txProvingState.requireAvmProof) {
333
355
  this.getOrEnqueueChonkVerifier(provingState, txIndex);
334
- logger.debug(`Enqueueing public VM for tx ${txIndex}`);
356
+ this.logger.debug(`Enqueueing public VM for tx ${txIndex}`);
335
357
  this.enqueueVM(provingState, txIndex);
336
358
  } else {
337
- logger.debug(`Enqueueing base rollup for private-only tx ${txIndex}`);
359
+ this.logger.debug(`Enqueueing base rollup for private-only tx ${txIndex}`);
338
360
  this.enqueueBaseRollup(provingState, txIndex);
339
361
  }
340
362
  } catch (err: any) {
@@ -352,7 +374,8 @@ export class ProvingOrchestrator implements EpochProver {
352
374
 
353
375
  provingState.setEndSpongeBlob(spongeBlobState);
354
376
 
355
- // Txs have been added to the block. Now try to accumulate the blobs as far as we can:
377
+ // Txs have been added to the block. Now try to accumulate the out hashes and blobs as far as we can:
378
+ await this.provingState.accumulateCheckpointOutHashes();
356
379
  await this.provingState.setBlobAccumulators();
357
380
  }
358
381
 
@@ -376,7 +399,7 @@ export class ProvingOrchestrator implements EpochProver {
376
399
  typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH
377
400
  >
378
401
  >();
379
- logger.debug(`Starting chonk verifier circuit for tx ${txHash}`);
402
+ this.logger.debug(`Starting chonk verifier circuit for tx ${txHash}`);
380
403
  this.doEnqueueChonkVerifier(txHash, privateInputs, proof => {
381
404
  tubeProof.resolve(proof);
382
405
  });
@@ -416,22 +439,28 @@ export class ProvingOrchestrator implements EpochProver {
416
439
  }
417
440
 
418
441
  // Given we've applied every change from this block, now assemble the block header:
419
- logger.verbose(`Block ${blockNumber} completed. Assembling header.`);
442
+ this.logger.verbose(`Block ${blockNumber} completed. Assembling header.`);
420
443
  const header = await provingState.buildBlockHeader();
421
444
 
422
445
  if (expectedHeader && !header.equals(expectedHeader)) {
423
- logger.error(`Block header mismatch: header=${header} expectedHeader=${expectedHeader}`);
446
+ this.logger.error(`Block header mismatch: header=${header} expectedHeader=${expectedHeader}`);
424
447
  throw new Error('Block header mismatch');
425
448
  }
426
449
 
427
- // Get db for this block
428
- const db = this.dbs.get(provingState.blockNumber)!;
450
+ // Get db for this block and remove from map — no other code should use it after this point.
451
+ const db = this.getDbForBlock(provingState.blockNumber);
452
+ this.dbs.delete(provingState.blockNumber);
429
453
 
430
- // Update the archive tree, so we're ready to start processing the next block:
431
- logger.verbose(
432
- `Updating archive tree with block ${provingState.blockNumber} header ${(await header.hash()).toString()}`,
433
- );
434
- await db.updateArchive(header);
454
+ // Update the archive tree, capture the snapshot, and close the fork deterministically.
455
+ try {
456
+ this.logger.verbose(
457
+ `Updating archive tree with block ${provingState.blockNumber} header ${(await header.hash()).toString()}`,
458
+ );
459
+ await db.updateArchive(header);
460
+ provingState.setBuiltArchive(await getTreeSnapshot(MerkleTreeId.ARCHIVE, db));
461
+ } finally {
462
+ await db.close();
463
+ }
435
464
 
436
465
  await this.verifyBuiltBlockAgainstSyncedState(provingState);
437
466
 
@@ -442,31 +471,34 @@ export class ProvingOrchestrator implements EpochProver {
442
471
  protected async verifyBuiltBlockAgainstSyncedState(provingState: BlockProvingState) {
443
472
  const builtBlockHeader = provingState.getBuiltBlockHeader();
444
473
  if (!builtBlockHeader) {
445
- logger.debug('Block header not built yet, skipping header check.');
474
+ this.logger.debug('Block header not built yet, skipping header check.');
446
475
  return;
447
476
  }
448
477
 
449
478
  const output = provingState.getBlockRootRollupOutput();
450
479
  if (!output) {
451
- logger.debug('Block root rollup proof not built yet, skipping header check.');
480
+ this.logger.debug('Block root rollup proof not built yet, skipping header check.');
481
+ return;
482
+ }
483
+
484
+ const newArchive = provingState.getBuiltArchive();
485
+ if (!newArchive) {
486
+ this.logger.debug('Archive snapshot not yet captured, skipping header check.');
452
487
  return;
453
488
  }
489
+
454
490
  const header = await buildHeaderFromCircuitOutputs(output);
455
491
 
456
492
  if (!(await header.hash()).equals(await builtBlockHeader.hash())) {
457
- logger.error(`Block header mismatch.\nCircuit: ${inspect(header)}\nComputed: ${inspect(builtBlockHeader)}`);
493
+ this.logger.error(`Block header mismatch.\nCircuit: ${inspect(header)}\nComputed: ${inspect(builtBlockHeader)}`);
458
494
  provingState.reject(`Block header hash mismatch.`);
459
495
  return;
460
496
  }
461
497
 
462
- // Get db for this block
463
498
  const blockNumber = provingState.blockNumber;
464
- const db = this.dbs.get(blockNumber)!;
465
-
466
- const newArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
467
499
  const syncedArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, this.dbProvider.getSnapshot(blockNumber));
468
500
  if (!syncedArchive.equals(newArchive)) {
469
- logger.error(
501
+ this.logger.error(
470
502
  `Archive tree mismatch for block ${blockNumber}: world state synced to ${inspect(
471
503
  syncedArchive,
472
504
  )} but built ${inspect(newArchive)}`,
@@ -477,32 +509,43 @@ export class ProvingOrchestrator implements EpochProver {
477
509
 
478
510
  const circuitArchive = output.newArchive;
479
511
  if (!newArchive.equals(circuitArchive)) {
480
- logger.error(`New archive mismatch.\nCircuit: ${output.newArchive}\nComputed: ${newArchive}`);
512
+ this.logger.error(`New archive mismatch.\nCircuit: ${output.newArchive}\nComputed: ${newArchive}`);
481
513
  provingState.reject(`New archive mismatch.`);
482
514
  return;
483
515
  }
484
-
485
- // TODO(palla/prover): This closes the fork only on the happy path. If this epoch orchestrator
486
- // is aborted and never reaches this point, it will leak the fork. We need to add a global cleanup,
487
- // but have to make sure it only runs once all operations are completed, otherwise some function here
488
- // will attempt to access the fork after it was closed.
489
- logger.debug(`Cleaning up world state fork for ${blockNumber}`);
490
- void this.dbs
491
- .get(blockNumber)
492
- ?.close()
493
- .then(() => this.dbs.delete(blockNumber))
494
- .catch(err => logger.error(`Error closing db for block ${blockNumber}`, err));
495
516
  }
496
517
 
497
518
  /**
498
- * Cancel any further proving
519
+ * Cancel any further proving.
520
+ * If cancelJobsOnStop is true, aborts all pending jobs with the broker (which marks them as 'Aborted').
521
+ * If cancelJobsOnStop is false (default), jobs remain in the broker queue and can be reused on restart/reorg.
499
522
  */
500
523
  public cancel() {
501
- for (const controller of this.pendingProvingJobs) {
502
- controller.abort();
524
+ void this.deferredJobQueue.cancel();
525
+ // Recreate the queue so it can accept jobs for subsequent epochs.
526
+ this.deferredJobQueue = new SerialQueue();
527
+ this.deferredJobQueue.start(this.enqueueConcurrency);
528
+
529
+ if (this.cancelJobsOnStop) {
530
+ for (const controller of this.pendingProvingJobs) {
531
+ controller.abort();
532
+ }
503
533
  }
504
534
 
505
535
  this.provingState?.cancel();
536
+
537
+ for (const [blockNumber, db] of this.dbs.entries()) {
538
+ void db.close().catch(err => this.logger.error(`Error closing db for block ${blockNumber}`, err));
539
+ }
540
+ this.dbs.clear();
541
+ }
542
+
543
+ private getDbForBlock(blockNumber: BlockNumber): MerkleTreeWriteOperations {
544
+ const db = this.dbs.get(blockNumber);
545
+ if (!db) {
546
+ throw new Error(`World state fork for block ${blockNumber} not found.`);
547
+ }
548
+ return db;
506
549
  }
507
550
 
508
551
  /**
@@ -546,7 +589,7 @@ export class ProvingOrchestrator implements EpochProver {
546
589
  callback: (result: T) => void | Promise<void>,
547
590
  ) {
548
591
  if (!provingState.verifyState()) {
549
- logger.debug(`Not enqueuing job, state no longer valid`);
592
+ this.logger.debug(`Not enqueuing job, state no longer valid`);
550
593
  return;
551
594
  }
552
595
 
@@ -564,7 +607,7 @@ export class ProvingOrchestrator implements EpochProver {
564
607
 
565
608
  const result = await request(controller.signal);
566
609
  if (!provingState.verifyState()) {
567
- logger.debug(`State no longer valid, discarding result`);
610
+ this.logger.debug(`State no longer valid, discarding result`);
568
611
  return;
569
612
  }
570
613
 
@@ -582,7 +625,7 @@ export class ProvingOrchestrator implements EpochProver {
582
625
  return;
583
626
  }
584
627
 
585
- logger.error(`Error thrown when proving job`, err);
628
+ this.logger.error(`Error thrown when proving job`, err);
586
629
  provingState!.reject(`${err}`);
587
630
  } finally {
588
631
  const index = this.pendingProvingJobs.indexOf(controller);
@@ -592,8 +635,11 @@ export class ProvingOrchestrator implements EpochProver {
592
635
  }
593
636
  };
594
637
 
595
- // let the callstack unwind before adding the job to the queue
596
- setImmediate(() => void safeJob());
638
+ void this.deferredJobQueue.put(async () => {
639
+ void safeJob();
640
+ // we yield here to the macro task queue such to give Nodejs a chance to run other operatoins in between enqueues
641
+ await sleep(0);
642
+ });
597
643
  }
598
644
 
599
645
  private async updateL1ToL2MessageTree(l1ToL2Messages: Fr[], db: MerkleTreeWriteOperations) {
@@ -667,12 +713,12 @@ export class ProvingOrchestrator implements EpochProver {
667
713
  // Executes the next level of merge if all inputs are available
668
714
  private enqueueBaseRollup(provingState: BlockProvingState, txIndex: number) {
669
715
  if (!provingState.verifyState()) {
670
- logger.debug('Not running base rollup, state invalid');
716
+ this.logger.debug('Not running base rollup, state invalid');
671
717
  return;
672
718
  }
673
719
 
674
720
  if (!provingState.tryStartProvingBase(txIndex)) {
675
- logger.debug(`Base rollup for tx ${txIndex} already started.`);
721
+ this.logger.debug(`Base rollup for tx ${txIndex} already started.`);
676
722
  return;
677
723
  }
678
724
 
@@ -680,7 +726,7 @@ export class ProvingOrchestrator implements EpochProver {
680
726
  const { processedTx } = txProvingState;
681
727
  const { rollupType, inputs } = txProvingState.getBaseRollupTypeAndInputs();
682
728
 
683
- logger.debug(`Enqueuing deferred proving base rollup for ${processedTx.hash.toString()}`);
729
+ this.logger.debug(`Enqueuing deferred proving base rollup for ${processedTx.hash.toString()}`);
684
730
 
685
731
  this.deferredProving(
686
732
  provingState,
@@ -704,7 +750,7 @@ export class ProvingOrchestrator implements EpochProver {
704
750
  },
705
751
  ),
706
752
  result => {
707
- logger.debug(`Completed proof for ${rollupType} for tx ${processedTx.hash.toString()}`);
753
+ this.logger.debug(`Completed proof for ${rollupType} for tx ${processedTx.hash.toString()}`);
708
754
  validatePartialState(result.inputs.endTreeSnapshots, txProvingState.treeSnapshots);
709
755
  const leafLocation = provingState.setBaseRollupProof(txIndex, result);
710
756
  if (provingState.totalNumTxs === 1) {
@@ -720,7 +766,7 @@ export class ProvingOrchestrator implements EpochProver {
720
766
  // Once completed, will enqueue the the public tx base rollup.
721
767
  private getOrEnqueueChonkVerifier(provingState: BlockProvingState, txIndex: number) {
722
768
  if (!provingState.verifyState()) {
723
- logger.debug('Not running chonk verifier circuit, state invalid');
769
+ this.logger.debug('Not running chonk verifier circuit, state invalid');
724
770
  return;
725
771
  }
726
772
 
@@ -733,19 +779,19 @@ export class ProvingOrchestrator implements EpochProver {
733
779
  typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH
734
780
  >,
735
781
  ) => {
736
- logger.debug(`Got chonk verifier proof for tx index: ${txIndex}`, { txHash });
782
+ this.logger.debug(`Got chonk verifier proof for tx index: ${txIndex}`, { txHash });
737
783
  txProvingState.setPublicChonkVerifierProof(result);
738
784
  this.provingState?.cachedChonkVerifierProofs.delete(txHash);
739
785
  this.checkAndEnqueueBaseRollup(provingState, txIndex);
740
786
  };
741
787
 
742
788
  if (this.provingState?.cachedChonkVerifierProofs.has(txHash)) {
743
- logger.debug(`Chonk verifier proof already enqueued for tx index: ${txIndex}`, { txHash });
789
+ this.logger.debug(`Chonk verifier proof already enqueued for tx index: ${txIndex}`, { txHash });
744
790
  void this.provingState!.cachedChonkVerifierProofs.get(txHash)!.then(handleResult);
745
791
  return;
746
792
  }
747
793
 
748
- logger.debug(`Enqueuing chonk verifier circuit for tx index: ${txIndex}`);
794
+ this.logger.debug(`Enqueuing chonk verifier circuit for tx index: ${txIndex}`);
749
795
  this.doEnqueueChonkVerifier(txHash, txProvingState.getPublicChonkVerifierPrivateInputs(), handleResult);
750
796
  }
751
797
 
@@ -761,7 +807,7 @@ export class ProvingOrchestrator implements EpochProver {
761
807
  provingState: EpochProvingState | BlockProvingState = this.provingState!,
762
808
  ) {
763
809
  if (!provingState.verifyState()) {
764
- logger.debug('Not running chonk verifier circuit, state invalid');
810
+ this.logger.debug('Not running chonk verifier circuit, state invalid');
765
811
  return;
766
812
  }
767
813
 
@@ -784,12 +830,12 @@ export class ProvingOrchestrator implements EpochProver {
784
830
  // Enqueues the next level of merge if all inputs are available
785
831
  private enqueueMergeRollup(provingState: BlockProvingState, location: TreeNodeLocation) {
786
832
  if (!provingState.verifyState()) {
787
- logger.debug('Not running merge rollup. State no longer valid.');
833
+ this.logger.debug('Not running merge rollup. State no longer valid.');
788
834
  return;
789
835
  }
790
836
 
791
837
  if (!provingState.tryStartProvingMerge(location)) {
792
- logger.debug('Merge rollup already started.');
838
+ this.logger.debug('Merge rollup already started.');
793
839
  return;
794
840
  }
795
841
 
@@ -815,18 +861,18 @@ export class ProvingOrchestrator implements EpochProver {
815
861
  // Executes the block root rollup circuit
816
862
  private enqueueBlockRootRollup(provingState: BlockProvingState) {
817
863
  if (!provingState.verifyState()) {
818
- logger.debug('Not running block root rollup, state no longer valid');
864
+ this.logger.debug('Not running block root rollup, state no longer valid');
819
865
  return;
820
866
  }
821
867
 
822
868
  if (!provingState.tryStartProvingBlockRoot()) {
823
- logger.debug('Block root rollup already started.');
869
+ this.logger.debug('Block root rollup already started.');
824
870
  return;
825
871
  }
826
872
 
827
873
  const { rollupType, inputs } = provingState.getBlockRootRollupTypeAndInputs();
828
874
 
829
- logger.debug(`Enqueuing ${rollupType} for block ${provingState.blockNumber}.`);
875
+ this.logger.debug(`Enqueuing ${rollupType} for block ${provingState.blockNumber}.`);
830
876
 
831
877
  this.deferredProving(
832
878
  provingState,
@@ -851,18 +897,19 @@ export class ProvingOrchestrator implements EpochProver {
851
897
  },
852
898
  ),
853
899
  async result => {
854
- // If the proofs were slower than the block header building, then we need to try validating the block header hashes here.
855
- await this.verifyBuiltBlockAgainstSyncedState(provingState);
856
-
857
- logger.debug(`Completed ${rollupType} proof for block ${provingState.blockNumber}`);
900
+ this.logger.debug(`Completed ${rollupType} proof for block ${provingState.blockNumber}`);
858
901
 
859
902
  const leafLocation = provingState.setBlockRootRollupProof(result);
860
903
  const checkpointProvingState = provingState.parentCheckpoint;
861
904
 
905
+ // Verification is called from both here and setBlockCompleted. Whichever runs last
906
+ // will be the first to see all three pieces (header, proof output, archive) and run the checks.
907
+ await this.verifyBuiltBlockAgainstSyncedState(provingState);
908
+
862
909
  if (checkpointProvingState.totalNumBlocks === 1) {
863
- this.checkAndEnqueueCheckpointRootRollup(checkpointProvingState);
910
+ await this.checkAndEnqueueCheckpointRootRollup(checkpointProvingState);
864
911
  } else {
865
- this.checkAndEnqueueNextBlockMergeRollup(checkpointProvingState, leafLocation);
912
+ await this.checkAndEnqueueNextBlockMergeRollup(checkpointProvingState, leafLocation);
866
913
  }
867
914
  },
868
915
  );
@@ -876,12 +923,12 @@ export class ProvingOrchestrator implements EpochProver {
876
923
  baseParityIndex: number,
877
924
  ) {
878
925
  if (!provingState.verifyState()) {
879
- logger.debug('Not running base parity. State no longer valid.');
926
+ this.logger.debug('Not running base parity. State no longer valid.');
880
927
  return;
881
928
  }
882
929
 
883
930
  if (!provingState.tryStartProvingBaseParity(baseParityIndex)) {
884
- logger.warn(`Base parity ${baseParityIndex} already started.`);
931
+ this.logger.warn(`Base parity ${baseParityIndex} already started.`);
885
932
  return;
886
933
  }
887
934
 
@@ -916,12 +963,12 @@ export class ProvingOrchestrator implements EpochProver {
916
963
  // Enqueues the root rollup proof if all inputs are available
917
964
  private enqueueRootParityCircuit(provingState: BlockProvingState) {
918
965
  if (!provingState.verifyState()) {
919
- logger.debug('Not running root parity. State no longer valid.');
966
+ this.logger.debug('Not running root parity. State no longer valid.');
920
967
  return;
921
968
  }
922
969
 
923
970
  if (!provingState.tryStartProvingRootParity()) {
924
- logger.debug('Root parity already started.');
971
+ this.logger.debug('Root parity already started.');
925
972
  return;
926
973
  }
927
974
 
@@ -948,12 +995,12 @@ export class ProvingOrchestrator implements EpochProver {
948
995
  // Enqueues the next level of merge if all inputs are available
949
996
  private enqueueBlockMergeRollup(provingState: CheckpointProvingState, location: TreeNodeLocation) {
950
997
  if (!provingState.verifyState()) {
951
- logger.debug('Not running block merge rollup. State no longer valid.');
998
+ this.logger.debug('Not running block merge rollup. State no longer valid.');
952
999
  return;
953
1000
  }
954
1001
 
955
1002
  if (!provingState.tryStartProvingBlockMerge(location)) {
956
- logger.debug('Block merge rollup already started.');
1003
+ this.logger.debug('Block merge rollup already started.');
957
1004
  return;
958
1005
  }
959
1006
 
@@ -968,29 +1015,29 @@ export class ProvingOrchestrator implements EpochProver {
968
1015
  },
969
1016
  signal => this.prover.getBlockMergeRollupProof(inputs, signal, provingState.epochNumber),
970
1017
  ),
971
- result => {
1018
+ async result => {
972
1019
  provingState.setBlockMergeRollupProof(location, result);
973
- this.checkAndEnqueueNextBlockMergeRollup(provingState, location);
1020
+ await this.checkAndEnqueueNextBlockMergeRollup(provingState, location);
974
1021
  },
975
1022
  );
976
1023
  }
977
1024
 
978
- private enqueueCheckpointRootRollup(provingState: CheckpointProvingState) {
1025
+ private async enqueueCheckpointRootRollup(provingState: CheckpointProvingState) {
979
1026
  if (!provingState.verifyState()) {
980
- logger.debug('Not running checkpoint root rollup. State no longer valid.');
1027
+ this.logger.debug('Not running checkpoint root rollup. State no longer valid.');
981
1028
  return;
982
1029
  }
983
1030
 
984
1031
  if (!provingState.tryStartProvingCheckpointRoot()) {
985
- logger.debug('Checkpoint root rollup already started.');
1032
+ this.logger.debug('Checkpoint root rollup already started.');
986
1033
  return;
987
1034
  }
988
1035
 
989
1036
  const rollupType = provingState.getCheckpointRootRollupType();
990
1037
 
991
- logger.debug(`Enqueuing ${rollupType} for checkpoint ${provingState.index}.`);
1038
+ this.logger.debug(`Enqueuing ${rollupType} for checkpoint ${provingState.index}.`);
992
1039
 
993
- const inputs = provingState.getCheckpointRootRollupInputs();
1040
+ const inputs = await provingState.getCheckpointRootRollupInputs();
994
1041
 
995
1042
  this.deferredProving(
996
1043
  provingState,
@@ -1012,7 +1059,7 @@ export class ProvingOrchestrator implements EpochProver {
1012
1059
  const computedEndBlobAccumulatorState = provingState.getEndBlobAccumulator()!.toBlobAccumulator();
1013
1060
  const circuitEndBlobAccumulatorState = result.inputs.endBlobAccumulator;
1014
1061
  if (!circuitEndBlobAccumulatorState.equals(computedEndBlobAccumulatorState)) {
1015
- logger.error(
1062
+ this.logger.error(
1016
1063
  `Blob accumulator state mismatch.\nCircuit: ${inspect(circuitEndBlobAccumulatorState)}\nComputed: ${inspect(
1017
1064
  computedEndBlobAccumulatorState,
1018
1065
  )}`,
@@ -1021,7 +1068,7 @@ export class ProvingOrchestrator implements EpochProver {
1021
1068
  return;
1022
1069
  }
1023
1070
 
1024
- logger.debug(`Completed ${rollupType} proof for checkpoint ${provingState.index}.`);
1071
+ this.logger.debug(`Completed ${rollupType} proof for checkpoint ${provingState.index}.`);
1025
1072
 
1026
1073
  const leafLocation = provingState.setCheckpointRootRollupProof(result);
1027
1074
  const epochProvingState = provingState.parentEpoch;
@@ -1037,12 +1084,12 @@ export class ProvingOrchestrator implements EpochProver {
1037
1084
 
1038
1085
  private enqueueCheckpointMergeRollup(provingState: EpochProvingState, location: TreeNodeLocation) {
1039
1086
  if (!provingState.verifyState()) {
1040
- logger.debug('Not running checkpoint merge rollup. State no longer valid.');
1087
+ this.logger.debug('Not running checkpoint merge rollup. State no longer valid.');
1041
1088
  return;
1042
1089
  }
1043
1090
 
1044
1091
  if (!provingState.tryStartProvingCheckpointMerge(location)) {
1045
- logger.debug('Checkpoint merge rollup already started.');
1092
+ this.logger.debug('Checkpoint merge rollup already started.');
1046
1093
  return;
1047
1094
  }
1048
1095
 
@@ -1059,7 +1106,7 @@ export class ProvingOrchestrator implements EpochProver {
1059
1106
  signal => this.prover.getCheckpointMergeRollupProof(inputs, signal, provingState.epochNumber),
1060
1107
  ),
1061
1108
  result => {
1062
- logger.debug('Completed proof for checkpoint merge rollup.');
1109
+ this.logger.debug('Completed proof for checkpoint merge rollup.');
1063
1110
  provingState.setCheckpointMergeRollupProof(location, result);
1064
1111
  this.checkAndEnqueueNextCheckpointMergeRollup(provingState, location);
1065
1112
  },
@@ -1068,16 +1115,16 @@ export class ProvingOrchestrator implements EpochProver {
1068
1115
 
1069
1116
  private enqueueEpochPadding(provingState: EpochProvingState) {
1070
1117
  if (!provingState.verifyState()) {
1071
- logger.debug('Not running epoch padding. State no longer valid.');
1118
+ this.logger.debug('Not running epoch padding. State no longer valid.');
1072
1119
  return;
1073
1120
  }
1074
1121
 
1075
1122
  if (!provingState.tryStartProvingPaddingCheckpoint()) {
1076
- logger.debug('Padding checkpoint already started.');
1123
+ this.logger.debug('Padding checkpoint already started.');
1077
1124
  return;
1078
1125
  }
1079
1126
 
1080
- logger.debug('Padding epoch proof with a padding block root proof.');
1127
+ this.logger.debug('Padding epoch proof with a padding block root proof.');
1081
1128
 
1082
1129
  const inputs = provingState.getPaddingCheckpointInputs();
1083
1130
 
@@ -1092,7 +1139,7 @@ export class ProvingOrchestrator implements EpochProver {
1092
1139
  signal => this.prover.getCheckpointPaddingRollupProof(inputs, signal, provingState.epochNumber),
1093
1140
  ),
1094
1141
  result => {
1095
- logger.debug('Completed proof for padding checkpoint.');
1142
+ this.logger.debug('Completed proof for padding checkpoint.');
1096
1143
  provingState.setCheckpointPaddingProof(result);
1097
1144
  this.checkAndEnqueueRootRollup(provingState);
1098
1145
  },
@@ -1102,11 +1149,11 @@ export class ProvingOrchestrator implements EpochProver {
1102
1149
  // Executes the root rollup circuit
1103
1150
  private enqueueRootRollup(provingState: EpochProvingState) {
1104
1151
  if (!provingState.verifyState()) {
1105
- logger.debug('Not running root rollup, state no longer valid');
1152
+ this.logger.debug('Not running root rollup, state no longer valid');
1106
1153
  return;
1107
1154
  }
1108
1155
 
1109
- logger.debug(`Preparing root rollup`);
1156
+ this.logger.debug(`Preparing root rollup`);
1110
1157
 
1111
1158
  const inputs = provingState.getRootRollupInputs();
1112
1159
 
@@ -1121,7 +1168,7 @@ export class ProvingOrchestrator implements EpochProver {
1121
1168
  signal => this.prover.getRootRollupProof(inputs, signal, provingState.epochNumber),
1122
1169
  ),
1123
1170
  result => {
1124
- logger.verbose(`Orchestrator completed root rollup for epoch ${provingState.epochNumber}`);
1171
+ this.logger.verbose(`Orchestrator completed root rollup for epoch ${provingState.epochNumber}`);
1125
1172
  provingState.setRootRollupProof(result);
1126
1173
  provingState.resolve({ status: 'success' });
1127
1174
  },
@@ -1143,32 +1190,35 @@ export class ProvingOrchestrator implements EpochProver {
1143
1190
 
1144
1191
  private checkAndEnqueueBlockRootRollup(provingState: BlockProvingState) {
1145
1192
  if (!provingState.isReadyForBlockRootRollup()) {
1146
- logger.debug('Not ready for block root rollup');
1193
+ this.logger.debug('Not ready for block root rollup');
1147
1194
  return;
1148
1195
  }
1149
1196
 
1150
1197
  this.enqueueBlockRootRollup(provingState);
1151
1198
  }
1152
1199
 
1153
- private checkAndEnqueueNextBlockMergeRollup(provingState: CheckpointProvingState, currentLocation: TreeNodeLocation) {
1200
+ private async checkAndEnqueueNextBlockMergeRollup(
1201
+ provingState: CheckpointProvingState,
1202
+ currentLocation: TreeNodeLocation,
1203
+ ) {
1154
1204
  if (!provingState.isReadyForBlockMerge(currentLocation)) {
1155
1205
  return;
1156
1206
  }
1157
1207
 
1158
1208
  const parentLocation = provingState.getParentLocation(currentLocation);
1159
1209
  if (parentLocation.level === 0) {
1160
- this.checkAndEnqueueCheckpointRootRollup(provingState);
1210
+ await this.checkAndEnqueueCheckpointRootRollup(provingState);
1161
1211
  } else {
1162
1212
  this.enqueueBlockMergeRollup(provingState, parentLocation);
1163
1213
  }
1164
1214
  }
1165
1215
 
1166
- private checkAndEnqueueCheckpointRootRollup(provingState: CheckpointProvingState) {
1216
+ private async checkAndEnqueueCheckpointRootRollup(provingState: CheckpointProvingState) {
1167
1217
  if (!provingState.isReadyForCheckpointRoot()) {
1168
1218
  return;
1169
1219
  }
1170
1220
 
1171
- this.enqueueCheckpointRootRollup(provingState);
1221
+ await this.enqueueCheckpointRootRollup(provingState);
1172
1222
  }
1173
1223
 
1174
1224
  private checkAndEnqueueNextCheckpointMergeRollup(provingState: EpochProvingState, currentLocation: TreeNodeLocation) {
@@ -1186,7 +1236,7 @@ export class ProvingOrchestrator implements EpochProver {
1186
1236
 
1187
1237
  private checkAndEnqueueRootRollup(provingState: EpochProvingState) {
1188
1238
  if (!provingState.isReadyForRootRollup()) {
1189
- logger.debug('Not ready for root rollup');
1239
+ this.logger.debug('Not ready for root rollup');
1190
1240
  return;
1191
1241
  }
1192
1242
 
@@ -1201,7 +1251,7 @@ export class ProvingOrchestrator implements EpochProver {
1201
1251
  */
1202
1252
  private enqueueVM(provingState: BlockProvingState, txIndex: number) {
1203
1253
  if (!provingState.verifyState()) {
1204
- logger.debug(`Not running VM circuit as state is no longer valid`);
1254
+ this.logger.debug(`Not running VM circuit as state is no longer valid`);
1205
1255
  return;
1206
1256
  }
1207
1257
 
@@ -1220,7 +1270,7 @@ export class ProvingOrchestrator implements EpochProver {
1220
1270
  );
1221
1271
 
1222
1272
  this.deferredProving(provingState, doAvmProving, proof => {
1223
- logger.debug(`Proven VM for tx index: ${txIndex}`);
1273
+ this.logger.debug(`Proven VM for tx index: ${txIndex}`);
1224
1274
  txProvingState.setAvmProof(proof);
1225
1275
  this.checkAndEnqueueBaseRollup(provingState, txIndex);
1226
1276
  });
@@ -1233,7 +1283,7 @@ export class ProvingOrchestrator implements EpochProver {
1233
1283
  }
1234
1284
 
1235
1285
  // We must have completed all proving (chonk verifier proof and (if required) vm proof are generated), we now move to the base rollup.
1236
- logger.debug(`Public functions completed for tx ${txIndex} enqueueing base rollup`);
1286
+ this.logger.debug(`Public functions completed for tx ${txIndex} enqueueing base rollup`);
1237
1287
 
1238
1288
  this.enqueueBaseRollup(provingState, txIndex);
1239
1289
  }