@aztec/prover-client 0.0.1-commit.b655e406 → 0.0.1-commit.b9865e97

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 (174) hide show
  1. package/dest/config.d.ts +2 -2
  2. package/dest/config.d.ts.map +1 -1
  3. package/dest/config.js +17 -3
  4. package/dest/index.d.ts +1 -1
  5. package/dest/light/index.d.ts +2 -0
  6. package/dest/light/index.d.ts.map +1 -0
  7. package/dest/light/index.js +1 -0
  8. package/dest/light/lightweight_checkpoint_builder.d.ts +52 -0
  9. package/dest/light/lightweight_checkpoint_builder.d.ts.map +1 -0
  10. package/dest/light/lightweight_checkpoint_builder.js +231 -0
  11. package/dest/mocks/fixtures.d.ts +1 -4
  12. package/dest/mocks/fixtures.d.ts.map +1 -1
  13. package/dest/mocks/fixtures.js +9 -18
  14. package/dest/mocks/test_context.d.ts +31 -46
  15. package/dest/mocks/test_context.d.ts.map +1 -1
  16. package/dest/mocks/test_context.js +133 -123
  17. package/dest/orchestrator/block-building-helpers.d.ts +18 -20
  18. package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
  19. package/dest/orchestrator/block-building-helpers.js +90 -115
  20. package/dest/orchestrator/block-proving-state.d.ts +20 -11
  21. package/dest/orchestrator/block-proving-state.d.ts.map +1 -1
  22. package/dest/orchestrator/block-proving-state.js +87 -19
  23. package/dest/orchestrator/checkpoint-proving-state.d.ts +29 -9
  24. package/dest/orchestrator/checkpoint-proving-state.d.ts.map +1 -1
  25. package/dest/orchestrator/checkpoint-proving-state.js +62 -21
  26. package/dest/orchestrator/checkpoint-sub-tree-orchestrator.d.ts +107 -0
  27. package/dest/orchestrator/checkpoint-sub-tree-orchestrator.d.ts.map +1 -0
  28. package/dest/orchestrator/checkpoint-sub-tree-orchestrator.js +151 -0
  29. package/dest/orchestrator/epoch-proving-context.d.ts +51 -0
  30. package/dest/orchestrator/epoch-proving-context.d.ts.map +1 -0
  31. package/dest/orchestrator/epoch-proving-context.js +81 -0
  32. package/dest/orchestrator/epoch-proving-state.d.ts +12 -10
  33. package/dest/orchestrator/epoch-proving-state.d.ts.map +1 -1
  34. package/dest/orchestrator/epoch-proving-state.js +40 -4
  35. package/dest/orchestrator/index.d.ts +4 -1
  36. package/dest/orchestrator/index.d.ts.map +1 -1
  37. package/dest/orchestrator/index.js +3 -0
  38. package/dest/orchestrator/orchestrator.d.ts +37 -32
  39. package/dest/orchestrator/orchestrator.d.ts.map +1 -1
  40. package/dest/orchestrator/orchestrator.js +568 -303
  41. package/dest/orchestrator/orchestrator_metrics.d.ts +1 -3
  42. package/dest/orchestrator/orchestrator_metrics.d.ts.map +1 -1
  43. package/dest/orchestrator/orchestrator_metrics.js +2 -15
  44. package/dest/orchestrator/proving-scheduler.d.ts +72 -0
  45. package/dest/orchestrator/proving-scheduler.d.ts.map +1 -0
  46. package/dest/orchestrator/proving-scheduler.js +117 -0
  47. package/dest/orchestrator/top-tree-orchestrator.d.ts +83 -0
  48. package/dest/orchestrator/top-tree-orchestrator.d.ts.map +1 -0
  49. package/dest/orchestrator/top-tree-orchestrator.js +182 -0
  50. package/dest/orchestrator/top-tree-proving-scheduler.d.ts +62 -0
  51. package/dest/orchestrator/top-tree-proving-scheduler.d.ts.map +1 -0
  52. package/dest/orchestrator/top-tree-proving-scheduler.js +73 -0
  53. package/dest/orchestrator/top-tree-proving-state.d.ts +61 -0
  54. package/dest/orchestrator/top-tree-proving-state.d.ts.map +1 -0
  55. package/dest/orchestrator/top-tree-proving-state.js +185 -0
  56. package/dest/orchestrator/tx-proving-state.d.ts +6 -5
  57. package/dest/orchestrator/tx-proving-state.d.ts.map +1 -1
  58. package/dest/orchestrator/tx-proving-state.js +7 -16
  59. package/dest/prover-client/factory.d.ts +3 -3
  60. package/dest/prover-client/factory.d.ts.map +1 -1
  61. package/dest/prover-client/index.d.ts +1 -1
  62. package/dest/prover-client/prover-client.d.ts +66 -7
  63. package/dest/prover-client/prover-client.d.ts.map +1 -1
  64. package/dest/prover-client/prover-client.js +64 -11
  65. package/dest/prover-client/server-epoch-prover.d.ts +8 -7
  66. package/dest/prover-client/server-epoch-prover.d.ts.map +1 -1
  67. package/dest/prover-client/server-epoch-prover.js +2 -2
  68. package/dest/proving_broker/broker_prover_facade.d.ts +25 -23
  69. package/dest/proving_broker/broker_prover_facade.d.ts.map +1 -1
  70. package/dest/proving_broker/broker_prover_facade.js +21 -33
  71. package/dest/proving_broker/config.d.ts +14 -62
  72. package/dest/proving_broker/config.d.ts.map +1 -1
  73. package/dest/proving_broker/config.js +29 -6
  74. package/dest/proving_broker/factory.d.ts +1 -1
  75. package/dest/proving_broker/fixtures.d.ts +3 -2
  76. package/dest/proving_broker/fixtures.d.ts.map +1 -1
  77. package/dest/proving_broker/fixtures.js +3 -2
  78. package/dest/proving_broker/index.d.ts +2 -1
  79. package/dest/proving_broker/index.d.ts.map +1 -1
  80. package/dest/proving_broker/index.js +1 -0
  81. package/dest/proving_broker/proof_store/factory.d.ts +2 -5
  82. package/dest/proving_broker/proof_store/factory.d.ts.map +1 -1
  83. package/dest/proving_broker/proof_store/factory.js +7 -30
  84. package/dest/proving_broker/proof_store/file_store_proof_store.d.ts +18 -0
  85. package/dest/proving_broker/proof_store/file_store_proof_store.d.ts.map +1 -0
  86. package/dest/proving_broker/proof_store/file_store_proof_store.js +60 -0
  87. package/dest/proving_broker/proof_store/index.d.ts +2 -2
  88. package/dest/proving_broker/proof_store/index.d.ts.map +1 -1
  89. package/dest/proving_broker/proof_store/index.js +1 -1
  90. package/dest/proving_broker/proof_store/inline_proof_store.d.ts +1 -1
  91. package/dest/proving_broker/proof_store/inline_proof_store.d.ts.map +1 -1
  92. package/dest/proving_broker/proof_store/proof_store.d.ts +1 -1
  93. package/dest/proving_broker/proving_agent.d.ts +5 -9
  94. package/dest/proving_broker/proving_agent.d.ts.map +1 -1
  95. package/dest/proving_broker/proving_agent.js +4 -19
  96. package/dest/proving_broker/proving_broker.d.ts +8 -5
  97. package/dest/proving_broker/proving_broker.d.ts.map +1 -1
  98. package/dest/proving_broker/proving_broker.js +74 -22
  99. package/dest/proving_broker/proving_broker_database/memory.d.ts +3 -2
  100. package/dest/proving_broker/proving_broker_database/memory.d.ts.map +1 -1
  101. package/dest/proving_broker/proving_broker_database/persisted.d.ts +5 -3
  102. package/dest/proving_broker/proving_broker_database/persisted.d.ts.map +1 -1
  103. package/dest/proving_broker/proving_broker_database/persisted.js +394 -5
  104. package/dest/proving_broker/proving_broker_database.d.ts +3 -2
  105. package/dest/proving_broker/proving_broker_database.d.ts.map +1 -1
  106. package/dest/proving_broker/proving_broker_instrumentation.d.ts +3 -1
  107. package/dest/proving_broker/proving_broker_instrumentation.d.ts.map +1 -1
  108. package/dest/proving_broker/proving_broker_instrumentation.js +22 -35
  109. package/dest/proving_broker/proving_job_controller.d.ts +5 -3
  110. package/dest/proving_broker/proving_job_controller.d.ts.map +1 -1
  111. package/dest/proving_broker/proving_job_controller.js +8 -6
  112. package/dest/proving_broker/rpc.d.ts +9 -5
  113. package/dest/proving_broker/rpc.d.ts.map +1 -1
  114. package/dest/proving_broker/rpc.js +87 -23
  115. package/dest/test/mock_proof_store.d.ts +1 -1
  116. package/dest/test/mock_proof_store.d.ts.map +1 -1
  117. package/dest/test/mock_prover.d.ts +5 -6
  118. package/dest/test/mock_prover.d.ts.map +1 -1
  119. package/dest/test/mock_prover.js +4 -4
  120. package/package.json +23 -22
  121. package/src/config.ts +19 -3
  122. package/src/light/index.ts +1 -0
  123. package/src/light/lightweight_checkpoint_builder.ts +320 -0
  124. package/src/mocks/fixtures.ts +9 -31
  125. package/src/mocks/test_context.ts +170 -185
  126. package/src/orchestrator/block-building-helpers.ts +129 -209
  127. package/src/orchestrator/block-proving-state.ts +109 -22
  128. package/src/orchestrator/checkpoint-proving-state.ts +89 -26
  129. package/src/orchestrator/checkpoint-sub-tree-orchestrator.ts +271 -0
  130. package/src/orchestrator/epoch-proving-context.ts +101 -0
  131. package/src/orchestrator/epoch-proving-state.ts +67 -15
  132. package/src/orchestrator/index.ts +8 -0
  133. package/src/orchestrator/orchestrator.ts +193 -354
  134. package/src/orchestrator/orchestrator_metrics.ts +2 -25
  135. package/src/orchestrator/proving-scheduler.ts +156 -0
  136. package/src/orchestrator/top-tree-orchestrator.ts +314 -0
  137. package/src/orchestrator/top-tree-proving-scheduler.ts +154 -0
  138. package/src/orchestrator/top-tree-proving-state.ts +220 -0
  139. package/src/orchestrator/tx-proving-state.ts +10 -27
  140. package/src/prover-client/factory.ts +6 -2
  141. package/src/prover-client/prover-client.ts +157 -24
  142. package/src/prover-client/server-epoch-prover.ts +6 -7
  143. package/src/proving_broker/broker_prover_facade.ts +46 -55
  144. package/src/proving_broker/config.ts +33 -3
  145. package/src/proving_broker/fixtures.ts +8 -3
  146. package/src/proving_broker/index.ts +1 -0
  147. package/src/proving_broker/proof_store/factory.ts +10 -32
  148. package/src/proving_broker/proof_store/file_store_proof_store.ts +78 -0
  149. package/src/proving_broker/proof_store/index.ts +1 -1
  150. package/src/proving_broker/proving_agent.ts +6 -19
  151. package/src/proving_broker/proving_broker.ts +70 -17
  152. package/src/proving_broker/proving_broker_database/memory.ts +2 -1
  153. package/src/proving_broker/proving_broker_database/persisted.ts +22 -7
  154. package/src/proving_broker/proving_broker_database.ts +2 -1
  155. package/src/proving_broker/proving_broker_instrumentation.ts +23 -35
  156. package/src/proving_broker/proving_job_controller.ts +13 -7
  157. package/src/proving_broker/rpc.ts +46 -20
  158. package/src/test/mock_prover.ts +2 -14
  159. package/dest/block-factory/index.d.ts +0 -2
  160. package/dest/block-factory/index.d.ts.map +0 -1
  161. package/dest/block-factory/index.js +0 -1
  162. package/dest/block-factory/light.d.ts +0 -38
  163. package/dest/block-factory/light.d.ts.map +0 -1
  164. package/dest/block-factory/light.js +0 -94
  165. package/dest/proving_broker/proof_store/gcs_proof_store.d.ts +0 -14
  166. package/dest/proving_broker/proof_store/gcs_proof_store.d.ts.map +0 -1
  167. package/dest/proving_broker/proof_store/gcs_proof_store.js +0 -52
  168. package/dest/proving_broker/proving_agent_instrumentation.d.ts +0 -8
  169. package/dest/proving_broker/proving_agent_instrumentation.d.ts.map +0 -1
  170. package/dest/proving_broker/proving_agent_instrumentation.js +0 -16
  171. package/src/block-factory/index.ts +0 -1
  172. package/src/block-factory/light.ts +0 -140
  173. package/src/proving_broker/proof_store/gcs_proof_store.ts +0 -76
  174. package/src/proving_broker/proving_agent_instrumentation.ts +0 -21
