@aztec/prover-client 0.0.0-test.0 → 0.0.1-commit.21caa21

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