@aztec/prover-client 0.0.0-test.1 → 0.0.1-commit.b655e406

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 (121) hide show
  1. package/dest/block-factory/index.d.ts +2 -0
  2. package/dest/block-factory/index.d.ts.map +1 -0
  3. package/dest/block-factory/light.d.ts +38 -0
  4. package/dest/block-factory/light.d.ts.map +1 -0
  5. package/dest/block-factory/light.js +94 -0
  6. package/dest/config.d.ts +6 -6
  7. package/dest/config.d.ts.map +1 -1
  8. package/dest/config.js +11 -1
  9. package/dest/mocks/fixtures.d.ts +7 -4
  10. package/dest/mocks/fixtures.d.ts.map +1 -1
  11. package/dest/mocks/fixtures.js +32 -4
  12. package/dest/mocks/test_context.d.ts +43 -15
  13. package/dest/mocks/test_context.d.ts.map +1 -1
  14. package/dest/mocks/test_context.js +110 -48
  15. package/dest/orchestrator/block-building-helpers.d.ts +37 -28
  16. package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
  17. package/dest/orchestrator/block-building-helpers.js +156 -150
  18. package/dest/orchestrator/block-proving-state.d.ts +62 -46
  19. package/dest/orchestrator/block-proving-state.d.ts.map +1 -1
  20. package/dest/orchestrator/block-proving-state.js +223 -179
  21. package/dest/orchestrator/checkpoint-proving-state.d.ts +63 -0
  22. package/dest/orchestrator/checkpoint-proving-state.d.ts.map +1 -0
  23. package/dest/orchestrator/checkpoint-proving-state.js +211 -0
  24. package/dest/orchestrator/epoch-proving-state.d.ts +37 -24
  25. package/dest/orchestrator/epoch-proving-state.d.ts.map +1 -1
  26. package/dest/orchestrator/epoch-proving-state.js +143 -73
  27. package/dest/orchestrator/orchestrator.d.ts +34 -31
  28. package/dest/orchestrator/orchestrator.d.ts.map +1 -1
  29. package/dest/orchestrator/orchestrator.js +392 -234
  30. package/dest/orchestrator/orchestrator_metrics.d.ts +2 -0
  31. package/dest/orchestrator/orchestrator_metrics.d.ts.map +1 -1
  32. package/dest/orchestrator/orchestrator_metrics.js +9 -0
  33. package/dest/orchestrator/tx-proving-state.d.ts +12 -10
  34. package/dest/orchestrator/tx-proving-state.d.ts.map +1 -1
  35. package/dest/orchestrator/tx-proving-state.js +30 -38
  36. package/dest/prover-client/prover-client.d.ts +3 -3
  37. package/dest/prover-client/prover-client.d.ts.map +1 -1
  38. package/dest/prover-client/prover-client.js +5 -4
  39. package/dest/prover-client/server-epoch-prover.d.ts +13 -10
  40. package/dest/prover-client/server-epoch-prover.d.ts.map +1 -1
  41. package/dest/prover-client/server-epoch-prover.js +11 -11
  42. package/dest/proving_broker/broker_prover_facade.d.ts +22 -15
  43. package/dest/proving_broker/broker_prover_facade.d.ts.map +1 -1
  44. package/dest/proving_broker/broker_prover_facade.js +64 -39
  45. package/dest/proving_broker/config.d.ts +9 -4
  46. package/dest/proving_broker/config.d.ts.map +1 -1
  47. package/dest/proving_broker/config.js +15 -4
  48. package/dest/proving_broker/factory.d.ts +1 -1
  49. package/dest/proving_broker/factory.d.ts.map +1 -1
  50. package/dest/proving_broker/factory.js +5 -1
  51. package/dest/proving_broker/fixtures.js +1 -1
  52. package/dest/proving_broker/proof_store/factory.js +1 -1
  53. package/dest/proving_broker/proof_store/gcs_proof_store.d.ts.map +1 -1
  54. package/dest/proving_broker/proof_store/gcs_proof_store.js +1 -0
  55. package/dest/proving_broker/proof_store/index.d.ts +1 -0
  56. package/dest/proving_broker/proof_store/index.d.ts.map +1 -1
  57. package/dest/proving_broker/proof_store/index.js +1 -0
  58. package/dest/proving_broker/proving_agent.d.ts +3 -3
  59. package/dest/proving_broker/proving_agent.d.ts.map +1 -1
  60. package/dest/proving_broker/proving_agent.js +83 -47
  61. package/dest/proving_broker/proving_broker.d.ts +11 -2
  62. package/dest/proving_broker/proving_broker.d.ts.map +1 -1
  63. package/dest/proving_broker/proving_broker.js +34 -22
  64. package/dest/proving_broker/proving_broker_database/memory.js +1 -1
  65. package/dest/proving_broker/proving_broker_database/persisted.d.ts.map +1 -1
  66. package/dest/proving_broker/proving_broker_database/persisted.js +9 -8
  67. package/dest/proving_broker/proving_job_controller.d.ts +7 -8
  68. package/dest/proving_broker/proving_job_controller.d.ts.map +1 -1
  69. package/dest/proving_broker/proving_job_controller.js +89 -61
  70. package/dest/proving_broker/rpc.d.ts +3 -5
  71. package/dest/proving_broker/rpc.d.ts.map +1 -1
  72. package/dest/proving_broker/rpc.js +1 -4
  73. package/dest/test/mock_proof_store.d.ts +9 -0
  74. package/dest/test/mock_proof_store.d.ts.map +1 -0
  75. package/dest/test/mock_proof_store.js +10 -0
  76. package/dest/test/mock_prover.d.ts +23 -16
  77. package/dest/test/mock_prover.d.ts.map +1 -1
  78. package/dest/test/mock_prover.js +38 -20
  79. package/package.json +29 -29
  80. package/src/block-factory/index.ts +1 -0
  81. package/src/block-factory/light.ts +140 -0
  82. package/src/config.ts +24 -8
  83. package/src/mocks/fixtures.ts +43 -15
  84. package/src/mocks/test_context.ts +201 -75
  85. package/src/orchestrator/block-building-helpers.ts +247 -243
  86. package/src/orchestrator/block-proving-state.ts +247 -231
  87. package/src/orchestrator/checkpoint-proving-state.ts +299 -0
  88. package/src/orchestrator/epoch-proving-state.ts +187 -111
  89. package/src/orchestrator/orchestrator.ts +590 -289
  90. package/src/orchestrator/orchestrator_metrics.ts +20 -1
  91. package/src/orchestrator/tx-proving-state.ts +60 -61
  92. package/src/prover-client/prover-client.ts +16 -14
  93. package/src/prover-client/server-epoch-prover.ts +40 -21
  94. package/src/proving_broker/broker_prover_facade.ts +200 -113
  95. package/src/proving_broker/config.ts +17 -6
  96. package/src/proving_broker/factory.ts +2 -1
  97. package/src/proving_broker/fixtures.ts +1 -1
  98. package/src/proving_broker/proof_store/factory.ts +1 -1
  99. package/src/proving_broker/proof_store/gcs_proof_store.ts +5 -1
  100. package/src/proving_broker/proof_store/index.ts +1 -0
  101. package/src/proving_broker/proof_store/inline_proof_store.ts +1 -1
  102. package/src/proving_broker/proving_agent.ts +89 -47
  103. package/src/proving_broker/proving_broker.ts +51 -32
  104. package/src/proving_broker/proving_broker_database/memory.ts +1 -1
  105. package/src/proving_broker/proving_broker_database/persisted.ts +9 -8
  106. package/src/proving_broker/proving_job_controller.ts +92 -81
  107. package/src/proving_broker/rpc.ts +1 -6
  108. package/src/test/mock_proof_store.ts +14 -0
  109. package/src/test/mock_prover.ts +164 -60
  110. package/dest/bin/get-proof-inputs.d.ts +0 -2
  111. package/dest/bin/get-proof-inputs.d.ts.map +0 -1
  112. package/dest/bin/get-proof-inputs.js +0 -51
  113. package/dest/block_builder/index.d.ts +0 -6
  114. package/dest/block_builder/index.d.ts.map +0 -1
  115. package/dest/block_builder/light.d.ts +0 -33
  116. package/dest/block_builder/light.d.ts.map +0 -1
  117. package/dest/block_builder/light.js +0 -82
  118. package/src/bin/get-proof-inputs.ts +0 -59
  119. package/src/block_builder/index.ts +0 -6
  120. package/src/block_builder/light.ts +0 -101
  121. /package/dest/{block_builder → block-factory}/index.js +0 -0
@@ -1,13 +1,12 @@
1
+ import { BatchedBlob, FinalBlobBatchingChallenges, SpongeBlob } from '@aztec/blob-lib';
1
2
  import {
2
- AVM_PROOF_LENGTH_IN_FIELDS,
3
- AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS,
4
3
  L1_TO_L2_MSG_SUBTREE_HEIGHT,
5
- L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH,
4
+ L1_TO_L2_MSG_SUBTREE_ROOT_SIBLING_PATH_LENGTH,
5
+ NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
6
6
  NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
7
7
  NUM_BASE_PARITY_PER_ROOT_PARITY,
8
- type TUBE_PROOF_LENGTH,
9
8
  } from '@aztec/constants';
10
- import { padArrayEnd, times } from '@aztec/foundation/collection';
9
+ import { padArrayEnd } from '@aztec/foundation/collection';
11
10
  import { AbortError } from '@aztec/foundation/error';
12
11
  import { Fr } from '@aztec/foundation/fields';
13
12
  import { createLogger } from '@aztec/foundation/log';
@@ -16,28 +15,33 @@ import { assertLength } from '@aztec/foundation/serialize';
16
15
  import { pushTestData } from '@aztec/foundation/testing';