@@ -1,29 +1,28 @@
1
- import { BatchedBlob, FinalBlobBatchingChallenges, SpongeBlob } from '@aztec/blob-lib';
1
+ import { BatchedBlob, FinalBlobBatchingChallenges, SpongeBlob } from '@aztec/blob-lib/types';
2
2
  import {
3
3
  L1_TO_L2_MSG_SUBTREE_HEIGHT,
4
4
  L1_TO_L2_MSG_SUBTREE_ROOT_SIBLING_PATH_LENGTH,
5
5
  NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
6
- NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
7
6
  NUM_BASE_PARITY_PER_ROOT_PARITY,
8
7
  } from '@aztec/constants';
9
- import { padArrayEnd } from '@aztec/foundation/collection';
10
- import { AbortError } from '@aztec/foundation/error';
11
- import { Fr } from '@aztec/foundation/fields';
12
- import { createLogger } from '@aztec/foundation/log';
8
+ import { BlockNumber, EpochNumber } from '@aztec/foundation/branded-types';
9
+ import { Fr } from '@aztec/foundation/curves/bn254';
10
+ import type { LoggerBindings } from '@aztec/foundation/log';
13
11
  import { promiseWithResolvers } from '@aztec/foundation/promise';
14
12
  import { assertLength } from '@aztec/foundation/serialize';
15
13
  import { pushTestData } from '@aztec/foundation/testing';
16
14
  import { elapsed } from '@aztec/foundation/timer';
17
15
  import type { TreeNodeLocation } from '@aztec/foundation/trees';
18
- import { readAvmMinimalPublicTxInputsFromFile } from '@aztec/simulator/public/fixtures';
19
- import { EthAddress, createBlockEndMarker } from '@aztec/stdlib/block';
16
+ import { EthAddress } from '@aztec/stdlib/block';
20
17
  import type {
21
18
  EpochProver,
22
19
  ForkMerkleTreeOperations,
23
20
  MerkleTreeWriteOperations,
24
21
  PublicInputsAndRecursiveProof,
22
+ ReadonlyWorldStateAccess,
25
23
  ServerCircuitProver,
26
24
  } from '@aztec/stdlib/interfaces/server';
25
+ import { appendL1ToL2MessagesToTree } from '@aztec/stdlib/messaging';
27
26
  import type { Proof } from '@aztec/stdlib/proofs';