17
16
  import { elapsed } from '@aztec/foundation/timer';
18
17
  import type { TreeNodeLocation } from '@aztec/foundation/trees';
19
- import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
20
- import { L2Block } from '@aztec/stdlib/block';
18
+ import { readAvmMinimalPublicTxInputsFromFile } from '@aztec/simulator/public/fixtures';
19
+ import { EthAddress, createBlockEndMarker } from '@aztec/stdlib/block';
21
20
  import type {
22
21
  EpochProver,
23
22
  ForkMerkleTreeOperations,
24
23
  MerkleTreeWriteOperations,
25
- ProofAndVerificationKey,
24
+ PublicInputsAndRecursiveProof,
26
25
  ServerCircuitProver,
27
26
  } from '@aztec/stdlib/interfaces/server';
28
- import { BaseParityInputs } from '@aztec/stdlib/parity';
29
- import { makeEmptyRecursiveProof } from '@aztec/stdlib/proofs';
27
+ import type { Proof } from '@aztec/stdlib/proofs';
30
28
  import {
31
29
  type BaseRollupHints,
32
- EmptyBlockRootRollupInputs,
33
- PrivateBaseRollupInputs,
34
- SingleTxBlockRootRollupInputs,
35
- TubeInputs,
30
+ BlockRootEmptyTxFirstRollupPrivateInputs,
31
+ BlockRootFirstRollupPrivateInputs,
32
+ BlockRootSingleTxFirstRollupPrivateInputs,
33
+ BlockRootSingleTxRollupPrivateInputs,
34
+ CheckpointConstantData,
35
+ CheckpointRootSingleBlockRollupPrivateInputs,
36
+ PrivateTxBaseRollupPrivateInputs,
37
+ PublicChonkVerifierPrivateInputs,
38
+ PublicChonkVerifierPublicInputs,
39
+ RootRollupPublicInputs,
36
40
  } from '@aztec/stdlib/rollup';
37
41
  import type { CircuitName } from '@aztec/stdlib/stats';
38
42
  import { type AppendOnlyTreeSnapshot, MerkleTreeId } from '@aztec/stdlib/trees';