28
27
  import {
29
28
  type BaseRollupHints,
@@ -54,7 +53,6 @@ import {
54
53
  import { inspect } from 'util';
55
54
 
56
55
  import {
57
- buildBlockHeaderFromTxs,
58
56
  buildHeaderFromCircuitOutputs,
59
57
  getLastSiblingPath,
60
58
  getPublicChonkVerifierPrivateInputsFromTx,
@@ -69,10 +67,9 @@ import type { BlockProvingState } from './block-proving-state.js';
69
67
  import type { CheckpointProvingState } from './checkpoint-proving-state.js';
70
68
  import { EpochProvingState, type ProvingResult, type TreeSnapshots } from './epoch-proving-state.js';
71
69
  import { ProvingOrchestratorMetrics } from './orchestrator_metrics.js';
70
+ import { TopTreeProvingScheduler } from './top-tree-proving-scheduler.js';
72
71
  import { TxProvingState } from './tx-proving-state.js';
73
72
 
74
- const logger = createLogger('prover-client:orchestrator');
75
-
76
73
  /**
77
74
  * Implements an event driven proving scheduler to build the recursive proof tree. The idea being:
78
75
  * 1. Transactions are provided to the scheduler post simulation.
@@ -87,20 +84,24 @@ const logger = createLogger('prover-client:orchestrator');
87
84
  /**
88
85
  * The orchestrator, managing the flow of recursive proving operations required to build the rollup proof tree.
89
86
  */
90
- export class ProvingOrchestrator implements EpochProver {
91
- private provingState: EpochProvingState | undefined = undefined;
92
- private pendingProvingJobs: AbortController[] = [];
87
+ export class ProvingOrchestrator extends TopTreeProvingScheduler implements EpochProver {
88
+ protected provingState: EpochProvingState | undefined = undefined;
93
89
 
94
- private provingPromise: Promise<ProvingResult> | undefined = undefined;
90
+ protected provingPromise: Promise<ProvingResult> | undefined = undefined;
95
91
  private metrics: ProvingOrchestratorMetrics;
96
- private dbs: Map<number, MerkleTreeWriteOperations> = new Map();
92
+
93
+ private dbs: Map<BlockNumber, MerkleTreeWriteOperations> = new Map();
97
94
 
98
95
  constructor(
99
- private dbProvider: ForkMerkleTreeOperations,
100
- private prover: ServerCircuitProver,
96
+ private dbProvider: ReadonlyWorldStateAccess & ForkMerkleTreeOperations,
97
+ prover: ServerCircuitProver,
101
98
  private readonly proverId: EthAddress,
99
+ private readonly cancelJobsOnStop: boolean = false,
100
+ enqueueConcurrency: number,
102
101
  telemetryClient: TelemetryClient = getTelemetryClient(),
102
+ bindings?: LoggerBindings,
103
103
  ) {
104
+ super(prover, enqueueConcurrency, 'prover-client:orchestrator', bindings);
104
105
  this.metrics = new ProvingOrchestratorMetrics(telemetryClient, 'ProvingOrchestrator');
105
106
  }
106
107
 
@@ -112,13 +113,32 @@ export class ProvingOrchestrator implements EpochProver {
112
113
  return this.proverId;
113
114
  }
114
115
 
115
- public stop(): Promise<void> {
116
+ public getNumActiveForks() {
117
+ return this.dbs.size;
118
+ }
119
+
120
+ protected override cancelInternal(): void {
116
121
  this.cancel();
117
- return Promise.resolve();
122
+ }
123
+
124
+ protected override wrapCircuitCall<T>(
125
+ circuitName: string,
126
+ fn: (signal: AbortSignal) => Promise<T>,
127
+ ): (signal: AbortSignal) => Promise<T> {
128
+ return wrapCallbackInSpan(
129
+ this.tracer,
130
+ `ProvingOrchestrator.prover.${circuitName}`,
131
+ { [Attributes.PROTOCOL_CIRCUIT_NAME]: circuitName as CircuitName },
132
+ fn,
133
+ );
134
+ }
135
+
136
+ protected override onRootRollupComplete(state: EpochProvingState) {
137
+ state.resolve({ status: 'success' });
118
138
  }
119
139
 
120
140
  public startNewEpoch(
121
- epochNumber: number,
141
+ epochNumber: EpochNumber,
122
142
  totalNumCheckpoints: number,
123
143
  finalBlobBatchingChallenges: FinalBlobBatchingChallenges,
124
144
  ) {
@@ -130,7 +150,7 @@ export class ProvingOrchestrator implements EpochProver {
130
150
 
131
151
  const { promise: _promise, resolve, reject } = promiseWithResolvers<ProvingResult>();
132
152
  const promise = _promise.catch((reason): ProvingResult => ({ status: 'failure', reason }));
133
- logger.info(`Starting epoch ${epochNumber} with ${totalNumCheckpoints} checkpoints.`);
153
+ this.logger.info(`Starting epoch ${epochNumber} with ${totalNumCheckpoints} checkpoints.`);
134
154
  this.provingState = new EpochProvingState(
135
155
  epochNumber,
136
156
  totalNumCheckpoints,
@@ -142,12 +162,19 @@ export class ProvingOrchestrator implements EpochProver {
142
162
  this.provingPromise = promise;
143
163
  }
144
164
 
165
+ /**
166
+ * Starts a new checkpoint.
167
+ * @param checkpointIndex - The index of the checkpoint in the epoch.
168
+ * @param constants - The constants for this checkpoint.
169
+ * @param l1ToL2Messages - The set of L1 to L2 messages to be inserted at the beginning of this checkpoint.
170
+ * @param totalNumBlocks - The total number of blocks expected in the checkpoint (must be at least one).
171
+ * @param headerOfLastBlockInPreviousCheckpoint - The header of the last block in the previous checkpoint.
172
+ */
145
173
  public async startNewCheckpoint(
146
174
  checkpointIndex: number,
147
175
  constants: CheckpointConstantData,
148
176
  l1ToL2Messages: Fr[],
149
177
  totalNumBlocks: number,
150
- totalNumBlobFields: number,
151
178
  headerOfLastBlockInPreviousCheckpoint: BlockHeader,
152
179
  ) {
153
180
  if (!this.provingState) {
@@ -162,7 +189,7 @@ export class ProvingOrchestrator implements EpochProver {
162
189
  const lastBlockNumber = headerOfLastBlockInPreviousCheckpoint.globalVariables.blockNumber;
163
190
  const db = await this.dbProvider.fork(lastBlockNumber);
164
191
 
165
- const firstBlockNumber = lastBlockNumber + 1;
192
+ const firstBlockNumber = BlockNumber(lastBlockNumber + 1);
166
193
  this.dbs.set(firstBlockNumber, db);
167
194
 
168
195
  // Get archive sibling path before any block in this checkpoint lands.
@@ -180,7 +207,6 @@ export class ProvingOrchestrator implements EpochProver {
180
207
  checkpointIndex,
181
208
  constants,
182
209
  totalNumBlocks,
183
- totalNumBlobFields,
184
210
  headerOfLastBlockInPreviousCheckpoint,
185
211
  lastArchiveSiblingPath,
186
212
  l1ToL2Messages,
@@ -201,7 +227,7 @@ export class ProvingOrchestrator implements EpochProver {
201
227
  @trackSpan('ProvingOrchestrator.startNewBlock', blockNumber => ({
202
228
  [Attributes.BLOCK_NUMBER]: blockNumber,
203
229
  }))
204
- public async startNewBlock(blockNumber: number, timestamp: UInt64, totalNumTxs: number) {
230
+ public async startNewBlock(blockNumber: BlockNumber, timestamp: UInt64, totalNumTxs: number) {
205
231
  if (!this.provingState) {
206
232
  throw new Error('Empty epoch proving state. Call startNewEpoch before starting a block.');
207
233
  }
@@ -216,21 +242,21 @@ export class ProvingOrchestrator implements EpochProver {
216
242
  }
217
243
 
218
244
  const constants = checkpointProvingState.constants;
219
- logger.info(`Starting block ${blockNumber} for slot ${constants.slotNumber.toNumber()}.`);
245
+ this.logger.info(`Starting block ${blockNumber} for slot ${constants.slotNumber}.`);
220
246
 
221
247
  // Fork the db only when it's not already set. The db for the first block is set in `startNewCheckpoint`.
222
248
  if (!this.dbs.has(blockNumber)) {
223
249
  // Fork world state at the end of the immediately previous block
224
- const db = await this.dbProvider.fork(blockNumber - 1);
250
+ const db = await this.dbProvider.fork(BlockNumber(blockNumber - 1));
225
251
  this.dbs.set(blockNumber, db);
226
252
  }
227
- const db = this.dbs.get(blockNumber)!;
253
+ const db = this.getDbForBlock(blockNumber);
228
254
 
229
255
  // Get archive snapshot and sibling path before any txs in this block lands.
230
256
  const lastArchiveTreeSnapshot = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
231
257
  const lastArchiveSiblingPath = await getRootTreeSiblingPath(MerkleTreeId.ARCHIVE, db);
232
258
 
233
- const blockProvingState = await checkpointProvingState.startNewBlock(
259
+ const blockProvingState = checkpointProvingState.startNewBlock(
234
260
  blockNumber,
235
261
  timestamp,
236
262
  totalNumTxs,
@@ -248,11 +274,16 @@ export class ProvingOrchestrator implements EpochProver {
248
274
  // Because `addTxs` won't be called for a block without txs, and that's where the sponge blob state is computed.
249
275
  // We need to set its end sponge blob here, which will become the start sponge blob for the next block.
250
276
  if (totalNumTxs === 0) {
277
+ const endState = await db.getStateReference();
278
+ blockProvingState.setEndState(endState);
279
+
251
280
  const endSpongeBlob = blockProvingState.getStartSpongeBlob().clone();
252
- await endSpongeBlob.absorb([createBlockEndMarker(0)]);
281
+ const blockEndBlobFields = blockProvingState.getBlockEndBlobFields();
282
+ await endSpongeBlob.absorb(blockEndBlobFields);
253
283
  blockProvingState.setEndSpongeBlob(endSpongeBlob);
254
284
 
255
- // And also try to accumulate the blobs as far as we can:
285
+ // Try to accumulate the out hashes and blobs as far as we can:
286
+ await this.provingState.accumulateCheckpointOutHashes();
256
287
  await this.provingState.setBlobAccumulators();
257
288
  }
258
289
  }
@@ -272,11 +303,11 @@ export class ProvingOrchestrator implements EpochProver {
272
303
  if (!txs.length) {
273
304
  // To avoid an ugly throw below. If we require an empty block, we can just call setBlockCompleted
274
305
  // on a block with no txs. We cannot do that here because we cannot find the blockNumber without any txs.
275
- logger.warn(`Provided no txs to orchestrator addTxs.`);
306
+ this.logger.warn(`Provided no txs to orchestrator addTxs.`);
276
307
  return;
277
308
  }
278
309
 
279
- const blockNumber = txs[0].globalVariables.blockNumber;
310
+ const blockNumber = BlockNumber(txs[0].globalVariables.blockNumber);
280
311
  const provingState = this.provingState.getBlockProvingStateByBlockNumber(blockNumber!);
281
312
  if (!provingState) {
282
313
  throw new Error(`Proving state for block ${blockNumber} not found. Call startNewBlock first.`);
@@ -292,9 +323,9 @@ export class ProvingOrchestrator implements EpochProver {
292
323
  throw new Error(`Block ${blockNumber} has been initialized with transactions.`);
293
324
  }
294
325
 
295
- logger.info(`Adding ${txs.length} transactions to block ${blockNumber}`);
326
+ this.logger.info(`Adding ${txs.length} transactions to block ${blockNumber}`);
296
327
 
297
- const db = this.dbs.get(blockNumber)!;
328
+ const db = this.getDbForBlock(blockNumber);
298
329
  const lastArchive = provingState.lastArchiveTreeSnapshot;
299
330
  const newL1ToL2MessageTreeSnapshot = provingState.newL1ToL2MessageTreeSnapshot;
300
331
  const spongeBlobState = provingState.getStartSpongeBlob().clone();
@@ -307,7 +338,7 @@ export class ProvingOrchestrator implements EpochProver {
307
338
 
308
339
  validateTx(tx);
309
340
 
310
- logger.info(`Received transaction: ${tx.hash}`);
341
+ this.logger.debug(`Received transaction: ${tx.hash}`);
311
342
 
312
343
  const startSpongeBlob = spongeBlobState.clone();
313
344
  const [hints, treeSnapshots] = await this.prepareBaseRollupInputs(
@@ -328,10 +359,10 @@ export class ProvingOrchestrator implements EpochProver {
328
359
  const txIndex = provingState.addNewTx(txProvingState);
329
360
  if (txProvingState.requireAvmProof) {
330
361
  this.getOrEnqueueChonkVerifier(provingState, txIndex);
331
- logger.debug(`Enqueueing public VM for tx ${txIndex}`);
362
+ this.logger.debug(`Enqueueing public VM for tx ${txIndex}`);
332
363
  this.enqueueVM(provingState, txIndex);
333
364
  } else {
334
- logger.debug(`Enqueueing base rollup for private-only tx ${txIndex}`);
365
+ this.logger.debug(`Enqueueing base rollup for private-only tx ${txIndex}`);
335
366
  this.enqueueBaseRollup(provingState, txIndex);
336
367
  }
337
368
  } catch (err: any) {
@@ -341,11 +372,16 @@ export class ProvingOrchestrator implements EpochProver {
341
372
  }
342
373
  }
343
374
 
344
- await spongeBlobState.absorb([createBlockEndMarker(txs.length)]);
375
+ const endState = await db.getStateReference();
376
+ provingState.setEndState(endState);
377
+
378
+ const blockEndBlobFields = provingState.getBlockEndBlobFields();
379
+ await spongeBlobState.absorb(blockEndBlobFields);
345
380
 
346
381
  provingState.setEndSpongeBlob(spongeBlobState);
347
382
 
348
- // Txs have been added to the block. Now try to accumulate the blobs as far as we can:
383
+ // Txs have been added to the block. Now try to accumulate the out hashes and blobs as far as we can:
384
+ await this.provingState.accumulateCheckpointOutHashes();
349
385
  await this.provingState.setBlobAccumulators();
350
386
  }
351
387
 
@@ -369,7 +405,7 @@ export class ProvingOrchestrator implements EpochProver {
369
405
  typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH
370
406
  >
371
407
  >();
372
- logger.debug(`Starting chonk verifier circuit for tx ${txHash}`);
408
+ this.logger.debug(`Starting chonk verifier circuit for tx ${txHash}`);
373
409
  this.doEnqueueChonkVerifier(txHash, privateInputs, proof => {
374
410
  tubeProof.resolve(proof);
375
411
  });
@@ -382,10 +418,10 @@ export class ProvingOrchestrator implements EpochProver {
382
418
  * Marks the block as completed.
383
419
  * Computes the block header and updates the archive tree.
384
420
  */
385
- @trackSpan('ProvingOrchestrator.setBlockCompleted', (blockNumber: number) => ({
421
+ @trackSpan('ProvingOrchestrator.setBlockCompleted', (blockNumber: BlockNumber) => ({
386
422
  [Attributes.BLOCK_NUMBER]: blockNumber,
387
423
  }))
388
- public async setBlockCompleted(blockNumber: number, expectedHeader?: BlockHeader): Promise<BlockHeader> {
424
+ public async setBlockCompleted(blockNumber: BlockNumber, expectedHeader?: BlockHeader): Promise<BlockHeader> {
389
425
  const provingState = this.provingState?.getBlockProvingStateByBlockNumber(blockNumber);
390
426
  if (!provingState) {
391
427
  throw new Error(`Block proving state for ${blockNumber} not found`);
@@ -408,39 +444,31 @@ export class ProvingOrchestrator implements EpochProver {
408
444
  );
409
445
  }
410
446
 
411
- // And build the block header
412
- logger.verbose(`Block ${blockNumber} completed. Assembling header.`);
413
- const header = await this.buildL2BlockHeader(provingState, expectedHeader);
414
-
415
- await this.verifyBuiltBlockAgainstSyncedState(provingState);
416
-
417
- return header;
418
- }
419
-
420
- private async buildL2BlockHeader(provingState: BlockProvingState, expectedHeader?: BlockHeader) {
421
- // Collect all txs in this block to build the header. The function calling this has made sure that all txs have been added.
422
- const txs = provingState.getProcessedTxs();
423
-
424
- const startSpongeBlob = provingState.getStartSpongeBlob();
425
-
426
- // Get db for this block
427
- const db = this.dbs.get(provingState.blockNumber)!;
428
-
429
- // Given we've applied every change from this block, now assemble the block header
430
- // and update the archive tree, so we're ready to start processing the next block
431
- const header = await buildBlockHeaderFromTxs(txs, provingState.getGlobalVariables(), startSpongeBlob, db);
447
+ // Given we've applied every change from this block, now assemble the block header:
448
+ this.logger.verbose(`Block ${blockNumber} completed. Assembling header.`);
449
+ const header = await provingState.buildBlockHeader();
432
450
 
433
451
  if (expectedHeader && !header.equals(expectedHeader)) {
434
- logger.error(`Block header mismatch: header=${header} expectedHeader=${expectedHeader}`);
452
+ this.logger.error(`Block header mismatch: header=${header} expectedHeader=${expectedHeader}`);
435
453
  throw new Error('Block header mismatch');
436
454
  }
437
455
 
438
- logger.verbose(
439
- `Updating archive tree with block ${provingState.blockNumber} header ${(await header.hash()).toString()}`,
440
- );
441
- await db.updateArchive(header);
456
+ // Get db for this block and remove from map — no other code should use it after this point.
457
+ const db = this.getDbForBlock(provingState.blockNumber);
458
+ this.dbs.delete(provingState.blockNumber);
442
459
 
443
- provingState.setBuiltBlockHeader(header);
460
+ // Update the archive tree, capture the snapshot, and close the fork deterministically.
461
+ try {
462
+ this.logger.verbose(
463
+ `Updating archive tree with block ${provingState.blockNumber} header ${(await header.hash()).toString()}`,
464
+ );
465
+ await db.updateArchive(header);
466
+ provingState.setBuiltArchive(await getTreeSnapshot(MerkleTreeId.ARCHIVE, db));
467
+ } finally {
468
+ await db.close();
469
+ }
470
+
471
+ await this.verifyBuiltBlockAgainstSyncedState(provingState);
444
472
 
445
473
  return header;
446
474
  }
@@ -449,31 +477,34 @@ export class ProvingOrchestrator implements EpochProver {
449
477
  protected async verifyBuiltBlockAgainstSyncedState(provingState: BlockProvingState) {
450
478
  const builtBlockHeader = provingState.getBuiltBlockHeader();
451
479
  if (!builtBlockHeader) {
452
- logger.debug('Block header not built yet, skipping header check.');
480
+ this.logger.debug('Block header not built yet, skipping header check.');
453
481
  return;
454
482
  }
455
483
 
456
484
  const output = provingState.getBlockRootRollupOutput();
457
485
  if (!output) {
458
- logger.debug('Block root rollup proof not built yet, skipping header check.');
486
+ this.logger.debug('Block root rollup proof not built yet, skipping header check.');
487
+ return;
488
+ }
489
+
490
+ const newArchive = provingState.getBuiltArchive();
491
+ if (!newArchive) {
492
+ this.logger.debug('Archive snapshot not yet captured, skipping header check.');
459
493
  return;
460
494
  }
495
+
461
496
  const header = await buildHeaderFromCircuitOutputs(output);
462
497
 
463
498
  if (!(await header.hash()).equals(await builtBlockHeader.hash())) {
464
- logger.error(`Block header mismatch.\nCircuit: ${inspect(header)}\nComputed: ${inspect(builtBlockHeader)}`);
499
+ this.logger.error(`Block header mismatch.\nCircuit: ${inspect(header)}\nComputed: ${inspect(builtBlockHeader)}`);
465
500
  provingState.reject(`Block header hash mismatch.`);
466
501
  return;
467
502
  }
468
503
 
469
- // Get db for this block
470
504
  const blockNumber = provingState.blockNumber;
471
- const db = this.dbs.get(blockNumber)!;
472
-
473
- const newArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
474
505
  const syncedArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, this.dbProvider.getSnapshot(blockNumber));
475
506
  if (!syncedArchive.equals(newArchive)) {
476
- logger.error(
507
+ this.logger.error(
477
508
  `Archive tree mismatch for block ${blockNumber}: world state synced to ${inspect(
478
509
  syncedArchive,
479
510
  )} but built ${inspect(newArchive)}`,
@@ -484,32 +515,34 @@ export class ProvingOrchestrator implements EpochProver {
484
515
 
485
516
  const circuitArchive = output.newArchive;
486
517
  if (!newArchive.equals(circuitArchive)) {
487
- logger.error(`New archive mismatch.\nCircuit: ${output.newArchive}\nComputed: ${newArchive}`);
518
+ this.logger.error(`New archive mismatch.\nCircuit: ${output.newArchive}\nComputed: ${newArchive}`);
488
519
  provingState.reject(`New archive mismatch.`);
489
520
  return;
490
521
  }
491
-
492
- // TODO(palla/prover): This closes the fork only on the happy path. If this epoch orchestrator
493
- // is aborted and never reaches this point, it will leak the fork. We need to add a global cleanup,
494
- // but have to make sure it only runs once all operations are completed, otherwise some function here
495
- // will attempt to access the fork after it was closed.
496
- logger.debug(`Cleaning up world state fork for ${blockNumber}`);
497
- void this.dbs
498
- .get(blockNumber)
499
- ?.close()
500
- .then(() => this.dbs.delete(blockNumber))
501
- .catch(err => logger.error(`Error closing db for block ${blockNumber}`, err));
502
522
  }
503
523
 
504
524
  /**
505
- * Cancel any further proving
525
+ * Cancel any further proving.
526
+ * If cancelJobsOnStop is true, aborts all pending jobs with the broker (which marks them as 'Aborted').
527
+ * If cancelJobsOnStop is false (default), jobs remain in the broker queue and can be reused on restart/reorg.
506
528
  */
507
529
  public cancel() {
508
- for (const controller of this.pendingProvingJobs) {
509
- controller.abort();
510
- }
530
+ this.resetSchedulerState(this.cancelJobsOnStop);
511
531
 
512
532
  this.provingState?.cancel();
533
+
534
+ for (const [blockNumber, db] of this.dbs.entries()) {
535
+ void db.close().catch(err => this.logger.error(`Error closing db for block ${blockNumber}`, err));
536
+ }
537
+ this.dbs.clear();
538
+ }
539
+
540
+ private getDbForBlock(blockNumber: BlockNumber): MerkleTreeWriteOperations {
541
+ const db = this.dbs.get(blockNumber);
542
+ if (!db) {
543
+ throw new Error(`World state fork for block ${blockNumber} not found.`);
544
+ }
545
+ return db;
513
546
  }
514
547
 
515
548
  /**
@@ -541,76 +574,7 @@ export class ProvingOrchestrator implements EpochProver {
541
574
  return epochProofResult;
542
575
  }
543
576
 
544
- /**
545
- * Enqueue a job to be scheduled
546
- * @param provingState - The proving state object being operated on
547
- * @param jobType - The type of job to be queued
548
- * @param job - The actual job, returns a promise notifying of the job's completion
549
- */
550
- private deferredProving<T>(
551
- provingState: EpochProvingState | CheckpointProvingState | BlockProvingState,
552
- request: (signal: AbortSignal) => Promise<T>,
553
- callback: (result: T) => void | Promise<void>,
554
- ) {
555
- if (!provingState.verifyState()) {
556
- logger.debug(`Not enqueuing job, state no longer valid`);
557
- return;
558
- }
559
-
560
- const controller = new AbortController();
561
- this.pendingProvingJobs.push(controller);
562
-
563
- // We use a 'safeJob'. We don't want promise rejections in the proving pool, we want to capture the error here
564
- // and reject the proving job whilst keeping the event loop free of rejections
565
- const safeJob = async () => {
566
- try {
567
- // there's a delay between enqueueing this job and it actually running
568
- if (controller.signal.aborted) {
569
- return;
570
- }
571
-
572
- const result = await request(controller.signal);
573
- if (!provingState.verifyState()) {
574
- logger.debug(`State no longer valid, discarding result`);
575
- return;
576
- }
577
-
578
- // we could have been cancelled whilst waiting for the result
579
- // and the prover ignored the signal. Drop the result in that case
580
- if (controller.signal.aborted) {
581
- return;
582
- }
583
-
584
- await callback(result);
585
- } catch (err) {
586
- if (err instanceof AbortError) {
587
- // operation was cancelled, probably because the block was cancelled
588
- // drop this result
589
- return;
590
- }
591
-
592
- logger.error(`Error thrown when proving job`, err);
593
- provingState!.reject(`${err}`);
594
- } finally {
595
- const index = this.pendingProvingJobs.indexOf(controller);
596
- if (index > -1) {
597
- this.pendingProvingJobs.splice(index, 1);
598
- }
599
- }
600
- };
601
-
602
- // let the callstack unwind before adding the job to the queue
603
- setImmediate(() => void safeJob());
604
- }
605
-
606
577
  private async updateL1ToL2MessageTree(l1ToL2Messages: Fr[], db: MerkleTreeWriteOperations) {
607
- const l1ToL2MessagesPadded = padArrayEnd<Fr, number>(
608
- l1ToL2Messages,
609
- Fr.ZERO,
610
- NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
611
- 'Too many L1 to L2 messages',
612
- );
613
-
614
578
  const lastL1ToL2MessageTreeSnapshot = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, db);
615
579
  const lastL1ToL2MessageSubtreeRootSiblingPath = assertLength(
616
580
  await getSubtreeSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, L1_TO_L2_MSG_SUBTREE_HEIGHT, db),
@@ -618,7 +582,7 @@ export class ProvingOrchestrator implements EpochProver {
618
582
  );
619
583
 
620
584
  // Update the local trees to include the new l1 to l2 messages
621
- await db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
585
+ await appendL1ToL2MessagesToTree(db, l1ToL2Messages);
622
586
 
623
587
  const newL1ToL2MessageTreeSnapshot = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, db);
624
588
  const newL1ToL2MessageSubtreeRootSiblingPath = assertLength(
@@ -674,12 +638,12 @@ export class ProvingOrchestrator implements EpochProver {
674
638
  // Executes the next level of merge if all inputs are available
675
639
  private enqueueBaseRollup(provingState: BlockProvingState, txIndex: number) {
676
640
  if (!provingState.verifyState()) {
677
- logger.debug('Not running base rollup, state invalid');
641
+ this.logger.debug('Not running base rollup, state invalid');
678
642
  return;
679
643
  }
680
644
 
681
645
  if (!provingState.tryStartProvingBase(txIndex)) {
682
- logger.debug(`Base rollup for tx ${txIndex} already started.`);
646
+ this.logger.debug(`Base rollup for tx ${txIndex} already started.`);
683
647
  return;
684
648
  }
685
649
 
@@ -687,7 +651,7 @@ export class ProvingOrchestrator implements EpochProver {
687
651
  const { processedTx } = txProvingState;
688
652
  const { rollupType, inputs } = txProvingState.getBaseRollupTypeAndInputs();
689
653
 
690
- logger.debug(`Enqueuing deferred proving base rollup for ${processedTx.hash.toString()}`);
654
+ this.logger.debug(`Enqueuing deferred proving base rollup for ${processedTx.hash.toString()}`);
691
655
 
692
656
  this.deferredProving(
693
657
  provingState,
@@ -711,7 +675,7 @@ export class ProvingOrchestrator implements EpochProver {
711
675
  },
712
676
  ),
713
677
  result => {
714
- logger.debug(`Completed proof for ${rollupType} for tx ${processedTx.hash.toString()}`);
678
+ this.logger.debug(`Completed proof for ${rollupType} for tx ${processedTx.hash.toString()}`);
715
679
  validatePartialState(result.inputs.endTreeSnapshots, txProvingState.treeSnapshots);
716
680
  const leafLocation = provingState.setBaseRollupProof(txIndex, result);
717
681
  if (provingState.totalNumTxs === 1) {
@@ -725,34 +689,33 @@ export class ProvingOrchestrator implements EpochProver {
725
689
 
726
690
  // Enqueues the public chonk verifier circuit for a given transaction index, or reuses the one already enqueued.
727
691
  // Once completed, will enqueue the the public tx base rollup.
728
- private getOrEnqueueChonkVerifier(provingState: BlockProvingState, txIndex: number) {
692
+ protected getOrEnqueueChonkVerifier(provingState: BlockProvingState, txIndex: number) {
729
693
  if (!provingState.verifyState()) {
730
- logger.debug('Not running chonk verifier circuit, state invalid');
694
+ this.logger.debug('Not running chonk verifier circuit, state invalid');
731
695
  return;
732
696
  }
733
697
 
734
698
  const txProvingState = provingState.getTxProvingState(txIndex);
735
699
  const txHash = txProvingState.processedTx.hash.toString();
736
- NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH;
737
700
  const handleResult = (
738
701
  result: PublicInputsAndRecursiveProof<
739
702
  PublicChonkVerifierPublicInputs,
740
703
  typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH
741
704
  >,
742
705
  ) => {
743
- logger.debug(`Got chonk verifier proof for tx index: ${txIndex}`, { txHash });
706
+ this.logger.debug(`Got chonk verifier proof for tx index: ${txIndex}`, { txHash });
744
707
  txProvingState.setPublicChonkVerifierProof(result);
745
708
  this.provingState?.cachedChonkVerifierProofs.delete(txHash);
746
709
  this.checkAndEnqueueBaseRollup(provingState, txIndex);
747
710
  };
748
711
 
749
712
  if (this.provingState?.cachedChonkVerifierProofs.has(txHash)) {
750
- logger.debug(`Chonk verifier proof already enqueued for tx index: ${txIndex}`, { txHash });
713
+ this.logger.debug(`Chonk verifier proof already enqueued for tx index: ${txIndex}`, { txHash });
751
714
  void this.provingState!.cachedChonkVerifierProofs.get(txHash)!.then(handleResult);
752
715
  return;
753
716
  }
754
717
 
755
- logger.debug(`Enqueuing chonk verifier circuit for tx index: ${txIndex}`);
718
+ this.logger.debug(`Enqueuing chonk verifier circuit for tx index: ${txIndex}`);
756
719
  this.doEnqueueChonkVerifier(txHash, txProvingState.getPublicChonkVerifierPrivateInputs(), handleResult);
757
720
  }
758
721
 
@@ -768,7 +731,7 @@ export class ProvingOrchestrator implements EpochProver {
768
731
  provingState: EpochProvingState | BlockProvingState = this.provingState!,
769
732
  ) {
770
733
  if (!provingState.verifyState()) {
771
- logger.debug('Not running chonk verifier circuit, state invalid');
734
+ this.logger.debug('Not running chonk verifier circuit, state invalid');
772
735
  return;
773
736
  }
774
737
 
@@ -791,12 +754,12 @@ export class ProvingOrchestrator implements EpochProver {
791
754
  // Enqueues the next level of merge if all inputs are available
792
755
  private enqueueMergeRollup(provingState: BlockProvingState, location: TreeNodeLocation) {
793
756
  if (!provingState.verifyState()) {
794
- logger.debug('Not running merge rollup. State no longer valid.');
757
+ this.logger.debug('Not running merge rollup. State no longer valid.');
795
758
  return;
796
759
  }
797
760
 
798
761
  if (!provingState.tryStartProvingMerge(location)) {
799
- logger.debug('Merge rollup already started.');
762
+ this.logger.debug('Merge rollup already started.');
800
763
  return;
801
764
  }
802
765
 
@@ -822,18 +785,18 @@ export class ProvingOrchestrator implements EpochProver {
822
785
  // Executes the block root rollup circuit
823
786
  private enqueueBlockRootRollup(provingState: BlockProvingState) {
824
787
  if (!provingState.verifyState()) {
825
- logger.debug('Not running block root rollup, state no longer valid');
788
+ this.logger.debug('Not running block root rollup, state no longer valid');
826
789
  return;
827
790
  }
828
791
 
829
792
  if (!provingState.tryStartProvingBlockRoot()) {
830
- logger.debug('Block root rollup already started.');
793
+ this.logger.debug('Block root rollup already started.');
831
794
  return;
832
795
  }
833
796
 
834
797
  const { rollupType, inputs } = provingState.getBlockRootRollupTypeAndInputs();
835
798
 
836
- logger.debug(`Enqueuing ${rollupType} for block ${provingState.blockNumber}.`);
799
+ this.logger.debug(`Enqueuing ${rollupType} for block ${provingState.blockNumber}.`);
837
800
 
838
801
  this.deferredProving(
839
802
  provingState,
@@ -858,18 +821,23 @@ export class ProvingOrchestrator implements EpochProver {
858
821
  },
859
822
  ),
860
823
  async result => {
861
- // If the proofs were slower than the block header building, then we need to try validating the block header hashes here.
862
- await this.verifyBuiltBlockAgainstSyncedState(provingState);
863
-
864
- logger.debug(`Completed ${rollupType} proof for block ${provingState.blockNumber}`);
824
+ this.logger.debug(`Completed ${rollupType} proof for block ${provingState.blockNumber}`, {
825
+ blockNumber: provingState.blockNumber,
826
+ checkpointIndex: provingState.parentCheckpoint.index,
827
+ ...result.inputs.toInspect(),
828
+ });
865
829
 
866
830
  const leafLocation = provingState.setBlockRootRollupProof(result);
867
831
  const checkpointProvingState = provingState.parentCheckpoint;
868
832
 
833
+ // Verification is called from both here and setBlockCompleted. Whichever runs last
834
+ // will be the first to see all three pieces (header, proof output, archive) and run the checks.
835
+ await this.verifyBuiltBlockAgainstSyncedState(provingState);
836
+
869
837
  if (checkpointProvingState.totalNumBlocks === 1) {
870
- this.checkAndEnqueueCheckpointRootRollup(checkpointProvingState);
838
+ await this.checkAndEnqueueCheckpointRootRollup(checkpointProvingState);
871
839
  } else {
872
- this.checkAndEnqueueNextBlockMergeRollup(checkpointProvingState, leafLocation);
840
+ await this.checkAndEnqueueNextBlockMergeRollup(checkpointProvingState, leafLocation);
873
841
  }
874
842
  },
875
843
  );
@@ -883,12 +851,12 @@ export class ProvingOrchestrator implements EpochProver {
883
851
  baseParityIndex: number,
884
852
  ) {
885
853
  if (!provingState.verifyState()) {
886
- logger.debug('Not running base parity. State no longer valid.');
854
+ this.logger.debug('Not running base parity. State no longer valid.');
887
855
  return;
888
856
  }
889
857
 
890
858
  if (!provingState.tryStartProvingBaseParity(baseParityIndex)) {
891
- logger.warn(`Base parity ${baseParityIndex} already started.`);
859
+ this.logger.warn(`Base parity ${baseParityIndex} already started.`);
892
860
  return;
893
861
  }
894
862
 
@@ -923,12 +891,12 @@ export class ProvingOrchestrator implements EpochProver {
923
891
  // Enqueues the root rollup proof if all inputs are available
924
892
  private enqueueRootParityCircuit(provingState: BlockProvingState) {
925
893
  if (!provingState.verifyState()) {
926
- logger.debug('Not running root parity. State no longer valid.');
894
+ this.logger.debug('Not running root parity. State no longer valid.');
927
895
  return;
928
896
  }
929
897
 
930
898
  if (!provingState.tryStartProvingRootParity()) {
931
- logger.debug('Root parity already started.');
899
+ this.logger.debug('Root parity already started.');
932
900
  return;
933
901
  }
934
902
 
@@ -955,12 +923,12 @@ export class ProvingOrchestrator implements EpochProver {
955
923
  // Enqueues the next level of merge if all inputs are available
956
924
  private enqueueBlockMergeRollup(provingState: CheckpointProvingState, location: TreeNodeLocation) {
957
925
  if (!provingState.verifyState()) {
958
- logger.debug('Not running block merge rollup. State no longer valid.');
926
+ this.logger.debug('Not running block merge rollup. State no longer valid.');
959
927
  return;
960
928
  }
961
929
 
962
930
  if (!provingState.tryStartProvingBlockMerge(location)) {
963
- logger.debug('Block merge rollup already started.');
931
+ this.logger.debug('Block merge rollup already started.');
964
932
  return;
965
933
  }
966
934
 
@@ -975,29 +943,34 @@ export class ProvingOrchestrator implements EpochProver {
975
943
  },
976
944
  signal => this.prover.getBlockMergeRollupProof(inputs, signal, provingState.epochNumber),
977
945
  ),
978
- result => {
946
+ async result => {
947
+ this.logger.debug(`Completed block merge rollup proof for checkpoint ${provingState.index}`, {
948
+ checkpointIndex: provingState.index,
949
+ mergeLocation: location,
950
+ ...result.inputs.toInspect(),
951
+ });
979
952
  provingState.setBlockMergeRollupProof(location, result);
980
- this.checkAndEnqueueNextBlockMergeRollup(provingState, location);
953
+ await this.checkAndEnqueueNextBlockMergeRollup(provingState, location);
981
954
  },
982
955
  );
983
956
  }
984
957
 
985
- private enqueueCheckpointRootRollup(provingState: CheckpointProvingState) {
958
+ private async enqueueCheckpointRootRollup(provingState: CheckpointProvingState) {
986
959
  if (!provingState.verifyState()) {
987
- logger.debug('Not running checkpoint root rollup. State no longer valid.');
960
+ this.logger.debug('Not running checkpoint root rollup. State no longer valid.');
988
961
  return;
989
962
  }
990
963
 
991
964
  if (!provingState.tryStartProvingCheckpointRoot()) {
992
- logger.debug('Checkpoint root rollup already started.');
965
+ this.logger.debug('Checkpoint root rollup already started.');
993
966
  return;
994
967
  }
995
968
 
996
969
  const rollupType = provingState.getCheckpointRootRollupType();
997
970
 
998
- logger.debug(`Enqueuing ${rollupType} for checkpoint ${provingState.index}.`);
971
+ this.logger.debug(`Enqueuing ${rollupType} for checkpoint ${provingState.index}.`);
999
972
 
1000
- const inputs = provingState.getCheckpointRootRollupInputs();
973
+ const inputs = await provingState.getCheckpointRootRollupInputs();
1001
974
 
1002
975
  this.deferredProving(
1003
976
  provingState,
@@ -1019,7 +992,7 @@ export class ProvingOrchestrator implements EpochProver {
1019
992
  const computedEndBlobAccumulatorState = provingState.getEndBlobAccumulator()!.toBlobAccumulator();
1020
993
  const circuitEndBlobAccumulatorState = result.inputs.endBlobAccumulator;
1021
994
  if (!circuitEndBlobAccumulatorState.equals(computedEndBlobAccumulatorState)) {
1022
- logger.error(
995
+ this.logger.error(
1023
996
  `Blob accumulator state mismatch.\nCircuit: ${inspect(circuitEndBlobAccumulatorState)}\nComputed: ${inspect(
1024
997
  computedEndBlobAccumulatorState,
1025
998
  )}`,
@@ -1028,7 +1001,10 @@ export class ProvingOrchestrator implements EpochProver {
1028
1001
  return;
1029
1002
  }
1030
1003
 
1031
- logger.debug(`Completed ${rollupType} proof for checkpoint ${provingState.index}.`);
1004
+ this.logger.debug(`Completed ${rollupType} proof for checkpoint ${provingState.index}`, {
1005
+ checkpointIndex: provingState.index,
1006
+ ...result.inputs.toInspect(),
1007
+ });
1032
1008
 
1033
1009
  const leafLocation = provingState.setCheckpointRootRollupProof(result);
1034
1010
  const epochProvingState = provingState.parentEpoch;
@@ -1042,99 +1018,6 @@ export class ProvingOrchestrator implements EpochProver {
1042
1018
  );
1043
1019
  }
1044
1020
 
1045
- private enqueueCheckpointMergeRollup(provingState: EpochProvingState, location: TreeNodeLocation) {
1046
- if (!provingState.verifyState()) {
1047
- logger.debug('Not running checkpoint merge rollup. State no longer valid.');
1048
- return;
1049
- }
1050
-
1051
- if (!provingState.tryStartProvingCheckpointMerge(location)) {
1052
- logger.debug('Checkpoint merge rollup already started.');
1053
- return;
1054
- }
1055
-
1056
- const inputs = provingState.getCheckpointMergeRollupInputs(location);
1057
-
1058
- this.deferredProving(
1059
- provingState,
1060
- wrapCallbackInSpan(
1061
- this.tracer,
1062
- 'ProvingOrchestrator.prover.getCheckpointMergeRollupProof',
1063
- {
1064
- [Attributes.PROTOCOL_CIRCUIT_NAME]: 'rollup-checkpoint-merge' satisfies CircuitName,
1065
- },
1066
- signal => this.prover.getCheckpointMergeRollupProof(inputs, signal, provingState.epochNumber),
1067
- ),
1068
- result => {
1069
- logger.debug('Completed proof for checkpoint merge rollup.');
1070
- provingState.setCheckpointMergeRollupProof(location, result);
1071
- this.checkAndEnqueueNextCheckpointMergeRollup(provingState, location);
1072
- },
1073
- );
1074
- }
1075
-
1076
- private enqueueEpochPadding(provingState: EpochProvingState) {
1077
- if (!provingState.verifyState()) {
1078
- logger.debug('Not running epoch padding. State no longer valid.');
1079
- return;
1080
- }
1081
-
1082
- if (!provingState.tryStartProvingPaddingCheckpoint()) {
1083
- logger.debug('Padding checkpoint already started.');
1084
- return;
1085
- }
1086
-
1087
- logger.debug('Padding epoch proof with a padding block root proof.');
1088
-
1089
- const inputs = provingState.getPaddingCheckpointInputs();
1090
-
1091
- this.deferredProving(
1092
- provingState,
1093
- wrapCallbackInSpan(
1094
- this.tracer,
1095
- 'ProvingOrchestrator.prover.getCheckpointPaddingRollupProof',
1096
- {
1097
- [Attributes.PROTOCOL_CIRCUIT_NAME]: 'rollup-checkpoint-padding' satisfies CircuitName,
1098
- },
1099
- signal => this.prover.getCheckpointPaddingRollupProof(inputs, signal, provingState.epochNumber),
1100
- ),
1101
- result => {
1102
- logger.debug('Completed proof for padding checkpoint.');
1103
- provingState.setCheckpointPaddingProof(result);
1104
- this.checkAndEnqueueRootRollup(provingState);
1105
- },
1106
- );
1107
- }
1108
-
1109
- // Executes the root rollup circuit
1110
- private enqueueRootRollup(provingState: EpochProvingState) {
1111
- if (!provingState.verifyState()) {
1112
- logger.debug('Not running root rollup, state no longer valid');
1113
- return;
1114
- }
1115
-
1116
- logger.debug(`Preparing root rollup`);
1117
-
1118
- const inputs = provingState.getRootRollupInputs();
1119
-
1120
- this.deferredProving(
1121
- provingState,
1122
- wrapCallbackInSpan(
1123
- this.tracer,
1124
- 'ProvingOrchestrator.prover.getRootRollupProof',
1125
- {
1126
- [Attributes.PROTOCOL_CIRCUIT_NAME]: 'rollup-root' satisfies CircuitName,
1127
- },
1128
- signal => this.prover.getRootRollupProof(inputs, signal, provingState.epochNumber),
1129
- ),
1130
- result => {
1131
- logger.verbose(`Orchestrator completed root rollup for epoch ${provingState.epochNumber}`);
1132
- provingState.setRootRollupProof(result);
1133
- provingState.resolve({ status: 'success' });
1134
- },
1135
- );
1136
- }
1137
-
1138
1021
  private checkAndEnqueueNextMergeRollup(provingState: BlockProvingState, currentLocation: TreeNodeLocation) {
1139
1022
  if (!provingState.isReadyForMergeRollup(currentLocation)) {
1140
1023
  return;
@@ -1150,54 +1033,35 @@ export class ProvingOrchestrator implements EpochProver {
1150
1033
 
1151
1034
  private checkAndEnqueueBlockRootRollup(provingState: BlockProvingState) {
1152
1035
  if (!provingState.isReadyForBlockRootRollup()) {
1153
- logger.debug('Not ready for block root rollup');
1036
+ this.logger.debug('Not ready for block root rollup');
1154
1037
  return;
1155
1038
  }
1156
1039
 
1157
1040
  this.enqueueBlockRootRollup(provingState);
1158
1041
  }
1159
1042
 
1160
- private checkAndEnqueueNextBlockMergeRollup(provingState: CheckpointProvingState, currentLocation: TreeNodeLocation) {
1043
+ private async checkAndEnqueueNextBlockMergeRollup(
1044
+ provingState: CheckpointProvingState,
1045
+ currentLocation: TreeNodeLocation,
1046
+ ) {
1161
1047
  if (!provingState.isReadyForBlockMerge(currentLocation)) {
1162
1048
  return;
1163
1049
  }
1164
1050
 
1165
1051
  const parentLocation = provingState.getParentLocation(currentLocation);
1166
1052
  if (parentLocation.level === 0) {
1167
- this.checkAndEnqueueCheckpointRootRollup(provingState);
1053
+ await this.checkAndEnqueueCheckpointRootRollup(provingState);
1168
1054
  } else {
1169
1055
  this.enqueueBlockMergeRollup(provingState, parentLocation);
1170
1056
  }
1171
1057
  }
1172
1058
 
1173
- private checkAndEnqueueCheckpointRootRollup(provingState: CheckpointProvingState) {
1059
+ protected async checkAndEnqueueCheckpointRootRollup(provingState: CheckpointProvingState) {
1174
1060
  if (!provingState.isReadyForCheckpointRoot()) {
1175
1061
  return;
1176
1062
  }
1177
1063
 
1178
- this.enqueueCheckpointRootRollup(provingState);
1179
- }
1180
-
1181
- private checkAndEnqueueNextCheckpointMergeRollup(provingState: EpochProvingState, currentLocation: TreeNodeLocation) {
1182
- if (!provingState.isReadyForCheckpointMerge(currentLocation)) {
1183
- return;
1184
- }
1185
-
1186
- const parentLocation = provingState.getParentLocation(currentLocation);
1187
- if (parentLocation.level === 0) {
1188
- this.checkAndEnqueueRootRollup(provingState);
1189
- } else {
1190
- this.enqueueCheckpointMergeRollup(provingState, parentLocation);
1191
- }
1192
- }
1193
-
1194
- private checkAndEnqueueRootRollup(provingState: EpochProvingState) {
1195
- if (!provingState.isReadyForRootRollup()) {
1196
- logger.debug('Not ready for root rollup');
1197
- return;
1198
- }
1199
-
1200
- this.enqueueRootRollup(provingState);
1064
+ await this.enqueueCheckpointRootRollup(provingState);
1201
1065
  }
1202
1066
 
1203
1067
  /**
@@ -1208,14 +1072,12 @@ export class ProvingOrchestrator implements EpochProver {
1208
1072
  */
1209
1073
  private enqueueVM(provingState: BlockProvingState, txIndex: number) {
1210
1074
  if (!provingState.verifyState()) {
1211
- logger.debug(`Not running VM circuit as state is no longer valid`);
1075
+ this.logger.debug(`Not running VM circuit as state is no longer valid`);
1212
1076
  return;
1213
1077
  }
1214
1078
 
1215
1079
  const txProvingState = provingState.getTxProvingState(txIndex);
1216
1080
 
1217
- // This function tries to do AVM proving. If there is a failure, it fakes the proof unless AVM_PROVING_STRICT is defined.
1218
- // Nothing downstream depends on the AVM proof yet. So having this mode lets us incrementally build the AVM circuit.
1219
1081
  const doAvmProving = wrapCallbackInSpan(
1220
1082
  this.tracer,
1221
1083
  'ProvingOrchestrator.prover.getAvmProof',
@@ -1224,48 +1086,25 @@ export class ProvingOrchestrator implements EpochProver {
1224
1086
  },
1225
1087
  async (signal: AbortSignal) => {
1226
1088
  const inputs = txProvingState.getAvmInputs();
1227
- try {
1228
- // TODO(#14234)[Unconditional PIs validation]: Remove the whole try-catch logic and
1229
- // just keep the next line but removing the second argument (false).
1230
- return await this.prover.getAvmProof(inputs, false, signal, provingState.epochNumber);
1231
- } catch (err) {
1232
- if (process.env.AVM_PROVING_STRICT) {
1233
- logger.error(`Error thrown when proving AVM circuit with AVM_PROVING_STRICT on`, err);
1234
- throw err;
1235
- } else {
1236
- logger.warn(
1237
- `Error thrown when proving AVM circuit but AVM_PROVING_STRICT is off. Use snapshotted
1238
- AVM inputs and carrying on. ${inspect(err)}.`,
1239
- );
1240
-
1241
- try {
1242
- this.metrics.incAvmFallback();
1243
- const snapshotAvmPrivateInputs = readAvmMinimalPublicTxInputsFromFile();
1244
- return await this.prover.getAvmProof(snapshotAvmPrivateInputs, true, signal, provingState.epochNumber);
1245
- } catch (err) {
1246
- logger.error(`Error thrown when proving snapshotted AVM inputs.`, err);
1247
- throw err;
1248
- }
1249
- }
1250
- }
1089
+ return await this.prover.getAvmProof(inputs, signal, provingState.epochNumber);
1251
1090
  },
1252
1091
  );
1253
1092
 
1254
- this.deferredProving(provingState, doAvmProving, proofAndVk => {
1255
- logger.debug(`Proven VM for tx index: ${txIndex}`);
1256
- txProvingState.setAvmProof(proofAndVk);
1093
+ this.deferredProving(provingState, doAvmProving, proof => {
1094
+ this.logger.debug(`Proven VM for tx index: ${txIndex}`);
1095
+ txProvingState.setAvmProof(proof);
1257
1096
  this.checkAndEnqueueBaseRollup(provingState, txIndex);
1258
1097
  });
1259
1098
  }
1260
1099
 
1261
- private checkAndEnqueueBaseRollup(provingState: BlockProvingState, txIndex: number) {
1100
+ protected checkAndEnqueueBaseRollup(provingState: BlockProvingState, txIndex: number) {
1262
1101
  const txProvingState = provingState.getTxProvingState(txIndex);
1263
1102
  if (!txProvingState.ready()) {
1264
1103
  return;
1265
1104
  }
1266
1105
 
1267
1106
  // We must have completed all proving (chonk verifier proof and (if required) vm proof are generated), we now move to the base rollup.
1268
- logger.debug(`Public functions completed for tx ${txIndex} enqueueing base rollup`);
1107
+ this.logger.debug(`Public functions completed for tx ${txIndex} enqueueing base rollup`);
1269
1108
 
1270
1109
  this.enqueueBaseRollup(provingState, txIndex);
1271
1110
  }