39
- import { type BlockHeader, type GlobalVariables, type ProcessedTx, type Tx, toNumBlobFields } from '@aztec/stdlib/tx';
40
- import { VerificationKeyData } from '@aztec/stdlib/vks';
43
+ import type { BlockHeader, ProcessedTx, Tx } from '@aztec/stdlib/tx';
44
+ import type { UInt64 } from '@aztec/stdlib/types';
41
45
  import {
42
46
  Attributes,
43
47
  type TelemetryClient,
@@ -50,15 +54,19 @@ import {
50
54
  import { inspect } from 'util';
51
55
 
52
56
  import {
53
- buildBaseRollupHints,
54
- buildHeaderAndBodyFromTxs,
57
+ buildBlockHeaderFromTxs,
58
+ buildHeaderFromCircuitOutputs,
59
+ getLastSiblingPath,
60
+ getPublicChonkVerifierPrivateInputsFromTx,
55
61
  getRootTreeSiblingPath,
56
62
  getSubtreeSiblingPath,
57
63
  getTreeSnapshot,
64
+ insertSideEffectsAndBuildBaseRollupHints,
58
65
  validatePartialState,
59
66
  validateTx,
60
67
  } from './block-building-helpers.js';
61
68
  import type { BlockProvingState } from './block-proving-state.js';
69
+ import type { CheckpointProvingState } from './checkpoint-proving-state.js';
62
70
  import { EpochProvingState, type ProvingResult, type TreeSnapshots } from './epoch-proving-state.js';
63
71
  import { ProvingOrchestratorMetrics } from './orchestrator_metrics.js';
64
72
  import { TxProvingState } from './tx-proving-state.js';
@@ -90,7 +98,7 @@ export class ProvingOrchestrator implements EpochProver {
90
98
  constructor(
91
99
  private dbProvider: ForkMerkleTreeOperations,
92
100
  private prover: ServerCircuitProver,
93
- private readonly proverId: Fr = Fr.ZERO,
101
+ private readonly proverId: EthAddress,
94
102
  telemetryClient: TelemetryClient = getTelemetryClient(),
95
103
  ) {
96
104
  this.metrics = new ProvingOrchestratorMetrics(telemetryClient, 'ProvingOrchestrator');
@@ -100,7 +108,7 @@ export class ProvingOrchestrator implements EpochProver {
100
108
  return this.metrics.tracer;
101
109
  }
102
110
 
103
- public getProverId(): Fr {
111
+ public getProverId(): EthAddress {
104
112
  return this.proverId;
105
113
  }
106
114
 
@@ -109,64 +117,143 @@ export class ProvingOrchestrator implements EpochProver {
109
117
  return Promise.resolve();
110
118
  }
111
119
 
112
- public startNewEpoch(epochNumber: number, firstBlockNumber: number, totalNumBlocks: number) {
120
+ public startNewEpoch(
121
+ epochNumber: number,
122
+ totalNumCheckpoints: number,
123
+ finalBlobBatchingChallenges: FinalBlobBatchingChallenges,
124
+ ) {
125
+ if (this.provingState?.verifyState()) {
126
+ throw new Error(
127
+ `Cannot start epoch ${epochNumber} when epoch ${this.provingState.epochNumber} is still being processed.`,
128
+ );
129
+ }
130
+
113
131
  const { promise: _promise, resolve, reject } = promiseWithResolvers<ProvingResult>();
114
132
  const promise = _promise.catch((reason): ProvingResult => ({ status: 'failure', reason }));
115
- if (totalNumBlocks <= 0 || !Number.isInteger(totalNumBlocks)) {
116
- throw new Error(`Invalid number of blocks for epoch (got ${totalNumBlocks})`);
117
- }
118
- logger.info(`Starting epoch ${epochNumber} with ${totalNumBlocks} blocks`);
119
- this.provingState = new EpochProvingState(epochNumber, firstBlockNumber, totalNumBlocks, resolve, reject);
133
+ logger.info(`Starting epoch ${epochNumber} with ${totalNumCheckpoints} checkpoints.`);
134
+ this.provingState = new EpochProvingState(
135
+ epochNumber,
136
+ totalNumCheckpoints,
137
+ finalBlobBatchingChallenges,
138
+ provingState => this.checkAndEnqueueCheckpointRootRollup(provingState),
139
+ resolve,
140
+ reject,
141
+ );
120
142
  this.provingPromise = promise;
121
143
  }
122
144
 
145
+ public async startNewCheckpoint(
146
+ checkpointIndex: number,
147
+ constants: CheckpointConstantData,
148
+ l1ToL2Messages: Fr[],
149
+ totalNumBlocks: number,
150
+ totalNumBlobFields: number,
151
+ headerOfLastBlockInPreviousCheckpoint: BlockHeader,
152
+ ) {
153
+ if (!this.provingState) {
154
+ throw new Error('Empty epoch proving state. Call startNewEpoch before starting a checkpoint.');
155
+ }
156
+
157
+ if (!this.provingState.isAcceptingCheckpoints()) {
158
+ throw new Error(`Epoch not accepting further checkpoints.`);
159
+ }
160
+
161
+ // Fork world state at the end of the immediately previous block.
162
+ const lastBlockNumber = headerOfLastBlockInPreviousCheckpoint.globalVariables.blockNumber;
163
+ const db = await this.dbProvider.fork(lastBlockNumber);
164
+
165
+ const firstBlockNumber = lastBlockNumber + 1;
166
+ this.dbs.set(firstBlockNumber, db);
167
+
168
+ // Get archive sibling path before any block in this checkpoint lands.
169
+ const lastArchiveSiblingPath = await getLastSiblingPath(MerkleTreeId.ARCHIVE, db);
170
+
171
+ // Insert all the l1 to l2 messages into the db. And get the states before and after the insertion.
172
+ const {
173
+ lastL1ToL2MessageTreeSnapshot,
174
+ lastL1ToL2MessageSubtreeRootSiblingPath,
175
+ newL1ToL2MessageTreeSnapshot,
176
+ newL1ToL2MessageSubtreeRootSiblingPath,
177
+ } = await this.updateL1ToL2MessageTree(l1ToL2Messages, db);
178
+
179
+ this.provingState.startNewCheckpoint(
180
+ checkpointIndex,
181
+ constants,
182
+ totalNumBlocks,
183
+ totalNumBlobFields,
184
+ headerOfLastBlockInPreviousCheckpoint,
185
+ lastArchiveSiblingPath,
186
+ l1ToL2Messages,
187
+ lastL1ToL2MessageTreeSnapshot,
188
+ lastL1ToL2MessageSubtreeRootSiblingPath,
189
+ newL1ToL2MessageTreeSnapshot,
190
+ newL1ToL2MessageSubtreeRootSiblingPath,
191
+ );
192
+ }
193
+
123
194
  /**
124
195
  * Starts off a new block
125
- * @param globalVariables - The global variables for the block
126
- * @param l1ToL2Messages - The l1 to l2 messages for the block
127
- * @returns A proving ticket, containing a promise notifying of proving completion
196
+ * @param blockNumber - The block number
197
+ * @param timestamp - The timestamp of the block. This is only required for constructing the private inputs for the
198
+ * block that doesn't have any txs.
199
+ * @param totalNumTxs - The total number of txs in the block
128
200
  */
129
- @trackSpan('ProvingOrchestrator.startNewBlock', globalVariables => ({
130
- [Attributes.BLOCK_NUMBER]: globalVariables.blockNumber.toNumber(),
201
+ @trackSpan('ProvingOrchestrator.startNewBlock', blockNumber => ({
202
+ [Attributes.BLOCK_NUMBER]: blockNumber,
131
203
  }))
132
- public async startNewBlock(globalVariables: GlobalVariables, l1ToL2Messages: Fr[], previousBlockHeader: BlockHeader) {
204
+ public async startNewBlock(blockNumber: number, timestamp: UInt64, totalNumTxs: number) {
133
205
  if (!this.provingState) {
134
- throw new Error(`Invalid proving state, call startNewEpoch before starting a block`);
206
+ throw new Error('Empty epoch proving state. Call startNewEpoch before starting a block.');
135
207
  }
136
208
 
137
- if (!this.provingState?.isAcceptingBlocks()) {
138
- throw new Error(`Epoch not accepting further blocks`);
209
+ const checkpointProvingState = this.provingState.getCheckpointProvingStateByBlockNumber(blockNumber);
210
+ if (!checkpointProvingState) {
211
+ throw new Error(`Checkpoint not started. Call startNewCheckpoint first.`);
139
212
  }
140
213
 
141
- logger.info(
142
- `Starting block ${globalVariables.blockNumber.toNumber()} for slot ${globalVariables.slotNumber.toNumber()}`,
143
- );
214
+ if (!checkpointProvingState.isAcceptingBlocks()) {
215
+ throw new Error(`Checkpoint not accepting further blocks.`);
216
+ }
144
217
 
145
- // Fork world state at the end of the immediately previous block
146
- const db = await this.dbProvider.fork(globalVariables.blockNumber.toNumber() - 1);
147
- this.dbs.set(globalVariables.blockNumber.toNumber(), db);
218
+ const constants = checkpointProvingState.constants;
219
+ logger.info(`Starting block ${blockNumber} for slot ${constants.slotNumber.toNumber()}.`);
148
220
 
149
- // we start the block by enqueueing all of the base parity circuits
150
- const { l1ToL2MessageSubtreeSiblingPath, l1ToL2MessageTreeSnapshotAfterInsertion, baseParityInputs } =
151
- await this.prepareBaseParityInputs(l1ToL2Messages, db);
221
+ // Fork the db only when it's not already set. The db for the first block is set in `startNewCheckpoint`.
222
+ if (!this.dbs.has(blockNumber)) {
223
+ // Fork world state at the end of the immediately previous block
224
+ const db = await this.dbProvider.fork(blockNumber - 1);
225
+ this.dbs.set(blockNumber, db);
226
+ }
227
+ const db = this.dbs.get(blockNumber)!;
228
+
229
+ // Get archive snapshot and sibling path before any txs in this block lands.
230
+ const lastArchiveTreeSnapshot = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
231
+ const lastArchiveSiblingPath = await getRootTreeSiblingPath(MerkleTreeId.ARCHIVE, db);
232
+
233
+ const blockProvingState = await checkpointProvingState.startNewBlock(
234
+ blockNumber,
235
+ timestamp,
236
+ totalNumTxs,
237
+ lastArchiveTreeSnapshot,
238
+ lastArchiveSiblingPath,
239
+ );
152
240
 
153
- // Get archive snapshot before this block lands
154
- const lastArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
155
- const newArchiveSiblingPath = await getRootTreeSiblingPath(MerkleTreeId.ARCHIVE, db);
241
+ // Enqueue base parity circuits for the first block in the checkpoint.
242
+ if (blockProvingState.index === 0) {
243
+ for (let i = 0; i < NUM_BASE_PARITY_PER_ROOT_PARITY; i++) {
244
+ this.enqueueBaseParityCircuit(checkpointProvingState, blockProvingState, i);
245
+ }
246
+ }
156
247
 
157
- const blockProvingState = this.provingState!.startNewBlock(
158
- globalVariables,
159
- l1ToL2Messages,
160
- l1ToL2MessageSubtreeSiblingPath,
161
- l1ToL2MessageTreeSnapshotAfterInsertion,
162
- lastArchive,
163
- newArchiveSiblingPath,
164
- previousBlockHeader,
165
- );
248
+ // Because `addTxs` won't be called for a block without txs, and that's where the sponge blob state is computed.
249
+ // We need to set its end sponge blob here, which will become the start sponge blob for the next block.
250
+ if (totalNumTxs === 0) {
251
+ const endSpongeBlob = blockProvingState.getStartSpongeBlob().clone();
252
+ await endSpongeBlob.absorb([createBlockEndMarker(0)]);
253
+ blockProvingState.setEndSpongeBlob(endSpongeBlob);
166
254
 
167
- // Enqueue base parity circuits for the block
168
- for (let i = 0; i < baseParityInputs.length; i++) {
169
- this.enqueueBaseParityCircuit(blockProvingState, baseParityInputs[i], i);
255
+ // And also try to accumulate the blobs as far as we can:
256
+ await this.provingState.setBlobAccumulators();
170
257
  }
171
258
  }
172
259
 
@@ -178,28 +265,40 @@ export class ProvingOrchestrator implements EpochProver {
178
265
  [Attributes.BLOCK_TXS_COUNT]: txs.length,
179
266
  }))
180
267
  public async addTxs(txs: ProcessedTx[]): Promise<void> {
268
+ if (!this.provingState) {
269
+ throw new Error(`Empty epoch proving state. Call startNewEpoch before adding txs.`);
270
+ }
271
+
181
272
  if (!txs.length) {
182
273
  // To avoid an ugly throw below. If we require an empty block, we can just call setBlockCompleted
183
274
  // on a block with no txs. We cannot do that here because we cannot find the blockNumber without any txs.
184
275
  logger.warn(`Provided no txs to orchestrator addTxs.`);
185
276
  return;
186
277
  }
187
- const blockNumber = txs[0].constants.globalVariables.blockNumber.toNumber();
188
- const provingState = this.provingState?.getBlockProvingStateByBlockNumber(blockNumber!);
278
+
279
+ const blockNumber = txs[0].globalVariables.blockNumber;
280
+ const provingState = this.provingState.getBlockProvingStateByBlockNumber(blockNumber!);
189
281
  if (!provingState) {
190
- throw new Error(`Block proving state for ${blockNumber} not found`);
282
+ throw new Error(`Proving state for block ${blockNumber} not found. Call startNewBlock first.`);
283
+ }
284
+
285
+ if (provingState.totalNumTxs !== txs.length) {
286
+ throw new Error(
287
+ `Block ${blockNumber} should be filled with ${provingState.totalNumTxs} txs. Received ${txs.length} txs.`,
288
+ );
191
289
  }
192
290
 
193
- if (provingState.totalNumTxs) {
291
+ if (!provingState.isAcceptingTxs()) {
194
292
  throw new Error(`Block ${blockNumber} has been initialized with transactions.`);
195
293
  }
196
294
 
197
- const numBlobFields = toNumBlobFields(txs);
198
- provingState.startNewBlock(txs.length, numBlobFields);
295
+ logger.info(`Adding ${txs.length} transactions to block ${blockNumber}`);
296
+
297
+ const db = this.dbs.get(blockNumber)!;
298
+ const lastArchive = provingState.lastArchiveTreeSnapshot;
299
+ const newL1ToL2MessageTreeSnapshot = provingState.newL1ToL2MessageTreeSnapshot;
300
+ const spongeBlobState = provingState.getStartSpongeBlob().clone();
199
301
 
200
- logger.info(
201
- `Adding ${txs.length} transactions with ${numBlobFields} blob fields to block ${provingState.blockNumber}`,
202
- );
203
302
  for (const tx of txs) {
204
303
  try {
205
304
  if (!provingState.verifyState()) {
@@ -210,13 +309,30 @@ export class ProvingOrchestrator implements EpochProver {
210
309
 
211
310
  logger.info(`Received transaction: ${tx.hash}`);
212
311
 
213
- const [hints, treeSnapshots] = await this.prepareTransaction(tx, provingState);
214
- const txProvingState = new TxProvingState(tx, hints, treeSnapshots);
312
+ const startSpongeBlob = spongeBlobState.clone();
313
+ const [hints, treeSnapshots] = await this.prepareBaseRollupInputs(
314
+ tx,
315
+ lastArchive,
316
+ newL1ToL2MessageTreeSnapshot,
317
+ startSpongeBlob,
318
+ db,
319
+ );
320
+
321
+ if (!provingState.verifyState()) {
322
+ throw new Error(`Unable to add transaction, preparing base inputs failed`);
323
+ }
324
+
325
+ await spongeBlobState.absorb(tx.txEffect.toBlobFields());
326
+
327
+ const txProvingState = new TxProvingState(tx, hints, treeSnapshots, this.proverId.toField());
215
328
  const txIndex = provingState.addNewTx(txProvingState);
216
- this.getOrEnqueueTube(provingState, txIndex);
217
329
  if (txProvingState.requireAvmProof) {
330
+ this.getOrEnqueueChonkVerifier(provingState, txIndex);
218
331
  logger.debug(`Enqueueing public VM for tx ${txIndex}`);
219
332
  this.enqueueVM(provingState, txIndex);
333
+ } else {
334
+ logger.debug(`Enqueueing base rollup for private-only tx ${txIndex}`);
335
+ this.enqueueBaseRollup(provingState, txIndex);
220
336
  }
221
337
  } catch (err: any) {
222
338
  throw new Error(`Error adding transaction ${tx.hash.toString()} to block ${blockNumber}: ${err.message}`, {
@@ -224,25 +340,42 @@ export class ProvingOrchestrator implements EpochProver {
224
340
  });
225
341
  }
226
342
  }
343
+
344
+ await spongeBlobState.absorb([createBlockEndMarker(txs.length)]);
345
+
346
+ provingState.setEndSpongeBlob(spongeBlobState);
347
+
348
+ // Txs have been added to the block. Now try to accumulate the blobs as far as we can:
349
+ await this.provingState.setBlobAccumulators();
227
350
  }
228
351
 
229
352
  /**
230
- * Kickstarts tube circuits for the specified txs. These will be used during epoch proving.
231
- * Note that if the tube circuits are not started this way, they will be started nontheless after processing.
353
+ * Kickstarts chonk verifier circuits for the specified txs. These will be used during epoch proving.
354
+ * Note that if the chonk verifier circuits are not started this way, they will be started nontheless after processing.
232
355
  */
233
- @trackSpan('ProvingOrchestrator.startTubeCircuits')
234
- public async startTubeCircuits(txs: Tx[]) {
356
+ @trackSpan('ProvingOrchestrator.startChonkVerifierCircuits')
357
+ public startChonkVerifierCircuits(txs: Tx[]) {
235
358
  if (!this.provingState?.verifyState()) {
236
- throw new Error(`Invalid proving state, call startNewEpoch before starting tube circuits`);
359
+ throw new Error(`Empty epoch proving state. call startNewEpoch before starting chonk verifier circuits.`);
237
360
  }
238
- for (const tx of txs) {
239
- const txHash = (await tx.getTxHash()).toString();
240
- const tubeInputs = new TubeInputs(tx.clientIvcProof);
241
- const tubeProof = promiseWithResolvers<ProofAndVerificationKey<typeof TUBE_PROOF_LENGTH>>();
242
- logger.debug(`Starting tube circuit for tx ${txHash}`);
243
- this.doEnqueueTube(txHash, tubeInputs, proof => tubeProof.resolve(proof));
244
- this.provingState?.cachedTubeProofs.set(txHash, tubeProof.promise);
361
+ const publicTxs = txs.filter(tx => tx.data.forPublic);
362
+ for (const tx of publicTxs) {
363
+ const txHash = tx.getTxHash().toString();
364
+ const privateInputs = getPublicChonkVerifierPrivateInputsFromTx(tx, this.proverId.toField());
365
+ const tubeProof =
366
+ promiseWithResolvers<
367
+ PublicInputsAndRecursiveProof<
368
+ PublicChonkVerifierPublicInputs,
369
+ typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH
370
+ >
371
+ >();
372
+ logger.debug(`Starting chonk verifier circuit for tx ${txHash}`);
373
+ this.doEnqueueChonkVerifier(txHash, privateInputs, proof => {
374
+ tubeProof.resolve(proof);
375
+ });
376
+ this.provingState.cachedChonkVerifierProofs.set(txHash, tubeProof.promise);
245
377
  }
378
+ return Promise.resolve();
246
379
  }
247
380
 
248
381
  /**
@@ -252,55 +385,50 @@ export class ProvingOrchestrator implements EpochProver {
252
385
  @trackSpan('ProvingOrchestrator.setBlockCompleted', (blockNumber: number) => ({
253
386
  [Attributes.BLOCK_NUMBER]: blockNumber,
254
387
  }))
255
- public async setBlockCompleted(blockNumber: number, expectedHeader?: BlockHeader): Promise<L2Block> {
388
+ public async setBlockCompleted(blockNumber: number, expectedHeader?: BlockHeader): Promise<BlockHeader> {
256
389
  const provingState = this.provingState?.getBlockProvingStateByBlockNumber(blockNumber);
257
390
  if (!provingState) {
258
391
  throw new Error(`Block proving state for ${blockNumber} not found`);
259
392
  }
260
393
 
261
- if (!provingState.spongeBlobState) {
262
- // If we are completing an empty block, initialise the provingState.
263
- // We will have 0 txs and no blob fields.
264
- provingState.startNewBlock(0, 0);
394
+ // Abort with specific error for the block if there's one.
395
+ const error = provingState.getError();
396
+ if (error) {
397
+ throw new Error(`Block proving failed: ${error}`);
265
398
  }
266
399
 
400
+ // Abort if the proving state is not valid due to errors occurred elsewhere.
267
401
  if (!provingState.verifyState()) {
268
- throw new Error(`Block proving failed: ${provingState.error}`);
402
+ throw new Error(`Invalid proving state when completing block ${blockNumber}.`);
403
+ }
404
+
405
+ if (provingState.isAcceptingTxs()) {
406
+ throw new Error(
407
+ `Block ${blockNumber} is still accepting txs. Call setBlockCompleted after all txs have been added.`,
408
+ );
269
409
  }
270
410
 
271
411
  // And build the block header
272
412
  logger.verbose(`Block ${blockNumber} completed. Assembling header.`);
273
- await this.buildBlock(provingState, expectedHeader);
413
+ const header = await this.buildL2BlockHeader(provingState, expectedHeader);
274
414
 
275
- // If the proofs were faster than the block building, then we need to try the block root rollup again here
276
- await this.checkAndEnqueueBlockRootRollup(provingState);
277
- return provingState.block!;
278
- }
415
+ await this.verifyBuiltBlockAgainstSyncedState(provingState);
279
416
 
280
- /** Returns the block as built for a given index. */
281
- public getBlock(index: number): L2Block {
282
- const block = this.provingState?.blocks[index]?.block;
283
- if (!block) {
284
- throw new Error(`Block at index ${index} not available`);
285
- }
286
- return block;
417
+ return header;
287
418
  }
288
419
 
289
- private async buildBlock(provingState: BlockProvingState, expectedHeader?: BlockHeader) {
290
- // Collect all new nullifiers, commitments, and contracts from all txs in this block to build body
291
- const txs = provingState.allTxs.map(a => a.processedTx);
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();
292
425
 
293
426
  // Get db for this block
294
427
  const db = this.dbs.get(provingState.blockNumber)!;
295
428
 
296
429
  // Given we've applied every change from this block, now assemble the block header
297
430
  // and update the archive tree, so we're ready to start processing the next block
298
- const { header, body } = await buildHeaderAndBodyFromTxs(
299
- txs,
300
- provingState.globalVariables,
301
- provingState.newL1ToL2Messages,
302
- db,
303
- );
431
+ const header = await buildBlockHeaderFromTxs(txs, provingState.getGlobalVariables(), startSpongeBlob, db);
304
432
 
305
433
  if (expectedHeader && !header.equals(expectedHeader)) {
306
434
  logger.error(`Block header mismatch: header=${header} expectedHeader=${expectedHeader}`);
@@ -312,26 +440,65 @@ export class ProvingOrchestrator implements EpochProver {
312
440
  );
313
441
  await db.updateArchive(header);
314
442
 
315
- // Assemble the L2 block
316
- const newArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
317
- const l2Block = new L2Block(newArchive, header, body);
318
-
319
- await this.verifyBuiltBlockAgainstSyncedState(l2Block, newArchive);
443
+ provingState.setBuiltBlockHeader(header);
320
444
 
321
- logger.verbose(`Orchestrator finalised block ${l2Block.number}`);
322
- provingState.block = l2Block;
445
+ return header;
323
446
  }
324
447
 
325
448
  // Flagged as protected to disable in certain unit tests
326
- protected async verifyBuiltBlockAgainstSyncedState(l2Block: L2Block, newArchive: AppendOnlyTreeSnapshot) {
327
- const syncedArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, this.dbProvider.getSnapshot(l2Block.number));
449
+ protected async verifyBuiltBlockAgainstSyncedState(provingState: BlockProvingState) {
450
+ const builtBlockHeader = provingState.getBuiltBlockHeader();
451
+ if (!builtBlockHeader) {
452
+ logger.debug('Block header not built yet, skipping header check.');
453
+ return;
454
+ }
455
+
456
+ const output = provingState.getBlockRootRollupOutput();
457
+ if (!output) {
458
+ logger.debug('Block root rollup proof not built yet, skipping header check.');
459
+ return;
460
+ }
461
+ const header = await buildHeaderFromCircuitOutputs(output);
462
+
463
+ if (!(await header.hash()).equals(await builtBlockHeader.hash())) {
464
+ logger.error(`Block header mismatch.\nCircuit: ${inspect(header)}\nComputed: ${inspect(builtBlockHeader)}`);
465
+ provingState.reject(`Block header hash mismatch.`);
466
+ return;
467
+ }
468
+
469
+ // Get db for this block
470
+ const blockNumber = provingState.blockNumber;
471
+ const db = this.dbs.get(blockNumber)!;
472
+
473
+ const newArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
474
+ const syncedArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, this.dbProvider.getSnapshot(blockNumber));
328
475
  if (!syncedArchive.equals(newArchive)) {
329
- throw new Error(
330
- `Archive tree mismatch for block ${l2Block.number}: world state synced to ${inspect(
476
+ logger.error(
477
+ `Archive tree mismatch for block ${blockNumber}: world state synced to ${inspect(
331
478
  syncedArchive,
332
479
  )} but built ${inspect(newArchive)}`,
333
480
  );
481
+ provingState.reject(`Archive tree mismatch.`);
482
+ return;
334
483
  }
484
+
485
+ const circuitArchive = output.newArchive;
486
+ if (!newArchive.equals(circuitArchive)) {
487
+ logger.error(`New archive mismatch.\nCircuit: ${output.newArchive}\nComputed: ${newArchive}`);
488
+ provingState.reject(`New archive mismatch.`);
489
+ return;
490
+ }
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));
335
502
  }
336
503
 
337
504
  /**
@@ -348,9 +515,13 @@ export class ProvingOrchestrator implements EpochProver {
348
515
  /**
349
516
  * Returns the proof for the current epoch.
350
517
  */
351
- public async finaliseEpoch() {
518
+ public async finalizeEpoch(): Promise<{
519
+ publicInputs: RootRollupPublicInputs;
520
+ proof: Proof;
521
+ batchedBlobInputs: BatchedBlob;
522
+ }> {
352
523
  if (!this.provingState || !this.provingPromise) {
353
- throw new Error(`Invalid proving state, an epoch must be proven before it can be finalised`);
524
+ throw new Error(`Invalid proving state, an epoch must be proven before it can be finalized`);
354
525
  }
355
526
 
356
527
  const result = await this.provingPromise!;
@@ -358,6 +529,8 @@ export class ProvingOrchestrator implements EpochProver {
358
529
  throw new Error(`Epoch proving failed: ${result.reason}`);
359
530
  }
360
531
 
532
+ await this.provingState.finalizeBatchedBlob();
533
+
361
534
  const epochProofResult = this.provingState.getEpochProofResult();
362
535
 
363
536
  pushTestData('epochProofResult', {
@@ -368,20 +541,6 @@ export class ProvingOrchestrator implements EpochProver {
368
541
  return epochProofResult;
369
542
  }
370
543
 
371
- /**
372
- * Starts the proving process for the given transaction and adds it to our state
373
- * @param tx - The transaction whose proving we wish to commence
374
- * @param provingState - The proving state being worked on
375
- */
376
- private async prepareTransaction(tx: ProcessedTx, provingState: BlockProvingState) {
377
- const txInputs = await this.prepareBaseRollupInputs(provingState, tx);
378
- if (!txInputs) {
379
- // This should not be possible
380
- throw new Error(`Unable to add transaction, preparing base inputs failed`);
381
- }
382
- return txInputs;
383
- }
384
-
385
544
  /**
386
545
  * Enqueue a job to be scheduled
387
546
  * @param provingState - The proving state object being operated on
@@ -389,11 +548,11 @@ export class ProvingOrchestrator implements EpochProver {
389
548
  * @param job - The actual job, returns a promise notifying of the job's completion
390
549
  */
391
550
  private deferredProving<T>(
392
- provingState: EpochProvingState | BlockProvingState | undefined,
551
+ provingState: EpochProvingState | CheckpointProvingState | BlockProvingState,
393
552
  request: (signal: AbortSignal) => Promise<T>,
394
553
  callback: (result: T) => void | Promise<void>,
395
554
  ) {
396
- if (!provingState?.verifyState()) {
555
+ if (!provingState.verifyState()) {
397
556
  logger.debug(`Not enqueuing job, state no longer valid`);
398
557
  return;
399
558
  }
@@ -411,7 +570,7 @@ export class ProvingOrchestrator implements EpochProver {
411
570
  }
412
571
 
413
572
  const result = await request(controller.signal);
414
- if (!provingState?.verifyState()) {
573
+ if (!provingState.verifyState()) {
415
574
  logger.debug(`State no longer valid, discarding result`);
416
575
  return;
417
576
  }
@@ -444,52 +603,59 @@ export class ProvingOrchestrator implements EpochProver {
444
603
  setImmediate(() => void safeJob());
445
604
  }
446
605
 
447
- private async prepareBaseParityInputs(l1ToL2Messages: Fr[], db: MerkleTreeWriteOperations) {
448
- const l1ToL2MessagesPadded = padArrayEnd(
606
+ private async updateL1ToL2MessageTree(l1ToL2Messages: Fr[], db: MerkleTreeWriteOperations) {
607
+ const l1ToL2MessagesPadded = padArrayEnd<Fr, number>(
449
608
  l1ToL2Messages,
450
609
  Fr.ZERO,
451
610
  NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
452
611
  'Too many L1 to L2 messages',
453
612
  );
454
- const baseParityInputs = times(NUM_BASE_PARITY_PER_ROOT_PARITY, i =>
455
- BaseParityInputs.fromSlice(l1ToL2MessagesPadded, i, getVKTreeRoot()),
456
- );
457
613
 
458
- const l1ToL2MessageSubtreeSiblingPath = assertLength(
614
+ const lastL1ToL2MessageTreeSnapshot = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, db);
615
+ const lastL1ToL2MessageSubtreeRootSiblingPath = assertLength(
459
616
  await getSubtreeSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, L1_TO_L2_MSG_SUBTREE_HEIGHT, db),
460
- L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH,
617
+ L1_TO_L2_MSG_SUBTREE_ROOT_SIBLING_PATH_LENGTH,
461
618
  );
462
619
 
463
620
  // Update the local trees to include the new l1 to l2 messages
464
621
  await db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
465
- const l1ToL2MessageTreeSnapshotAfterInsertion = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, db);
622
+
623
+ const newL1ToL2MessageTreeSnapshot = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, db);
624
+ const newL1ToL2MessageSubtreeRootSiblingPath = assertLength(
625
+ await getSubtreeSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, L1_TO_L2_MSG_SUBTREE_HEIGHT, db),
626
+ L1_TO_L2_MSG_SUBTREE_ROOT_SIBLING_PATH_LENGTH,
627
+ );
466
628
 
467
629
  return {
468
- l1ToL2MessageSubtreeSiblingPath,
469
- l1ToL2MessageTreeSnapshotAfterInsertion,
470
- baseParityInputs,
630
+ lastL1ToL2MessageTreeSnapshot,
631
+ lastL1ToL2MessageSubtreeRootSiblingPath,
632
+ newL1ToL2MessageTreeSnapshot,
633
+ newL1ToL2MessageSubtreeRootSiblingPath,
471
634
  };
472
635
  }
473
636
 
474
637
  // Updates the merkle trees for a transaction. The first enqueued job for a transaction
475
- @trackSpan('ProvingOrchestrator.prepareBaseRollupInputs', (_, tx) => ({
638
+ @trackSpan('ProvingOrchestrator.prepareBaseRollupInputs', tx => ({
476
639
  [Attributes.TX_HASH]: tx.hash.toString(),
477
640
  }))
478
641
  private async prepareBaseRollupInputs(
479
- provingState: BlockProvingState,
480
642
  tx: ProcessedTx,
481
- ): Promise<[BaseRollupHints, TreeSnapshots] | undefined> {
482
- if (!provingState.verifyState() || !provingState.spongeBlobState) {
483
- logger.debug('Not preparing base rollup inputs, state invalid');
484
- return;
485
- }
486
-
487
- const db = this.dbs.get(provingState.blockNumber)!;
488
-
643
+ lastArchive: AppendOnlyTreeSnapshot,
644
+ newL1ToL2MessageTreeSnapshot: AppendOnlyTreeSnapshot,
645
+ startSpongeBlob: SpongeBlob,
646
+ db: MerkleTreeWriteOperations,
647
+ ): Promise<[BaseRollupHints, TreeSnapshots]> {
489
648
  // We build the base rollup inputs using a mock proof and verification key.
490
- // These will be overwritten later once we have proven the tube circuit and any public kernels
649
+ // These will be overwritten later once we have proven the chonk verifier circuit and any public kernels
491
650
  const [ms, hints] = await elapsed(
492
- buildBaseRollupHints(tx, provingState.globalVariables, db, provingState.spongeBlobState),
651
+ insertSideEffectsAndBuildBaseRollupHints(
652
+ tx,
653
+ lastArchive,
654
+ newL1ToL2MessageTreeSnapshot,
655
+ startSpongeBlob,
656
+ this.proverId.toField(),
657
+ db,
658
+ ),
493
659
  );
494
660
 
495
661
  this.metrics.recordBaseRollupInputs(ms);
@@ -501,10 +667,6 @@ export class ProvingOrchestrator implements EpochProver {
501
667
  );
502
668
  const treeSnapshots: TreeSnapshots = new Map((await Promise.all(promises)).map(obj => [obj.key, obj.value]));
503
669
 
504
- if (!provingState.verifyState()) {
505
- logger.debug(`Discarding proving job, state no longer valid`);
506
- return;
507
- }
508
670
  return [hints, treeSnapshots];
509
671
  }
510
672
 
@@ -516,6 +678,11 @@ export class ProvingOrchestrator implements EpochProver {
516
678
  return;
517
679
  }
518
680
 
681
+ if (!provingState.tryStartProvingBase(txIndex)) {
682
+ logger.debug(`Base rollup for tx ${txIndex} already started.`);
683
+ return;
684
+ }
685
+
519
686
  const txProvingState = provingState.getTxProvingState(txIndex);
520
687
  const { processedTx } = txProvingState;
521
688
  const { rollupType, inputs } = txProvingState.getBaseRollupTypeAndInputs();
@@ -527,70 +694,81 @@ export class ProvingOrchestrator implements EpochProver {
527
694
  wrapCallbackInSpan(
528
695
  this.tracer,
529
696
  `ProvingOrchestrator.prover.${
530
- inputs instanceof PrivateBaseRollupInputs ? 'getPrivateBaseRollupProof' : 'getPublicBaseRollupProof'
697
+ inputs instanceof PrivateTxBaseRollupPrivateInputs
698
+ ? 'getPrivateTxBaseRollupProof'
699
+ : 'getPublicTxBaseRollupProof'
531
700
  }`,
532
701
  {
533
702
  [Attributes.TX_HASH]: processedTx.hash.toString(),
534
- [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
535
703
  [Attributes.PROTOCOL_CIRCUIT_NAME]: rollupType,
536
704
  },
537
705
  signal => {
538
- if (inputs instanceof PrivateBaseRollupInputs) {
539
- return this.prover.getPrivateBaseRollupProof(inputs, signal, provingState.epochNumber);
706
+ if (inputs instanceof PrivateTxBaseRollupPrivateInputs) {
707
+ return this.prover.getPrivateTxBaseRollupProof(inputs, signal, provingState.epochNumber);
540
708
  } else {
541
- return this.prover.getPublicBaseRollupProof(inputs, signal, provingState.epochNumber);
709
+ return this.prover.getPublicTxBaseRollupProof(inputs, signal, provingState.epochNumber);
542
710
  }
543
711
  },
544
712
  ),
545
- async result => {
713
+ result => {
546
714
  logger.debug(`Completed proof for ${rollupType} for tx ${processedTx.hash.toString()}`);
547
- validatePartialState(result.inputs.end, txProvingState.treeSnapshots);
715
+ validatePartialState(result.inputs.endTreeSnapshots, txProvingState.treeSnapshots);
548
716
  const leafLocation = provingState.setBaseRollupProof(txIndex, result);
549
717
  if (provingState.totalNumTxs === 1) {
550
- await this.checkAndEnqueueBlockRootRollup(provingState);
718
+ this.checkAndEnqueueBlockRootRollup(provingState);
551
719
  } else {
552
- await this.checkAndEnqueueNextMergeRollup(provingState, leafLocation);
720
+ this.checkAndEnqueueNextMergeRollup(provingState, leafLocation);
553
721
  }
554
722
  },
555
723
  );
556
724
  }
557
725
 
558
- // Enqueues the tube circuit for a given transaction index, or reuses the one already enqueued
559
- // Once completed, will enqueue the next circuit, either a public kernel or the base rollup
560
- private getOrEnqueueTube(provingState: BlockProvingState, txIndex: number) {
726
+ // Enqueues the public chonk verifier circuit for a given transaction index, or reuses the one already enqueued.
727
+ // Once completed, will enqueue the the public tx base rollup.
728
+ private getOrEnqueueChonkVerifier(provingState: BlockProvingState, txIndex: number) {
561
729
  if (!provingState.verifyState()) {
562
- logger.debug('Not running tube circuit, state invalid');
730
+ logger.debug('Not running chonk verifier circuit, state invalid');
563
731
  return;
564
732
  }
565
733
 
566
734
  const txProvingState = provingState.getTxProvingState(txIndex);
567
735
  const txHash = txProvingState.processedTx.hash.toString();
568
-
569
- const handleResult = (result: ProofAndVerificationKey<typeof TUBE_PROOF_LENGTH>) => {
570
- logger.debug(`Got tube proof for tx index: ${txIndex}`, { txHash });
571
- txProvingState.setTubeProof(result);
572
- this.provingState?.cachedTubeProofs.delete(txHash);
573
- this.checkAndEnqueueNextTxCircuit(provingState, txIndex);
736
+ NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH;
737
+ const handleResult = (
738
+ result: PublicInputsAndRecursiveProof<
739
+ PublicChonkVerifierPublicInputs,
740
+ typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH
741
+ >,
742
+ ) => {
743
+ logger.debug(`Got chonk verifier proof for tx index: ${txIndex}`, { txHash });
744
+ txProvingState.setPublicChonkVerifierProof(result);
745
+ this.provingState?.cachedChonkVerifierProofs.delete(txHash);
746
+ this.checkAndEnqueueBaseRollup(provingState, txIndex);
574
747
  };
575
748
 
576
- if (this.provingState?.cachedTubeProofs.has(txHash)) {
577
- logger.debug(`Tube proof already enqueued for tx index: ${txIndex}`, { txHash });
578
- void this.provingState!.cachedTubeProofs.get(txHash)!.then(handleResult);
749
+ if (this.provingState?.cachedChonkVerifierProofs.has(txHash)) {
750
+ logger.debug(`Chonk verifier proof already enqueued for tx index: ${txIndex}`, { txHash });
751
+ void this.provingState!.cachedChonkVerifierProofs.get(txHash)!.then(handleResult);
579
752
  return;
580
753
  }
581
754
 
582
- logger.debug(`Enqueuing tube circuit for tx index: ${txIndex}`);
583
- this.doEnqueueTube(txHash, txProvingState.getTubeInputs(), handleResult);
755
+ logger.debug(`Enqueuing chonk verifier circuit for tx index: ${txIndex}`);
756
+ this.doEnqueueChonkVerifier(txHash, txProvingState.getPublicChonkVerifierPrivateInputs(), handleResult);
584
757
  }
585
758
 
586
- private doEnqueueTube(
759
+ private doEnqueueChonkVerifier(
587
760
  txHash: string,
588
- inputs: TubeInputs,
589
- handler: (result: ProofAndVerificationKey<typeof TUBE_PROOF_LENGTH>) => void,
761
+ inputs: PublicChonkVerifierPrivateInputs,
762
+ handler: (
763
+ result: PublicInputsAndRecursiveProof<
764
+ PublicChonkVerifierPublicInputs,
765
+ typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH
766
+ >,
767
+ ) => void,
590
768
  provingState: EpochProvingState | BlockProvingState = this.provingState!,
591
769
  ) {
592
- if (!provingState?.verifyState()) {
593
- logger.debug('Not running tube circuit, state invalid');
770
+ if (!provingState.verifyState()) {
771
+ logger.debug('Not running chonk verifier circuit, state invalid');
594
772
  return;
595
773
  }
596
774
 
@@ -598,13 +776,12 @@ export class ProvingOrchestrator implements EpochProver {
598
776
  provingState,
599
777
  wrapCallbackInSpan(
600
778
  this.tracer,
601
- 'ProvingOrchestrator.prover.getTubeProof',
779
+ 'ProvingOrchestrator.prover.getPublicChonkVerifierProof',
602
780
  {
603
781
  [Attributes.TX_HASH]: txHash,
604
- [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
605
- [Attributes.PROTOCOL_CIRCUIT_NAME]: 'tube-circuit' satisfies CircuitName,
782
+ [Attributes.PROTOCOL_CIRCUIT_NAME]: 'chonk-verifier-public' satisfies CircuitName,
606
783
  },
607
- signal => this.prover.getTubeProof(inputs, signal, this.provingState!.epochNumber),
784
+ signal => this.prover.getPublicChonkVerifierProof(inputs, signal, provingState.epochNumber),
608
785
  ),
609
786
  handler,
610
787
  );
@@ -618,40 +795,45 @@ export class ProvingOrchestrator implements EpochProver {
618
795
  return;
619
796
  }
620
797
 
798
+ if (!provingState.tryStartProvingMerge(location)) {
799
+ logger.debug('Merge rollup already started.');
800
+ return;
801
+ }
802
+
621
803
  const inputs = provingState.getMergeRollupInputs(location);
622
804
 
623
805
  this.deferredProving(
624
806
  provingState,
625
807
  wrapCallbackInSpan(
626
808
  this.tracer,
627
- 'ProvingOrchestrator.prover.getMergeRollupProof',
809
+ 'ProvingOrchestrator.prover.getTxMergeRollupProof',
628
810
  {
629
- [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
630
- [Attributes.PROTOCOL_CIRCUIT_NAME]: 'merge-rollup' satisfies CircuitName,
811
+ [Attributes.PROTOCOL_CIRCUIT_NAME]: 'rollup-tx-merge' satisfies CircuitName,
631
812
  },
632
- signal => this.prover.getMergeRollupProof(inputs, signal, provingState.epochNumber),
813
+ signal => this.prover.getTxMergeRollupProof(inputs, signal, provingState.epochNumber),
633
814
  ),
634
- async result => {
815
+ result => {
635
816
  provingState.setMergeRollupProof(location, result);
636
- await this.checkAndEnqueueNextMergeRollup(provingState, location);
817
+ this.checkAndEnqueueNextMergeRollup(provingState, location);
637
818
  },
638
819
  );
639
820
  }
640
821
 
641
822
  // Executes the block root rollup circuit
642
- private async enqueueBlockRootRollup(provingState: BlockProvingState) {
823
+ private enqueueBlockRootRollup(provingState: BlockProvingState) {
643
824
  if (!provingState.verifyState()) {
644
825
  logger.debug('Not running block root rollup, state no longer valid');
645
826
  return;
646
827
  }
647
828
 
648
- provingState.blockRootRollupStarted = true;
829
+ if (!provingState.tryStartProvingBlockRoot()) {
830
+ logger.debug('Block root rollup already started.');
831
+ return;
832
+ }
649
833
 
650
- const { rollupType, inputs } = await provingState.getBlockRootRollupTypeAndInputs(this.proverId);
834
+ const { rollupType, inputs } = provingState.getBlockRootRollupTypeAndInputs();
651
835
 
652
- logger.debug(
653
- `Enqueuing ${rollupType} for block ${provingState.blockNumber} with ${provingState.newL1ToL2Messages.length} l1 to l2 msgs.`,
654
- );
836
+ logger.debug(`Enqueuing ${rollupType} for block ${provingState.blockNumber}.`);
655
837
 
656
838
  this.deferredProving(
657
839
  provingState,
@@ -659,38 +841,35 @@ export class ProvingOrchestrator implements EpochProver {
659
841
  this.tracer,
660
842
  'ProvingOrchestrator.prover.getBlockRootRollupProof',
661
843
  {
662
- [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
663
844
  [Attributes.PROTOCOL_CIRCUIT_NAME]: rollupType,
664
845
  },
665
846
  signal => {
666
- if (inputs instanceof EmptyBlockRootRollupInputs) {
667
- return this.prover.getEmptyBlockRootRollupProof(inputs, signal, provingState.epochNumber);
668
- } else if (inputs instanceof SingleTxBlockRootRollupInputs) {
669
- return this.prover.getSingleTxBlockRootRollupProof(inputs, signal, provingState.epochNumber);
847
+ if (inputs instanceof BlockRootFirstRollupPrivateInputs) {
848
+ return this.prover.getBlockRootFirstRollupProof(inputs, signal, provingState.epochNumber);
849
+ } else if (inputs instanceof BlockRootSingleTxFirstRollupPrivateInputs) {
850
+ return this.prover.getBlockRootSingleTxFirstRollupProof(inputs, signal, provingState.epochNumber);
851
+ } else if (inputs instanceof BlockRootEmptyTxFirstRollupPrivateInputs) {
852
+ return this.prover.getBlockRootEmptyTxFirstRollupProof(inputs, signal, provingState.epochNumber);
853
+ } else if (inputs instanceof BlockRootSingleTxRollupPrivateInputs) {
854
+ return this.prover.getBlockRootSingleTxRollupProof(inputs, signal, provingState.epochNumber);
670
855
  } else {
671
856
  return this.prover.getBlockRootRollupProof(inputs, signal, provingState.epochNumber);
672
857
  }
673
858
  },
674
859
  ),
675
860
  async result => {
676
- provingState.setBlockRootRollupProof(result);
677
- const header = await provingState.buildHeaderFromProvingOutputs(logger);
678
- if (!(await header.hash()).equals(await provingState.block!.header.hash())) {
679
- logger.error(
680
- `Block header mismatch\nCircuit:${inspect(header)}\nComputed:${inspect(provingState.block!.header)}`,
681
- );
682
- provingState.reject(`Block header hash mismatch`);
683
- }
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);
684
863
 
685
- logger.debug(`Completed ${rollupType} proof for block ${provingState.block!.number}`);
686
- // validatePartialState(result.inputs.end, tx.treeSnapshots); // TODO(palla/prover)
864
+ logger.debug(`Completed ${rollupType} proof for block ${provingState.blockNumber}`);
687
865
 
688
- const epochProvingState = this.provingState!;
689
- const leafLocation = epochProvingState.setBlockRootRollupProof(provingState.index, result);
690
- if (epochProvingState.totalNumBlocks === 1) {
691
- await this.enqueueEpochPadding(epochProvingState);
866
+ const leafLocation = provingState.setBlockRootRollupProof(result);
867
+ const checkpointProvingState = provingState.parentCheckpoint;
868
+
869
+ if (checkpointProvingState.totalNumBlocks === 1) {
870
+ this.checkAndEnqueueCheckpointRootRollup(checkpointProvingState);
692
871
  } else {
693
- this.checkAndEnqueueNextBlockMergeRollup(epochProvingState, leafLocation);
872
+ this.checkAndEnqueueNextBlockMergeRollup(checkpointProvingState, leafLocation);
694
873
  }
695
874
  },
696
875
  );
@@ -698,25 +877,35 @@ export class ProvingOrchestrator implements EpochProver {
698
877
 
699
878
  // Executes the base parity circuit and stores the intermediate state for the root parity circuit
700
879
  // Enqueues the root parity circuit if all inputs are available
701
- private enqueueBaseParityCircuit(provingState: BlockProvingState, inputs: BaseParityInputs, index: number) {
880
+ private enqueueBaseParityCircuit(
881
+ checkpointProvingState: CheckpointProvingState,
882
+ provingState: BlockProvingState,
883
+ baseParityIndex: number,
884
+ ) {
702
885
  if (!provingState.verifyState()) {
703
886
  logger.debug('Not running base parity. State no longer valid.');
704
887
  return;
705
888
  }
706
889
 
890
+ if (!provingState.tryStartProvingBaseParity(baseParityIndex)) {
891
+ logger.warn(`Base parity ${baseParityIndex} already started.`);
892
+ return;
893
+ }
894
+
895
+ const inputs = checkpointProvingState.getBaseParityInputs(baseParityIndex);
896
+
707
897
  this.deferredProving(
708
898
  provingState,
709
899
  wrapCallbackInSpan(
710
900
  this.tracer,
711
901
  'ProvingOrchestrator.prover.getBaseParityProof',
712
902
  {
713
- [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
714
- [Attributes.PROTOCOL_CIRCUIT_NAME]: 'base-parity' satisfies CircuitName,
903
+ [Attributes.PROTOCOL_CIRCUIT_NAME]: 'parity-base' satisfies CircuitName,
715
904
  },
716
905
  signal => this.prover.getBaseParityProof(inputs, signal, provingState.epochNumber),
717
906
  ),
718
907
  provingOutput => {
719
- provingState.setBaseParityProof(index, provingOutput);
908
+ provingState.setBaseParityProof(baseParityIndex, provingOutput);
720
909
  this.checkAndEnqueueRootParityCircuit(provingState);
721
910
  },
722
911
  );
@@ -738,7 +927,12 @@ export class ProvingOrchestrator implements EpochProver {
738
927
  return;
739
928
  }
740
929
 
741
- const inputs = provingState.getRootParityInputs();
930
+ if (!provingState.tryStartProvingRootParity()) {
931
+ logger.debug('Root parity already started.');
932
+ return;
933
+ }
934
+
935
+ const inputs = provingState.getParityRootInputs();
742
936
 
743
937
  this.deferredProving(
744
938
  provingState,
@@ -746,36 +940,38 @@ export class ProvingOrchestrator implements EpochProver {
746
940
  this.tracer,
747
941
  'ProvingOrchestrator.prover.getRootParityProof',
748
942
  {
749
- [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
750
- [Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-parity' satisfies CircuitName,
943
+ [Attributes.PROTOCOL_CIRCUIT_NAME]: 'parity-root' satisfies CircuitName,
751
944
  },
752
945
  signal => this.prover.getRootParityProof(inputs, signal, provingState.epochNumber),
753
946
  ),
754
- async result => {
947
+ result => {
755
948
  provingState.setRootParityProof(result);
756
- await this.checkAndEnqueueBlockRootRollup(provingState);
949
+ this.checkAndEnqueueBlockRootRollup(provingState);
757
950
  },
758
951
  );
759
952
  }
760
953
 
761
954
  // Executes the block merge rollup circuit and stored the output as intermediate state for the parent merge/block root circuit
762
955
  // Enqueues the next level of merge if all inputs are available
763
- private enqueueBlockMergeRollup(provingState: EpochProvingState, location: TreeNodeLocation) {
956
+ private enqueueBlockMergeRollup(provingState: CheckpointProvingState, location: TreeNodeLocation) {
764
957
  if (!provingState.verifyState()) {
765
958
  logger.debug('Not running block merge rollup. State no longer valid.');
766
959
  return;
767
960
  }
768
961
 
769
- const inputs = provingState.getBlockMergeRollupInputs(location);
962
+ if (!provingState.tryStartProvingBlockMerge(location)) {
963
+ logger.debug('Block merge rollup already started.');
964
+ return;
965
+ }
770
966
 
967
+ const inputs = provingState.getBlockMergeRollupInputs(location);
771
968
  this.deferredProving(
772
969
  provingState,
773
970
  wrapCallbackInSpan(
774
971
  this.tracer,
775
972
  'ProvingOrchestrator.prover.getBlockMergeRollupProof',
776
973
  {
777
- [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
778
- [Attributes.PROTOCOL_CIRCUIT_NAME]: 'block-merge-rollup' satisfies CircuitName,
974
+ [Attributes.PROTOCOL_CIRCUIT_NAME]: 'rollup-block-merge' satisfies CircuitName,
779
975
  },
780
976
  signal => this.prover.getBlockMergeRollupProof(inputs, signal, provingState.epochNumber),
781
977
  ),
@@ -786,30 +982,125 @@ export class ProvingOrchestrator implements EpochProver {
786
982
  );
787
983
  }
788
984
 
789
- private async enqueueEpochPadding(provingState: EpochProvingState) {
985
+ private enqueueCheckpointRootRollup(provingState: CheckpointProvingState) {
986
+ if (!provingState.verifyState()) {
987
+ logger.debug('Not running checkpoint root rollup. State no longer valid.');
988
+ return;
989
+ }
990
+
991
+ if (!provingState.tryStartProvingCheckpointRoot()) {
992
+ logger.debug('Checkpoint root rollup already started.');
993
+ return;
994
+ }
995
+
996
+ const rollupType = provingState.getCheckpointRootRollupType();
997
+
998
+ logger.debug(`Enqueuing ${rollupType} for checkpoint ${provingState.index}.`);
999
+
1000
+ const inputs = provingState.getCheckpointRootRollupInputs();
1001
+
1002
+ this.deferredProving(
1003
+ provingState,
1004
+ wrapCallbackInSpan(
1005
+ this.tracer,
1006
+ 'ProvingOrchestrator.prover.getCheckpointRootRollupProof',
1007
+ {
1008
+ [Attributes.PROTOCOL_CIRCUIT_NAME]: rollupType,
1009
+ },
1010
+ signal => {
1011
+ if (inputs instanceof CheckpointRootSingleBlockRollupPrivateInputs) {
1012
+ return this.prover.getCheckpointRootSingleBlockRollupProof(inputs, signal, provingState.epochNumber);
1013
+ } else {
1014
+ return this.prover.getCheckpointRootRollupProof(inputs, signal, provingState.epochNumber);
1015
+ }
1016
+ },
1017
+ ),
1018
+ result => {
1019
+ const computedEndBlobAccumulatorState = provingState.getEndBlobAccumulator()!.toBlobAccumulator();
1020
+ const circuitEndBlobAccumulatorState = result.inputs.endBlobAccumulator;
1021
+ if (!circuitEndBlobAccumulatorState.equals(computedEndBlobAccumulatorState)) {
1022
+ logger.error(
1023
+ `Blob accumulator state mismatch.\nCircuit: ${inspect(circuitEndBlobAccumulatorState)}\nComputed: ${inspect(
1024
+ computedEndBlobAccumulatorState,
1025
+ )}`,
1026
+ );
1027
+ provingState.reject(`Blob accumulator state mismatch.`);
1028
+ return;
1029
+ }
1030
+
1031
+ logger.debug(`Completed ${rollupType} proof for checkpoint ${provingState.index}.`);
1032
+
1033
+ const leafLocation = provingState.setCheckpointRootRollupProof(result);
1034
+ const epochProvingState = provingState.parentEpoch;
1035
+
1036
+ if (epochProvingState.totalNumCheckpoints === 1) {
1037
+ this.enqueueEpochPadding(epochProvingState);
1038
+ } else {
1039
+ this.checkAndEnqueueNextCheckpointMergeRollup(epochProvingState, leafLocation);
1040
+ }
1041
+ },
1042
+ );
1043
+ }
1044
+
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) {
790
1077
  if (!provingState.verifyState()) {
791
1078
  logger.debug('Not running epoch padding. State no longer valid.');
792
1079
  return;
793
1080
  }
794
1081
 
795
- logger.debug('Padding epoch proof with an empty block root proof.');
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.');
796
1088
 
797
- const inputs = await provingState.getPaddingBlockRootInputs(this.proverId);
1089
+ const inputs = provingState.getPaddingCheckpointInputs();
798
1090
 
799
1091
  this.deferredProving(
800
1092
  provingState,
801
1093
  wrapCallbackInSpan(
802
1094
  this.tracer,
803
- 'ProvingOrchestrator.prover.getEmptyBlockRootRollupProof',
1095
+ 'ProvingOrchestrator.prover.getCheckpointPaddingRollupProof',
804
1096
  {
805
- [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
806
- [Attributes.PROTOCOL_CIRCUIT_NAME]: 'empty-block-root-rollup' satisfies CircuitName,
1097
+ [Attributes.PROTOCOL_CIRCUIT_NAME]: 'rollup-checkpoint-padding' satisfies CircuitName,
807
1098
  },
808
- signal => this.prover.getEmptyBlockRootRollupProof(inputs, signal, provingState.epochNumber),
1099
+ signal => this.prover.getCheckpointPaddingRollupProof(inputs, signal, provingState.epochNumber),
809
1100
  ),
810
1101
  result => {
811
- logger.debug('Completed proof for padding block root.');
812
- provingState.setPaddingBlockRootProof(result);
1102
+ logger.debug('Completed proof for padding checkpoint.');
1103
+ provingState.setCheckpointPaddingProof(result);
813
1104
  this.checkAndEnqueueRootRollup(provingState);
814
1105
  },
815
1106
  );
@@ -824,7 +1115,7 @@ export class ProvingOrchestrator implements EpochProver {
824
1115
 
825
1116
  logger.debug(`Preparing root rollup`);
826
1117
 
827
- const inputs = provingState.getRootRollupInputs(this.proverId);
1118
+ const inputs = provingState.getRootRollupInputs();
828
1119
 
829
1120
  this.deferredProving(
830
1121
  provingState,
@@ -832,8 +1123,7 @@ export class ProvingOrchestrator implements EpochProver {
832
1123
  this.tracer,
833
1124
  'ProvingOrchestrator.prover.getRootRollupProof',
834
1125
  {
835
- [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
836
- [Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-rollup' satisfies CircuitName,
1126
+ [Attributes.PROTOCOL_CIRCUIT_NAME]: 'rollup-root' satisfies CircuitName,
837
1127
  },
838
1128
  signal => this.prover.getRootRollupProof(inputs, signal, provingState.epochNumber),
839
1129
  ),
@@ -845,46 +1135,51 @@ export class ProvingOrchestrator implements EpochProver {
845
1135
  );
846
1136
  }
847
1137
 
848
- private async checkAndEnqueueNextMergeRollup(provingState: BlockProvingState, currentLocation: TreeNodeLocation) {
1138
+ private checkAndEnqueueNextMergeRollup(provingState: BlockProvingState, currentLocation: TreeNodeLocation) {
849
1139
  if (!provingState.isReadyForMergeRollup(currentLocation)) {
850
1140
  return;
851
1141
  }
852
1142
 
853
1143
  const parentLocation = provingState.getParentLocation(currentLocation);
854
1144
  if (parentLocation.level === 0) {
855
- await this.checkAndEnqueueBlockRootRollup(provingState);
1145
+ this.checkAndEnqueueBlockRootRollup(provingState);
856
1146
  } else {
857
1147
  this.enqueueMergeRollup(provingState, parentLocation);
858
1148
  }
859
1149
  }
860
1150
 
861
- private async checkAndEnqueueBlockRootRollup(provingState: BlockProvingState) {
1151
+ private checkAndEnqueueBlockRootRollup(provingState: BlockProvingState) {
862
1152
  if (!provingState.isReadyForBlockRootRollup()) {
863
- logger.debug('Not ready for root rollup');
1153
+ logger.debug('Not ready for block root rollup');
864
1154
  return;
865
1155
  }
866
- if (provingState.blockRootRollupStarted) {
867
- logger.debug('Block root rollup already started');
1156
+
1157
+ this.enqueueBlockRootRollup(provingState);
1158
+ }
1159
+
1160
+ private checkAndEnqueueNextBlockMergeRollup(provingState: CheckpointProvingState, currentLocation: TreeNodeLocation) {
1161
+ if (!provingState.isReadyForBlockMerge(currentLocation)) {
868
1162
  return;
869
1163
  }
870
- const blockNumber = provingState.blockNumber;
871
1164
 
872
- // TODO(palla/prover): This closes the fork only on the happy path. If this epoch orchestrator
873
- // is aborted and never reaches this point, it will leak the fork. We need to add a global cleanup,
874
- // but have to make sure it only runs once all operations are completed, otherwise some function here
875
- // will attempt to access the fork after it was closed.
876
- logger.debug(`Cleaning up world state fork for ${blockNumber}`);
877
- void this.dbs
878
- .get(blockNumber)
879
- ?.close()
880
- .then(() => this.dbs.delete(blockNumber))
881
- .catch(err => logger.error(`Error closing db for block ${blockNumber}`, err));
1165
+ const parentLocation = provingState.getParentLocation(currentLocation);
1166
+ if (parentLocation.level === 0) {
1167
+ this.checkAndEnqueueCheckpointRootRollup(provingState);
1168
+ } else {
1169
+ this.enqueueBlockMergeRollup(provingState, parentLocation);
1170
+ }
1171
+ }
1172
+
1173
+ private checkAndEnqueueCheckpointRootRollup(provingState: CheckpointProvingState) {
1174
+ if (!provingState.isReadyForCheckpointRoot()) {
1175
+ return;
1176
+ }
882
1177
 
883
- await this.enqueueBlockRootRollup(provingState);
1178
+ this.enqueueCheckpointRootRollup(provingState);
884
1179
  }
885
1180
 
886
- private checkAndEnqueueNextBlockMergeRollup(provingState: EpochProvingState, currentLocation: TreeNodeLocation) {
887
- if (!provingState.isReadyForBlockMerge(currentLocation)) {
1181
+ private checkAndEnqueueNextCheckpointMergeRollup(provingState: EpochProvingState, currentLocation: TreeNodeLocation) {
1182
+ if (!provingState.isReadyForCheckpointMerge(currentLocation)) {
888
1183
  return;
889
1184
  }
890
1185
 
@@ -892,7 +1187,7 @@ export class ProvingOrchestrator implements EpochProver {
892
1187
  if (parentLocation.level === 0) {
893
1188
  this.checkAndEnqueueRootRollup(provingState);
894
1189
  } else {
895
- this.enqueueBlockMergeRollup(provingState, parentLocation);
1190
+ this.enqueueCheckpointMergeRollup(provingState, parentLocation);
896
1191
  }
897
1192
  }
898
1193
 
@@ -930,21 +1225,27 @@ export class ProvingOrchestrator implements EpochProver {
930
1225
  async (signal: AbortSignal) => {
931
1226
  const inputs = txProvingState.getAvmInputs();
932
1227
  try {
933
- return await this.prover.getAvmProof(inputs, signal, provingState.epochNumber);
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);
934
1231
  } catch (err) {
935
1232
  if (process.env.AVM_PROVING_STRICT) {
936
1233
  logger.error(`Error thrown when proving AVM circuit with AVM_PROVING_STRICT on`, err);
937
1234
  throw err;
938
1235
  } else {
939
1236
  logger.warn(
940
- `Error thrown when proving AVM circuit but AVM_PROVING_STRICT is off. Faking AVM proof and carrying on. ${inspect(
941
- err,
942
- )}.`,
1237
+ `Error thrown when proving AVM circuit but AVM_PROVING_STRICT is off. Use snapshotted
1238
+ AVM inputs and carrying on. ${inspect(err)}.`,
943
1239
  );
944
- return {
945
- proof: makeEmptyRecursiveProof(AVM_PROOF_LENGTH_IN_FIELDS),
946
- verificationKey: VerificationKeyData.makeFake(AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS),
947
- };
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
+ }
948
1249
  }
949
1250
  }
950
1251
  },
@@ -953,17 +1254,17 @@ export class ProvingOrchestrator implements EpochProver {
953
1254
  this.deferredProving(provingState, doAvmProving, proofAndVk => {
954
1255
  logger.debug(`Proven VM for tx index: ${txIndex}`);
955
1256
  txProvingState.setAvmProof(proofAndVk);
956
- this.checkAndEnqueueNextTxCircuit(provingState, txIndex);
1257
+ this.checkAndEnqueueBaseRollup(provingState, txIndex);
957
1258
  });
958
1259
  }
959
1260
 
960
- private checkAndEnqueueNextTxCircuit(provingState: BlockProvingState, txIndex: number) {
1261
+ private checkAndEnqueueBaseRollup(provingState: BlockProvingState, txIndex: number) {
961
1262
  const txProvingState = provingState.getTxProvingState(txIndex);
962
1263
  if (!txProvingState.ready()) {
963
1264
  return;
964
1265
  }
965
1266
 
966
- // We must have completed all proving (tube proof and (if required) vm proof are generated), we now move to the base rollup.
1267
+ // We must have completed all proving (chonk verifier proof and (if required) vm proof are generated), we now move to the base rollup.
967
1268
  logger.debug(`Public functions completed for tx ${txIndex} enqueueing base rollup`);
968
1269
 
969
1270
  this.enqueueBaseRollup(provingState, txIndex);