@aztec/prover-client 3.0.0-nightly.20250917 → 3.0.0-nightly.20250919

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 (65) hide show
  1. package/dest/block-factory/light.d.ts +5 -3
  2. package/dest/block-factory/light.d.ts.map +1 -1
  3. package/dest/block-factory/light.js +16 -9
  4. package/dest/mocks/fixtures.d.ts +3 -1
  5. package/dest/mocks/fixtures.d.ts.map +1 -1
  6. package/dest/mocks/fixtures.js +19 -2
  7. package/dest/mocks/test_context.d.ts +30 -9
  8. package/dest/mocks/test_context.d.ts.map +1 -1
  9. package/dest/mocks/test_context.js +68 -15
  10. package/dest/orchestrator/block-building-helpers.d.ts +16 -14
  11. package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
  12. package/dest/orchestrator/block-building-helpers.js +69 -66
  13. package/dest/orchestrator/block-proving-state.d.ts +59 -52
  14. package/dest/orchestrator/block-proving-state.d.ts.map +1 -1
  15. package/dest/orchestrator/block-proving-state.js +215 -187
  16. package/dest/orchestrator/checkpoint-proving-state.d.ts +62 -0
  17. package/dest/orchestrator/checkpoint-proving-state.d.ts.map +1 -0
  18. package/dest/orchestrator/checkpoint-proving-state.js +208 -0
  19. package/dest/orchestrator/epoch-proving-state.d.ts +32 -25
  20. package/dest/orchestrator/epoch-proving-state.d.ts.map +1 -1
  21. package/dest/orchestrator/epoch-proving-state.js +132 -81
  22. package/dest/orchestrator/orchestrator.d.ts +25 -24
  23. package/dest/orchestrator/orchestrator.d.ts.map +1 -1
  24. package/dest/orchestrator/orchestrator.js +331 -203
  25. package/dest/orchestrator/tx-proving-state.d.ts +3 -3
  26. package/dest/orchestrator/tx-proving-state.d.ts.map +1 -1
  27. package/dest/orchestrator/tx-proving-state.js +5 -5
  28. package/dest/prover-client/server-epoch-prover.d.ts +8 -7
  29. package/dest/prover-client/server-epoch-prover.d.ts.map +1 -1
  30. package/dest/prover-client/server-epoch-prover.js +7 -7
  31. package/dest/proving_broker/broker_prover_facade.d.ts +18 -13
  32. package/dest/proving_broker/broker_prover_facade.d.ts.map +1 -1
  33. package/dest/proving_broker/broker_prover_facade.js +36 -21
  34. package/dest/proving_broker/fixtures.js +1 -1
  35. package/dest/proving_broker/proof_store/index.d.ts +1 -0
  36. package/dest/proving_broker/proof_store/index.d.ts.map +1 -1
  37. package/dest/proving_broker/proof_store/index.js +1 -0
  38. package/dest/proving_broker/proving_broker.d.ts.map +1 -1
  39. package/dest/proving_broker/proving_broker.js +27 -16
  40. package/dest/proving_broker/proving_job_controller.d.ts.map +1 -1
  41. package/dest/proving_broker/proving_job_controller.js +34 -14
  42. package/dest/test/mock_prover.d.ts +18 -13
  43. package/dest/test/mock_prover.d.ts.map +1 -1
  44. package/dest/test/mock_prover.js +31 -16
  45. package/package.json +16 -17
  46. package/src/block-factory/light.ts +33 -9
  47. package/src/mocks/fixtures.ts +25 -7
  48. package/src/mocks/test_context.ts +113 -21
  49. package/src/orchestrator/block-building-helpers.ts +107 -93
  50. package/src/orchestrator/block-proving-state.ts +232 -244
  51. package/src/orchestrator/checkpoint-proving-state.ts +294 -0
  52. package/src/orchestrator/epoch-proving-state.ts +169 -121
  53. package/src/orchestrator/orchestrator.ts +483 -262
  54. package/src/orchestrator/tx-proving-state.ts +6 -6
  55. package/src/prover-client/server-epoch-prover.ts +30 -16
  56. package/src/proving_broker/broker_prover_facade.ts +151 -83
  57. package/src/proving_broker/fixtures.ts +1 -1
  58. package/src/proving_broker/proof_store/index.ts +1 -0
  59. package/src/proving_broker/proving_broker.ts +34 -16
  60. package/src/proving_broker/proving_job_controller.ts +34 -14
  61. package/src/test/mock_prover.ts +125 -54
  62. package/dest/bin/get-proof-inputs.d.ts +0 -2
  63. package/dest/bin/get-proof-inputs.d.ts.map +0 -1
  64. package/dest/bin/get-proof-inputs.js +0 -51
  65. package/src/bin/get-proof-inputs.ts +0 -59
@@ -1,140 +1,155 @@
1
- import { BatchedBlobAccumulator, BlobAccumulatorPublicInputs, SpongeBlob } from '@aztec/blob-lib';
1
+ import type { SpongeBlob } from '@aztec/blob-lib';
2
2
  import {
3
3
  type ARCHIVE_HEIGHT,
4
- BLOBS_PER_BLOCK,
5
- FIELDS_PER_BLOB,
6
4
  type L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH,
5
+ NESTED_RECURSIVE_PROOF_LENGTH,
7
6
  type NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
8
7
  NUM_BASE_PARITY_PER_ROOT_PARITY,
9
- type RECURSIVE_PROOF_LENGTH,
10
8
  } from '@aztec/constants';
11
- import { padArrayEnd } from '@aztec/foundation/collection';
12
- import { BLS12Point, Fr } from '@aztec/foundation/fields';
13
- import type { Tuple } from '@aztec/foundation/serialize';
9
+ import { Fr } from '@aztec/foundation/fields';
10
+ import { type Tuple, assertLength } from '@aztec/foundation/serialize';
14
11
  import { type TreeNodeLocation, UnbalancedTreeStore } from '@aztec/foundation/trees';
15
- import { getVKIndex, getVKSiblingPath, getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
16
- import { protocolContractTreeRoot } from '@aztec/protocol-contracts';
17
- import type { EthAddress, L2Block } from '@aztec/stdlib/block';
12
+ import { getBlockBlobFields } from '@aztec/stdlib/block';
18
13
  import type { PublicInputsAndRecursiveProof } from '@aztec/stdlib/interfaces/server';
19
- import { type ParityPublicInputs, RootParityInput, RootParityInputs } from '@aztec/stdlib/parity';
14
+ import { type ParityPublicInputs, ParityRootPrivateInputs } from '@aztec/stdlib/parity';
15
+ import type { RollupHonkProofData } from '@aztec/stdlib/proofs';
20
16
  import {
21
- type BaseOrMergeRollupPublicInputs,
22
- BlockConstantData,
23
- type BlockRootOrBlockMergePublicInputs,
24
- BlockRootRollupBlobData,
25
- BlockRootRollupData,
26
- BlockRootRollupInputs,
27
- EmptyBlockRootRollupInputs,
28
- EpochConstantData,
29
- MergeRollupInputs,
30
- PaddingBlockRootRollupInputs,
31
- PreviousRollupData,
32
- SingleTxBlockRootRollupInputs,
17
+ BlockRollupPublicInputs,
18
+ BlockRootEmptyTxFirstRollupPrivateInputs,
19
+ BlockRootFirstRollupPrivateInputs,
20
+ BlockRootRollupPrivateInputs,
21
+ BlockRootSingleTxFirstRollupPrivateInputs,
22
+ BlockRootSingleTxRollupPrivateInputs,
23
+ CheckpointConstantData,
24
+ TxMergeRollupPrivateInputs,
25
+ type TxRollupPublicInputs,
33
26
  } from '@aztec/stdlib/rollup';
34
27
  import type { CircuitName } from '@aztec/stdlib/stats';
35
- import { AppendOnlyTreeSnapshot, type MerkleTreeId } from '@aztec/stdlib/trees';
36
- import { type BlockHeader, type GlobalVariables, StateReference } from '@aztec/stdlib/tx';
37
- import { VkData } from '@aztec/stdlib/vks';
28
+ import { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
29
+ import { type BlockHeader, GlobalVariables } from '@aztec/stdlib/tx';
30
+ import type { UInt64 } from '@aztec/stdlib/types';
38
31
 
39
- import {
40
- accumulateBlobs,
41
- buildBlobHints,
42
- buildHeaderFromCircuitOutputs,
43
- getEmptyBlockBlobsHash,
44
- } from './block-building-helpers.js';
45
- import type { EpochProvingState } from './epoch-proving-state.js';
32
+ import { buildHeaderFromCircuitOutputs, toProofData } from './block-building-helpers.js';
33
+ import type { CheckpointProvingState } from './checkpoint-proving-state.js';
46
34
  import type { TxProvingState } from './tx-proving-state.js';
47
35
 
48
- export type TreeSnapshots = Map<MerkleTreeId, AppendOnlyTreeSnapshot>;
36
+ export type ProofState<T, PROOF_LENGTH extends number> = {
37
+ provingOutput?: PublicInputsAndRecursiveProof<T, PROOF_LENGTH>;
38
+ isProving?: boolean;
39
+ };
49
40
 
50
41
  /**
51
42
  * The current state of the proving schedule for a given block. Managed by ProvingState.
52
43
  * Contains the raw inputs and intermediate state to generate every constituent proof in the tree.
53
44
  */
54
45
  export class BlockProvingState {
55
- private baseOrMergeProvingOutputs: UnbalancedTreeStore<
56
- PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs, typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH>
46
+ private baseOrMergeProofs: UnbalancedTreeStore<
47
+ ProofState<TxRollupPublicInputs, typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH>
57
48
  > = new UnbalancedTreeStore(0);
58
- private baseParityProvingOutputs: (PublicInputsAndRecursiveProof<ParityPublicInputs> | undefined)[];
59
- private rootParityProvingOutput: PublicInputsAndRecursiveProof<ParityPublicInputs> | undefined;
60
- private blockRootProvingOutput:
61
- | PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs, typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH>
49
+ private baseParityProofs: (ProofState<ParityPublicInputs, typeof NESTED_RECURSIVE_PROOF_LENGTH> | undefined)[] =
50
+ Array.from({
51
+ length: NUM_BASE_PARITY_PER_ROOT_PARITY,
52
+ }).map(_ => undefined);
53
+ private rootParityProof: ProofState<ParityPublicInputs, typeof NESTED_RECURSIVE_PROOF_LENGTH> | undefined;
54
+ private blockRootProof:
55
+ | ProofState<BlockRollupPublicInputs, typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH>
62
56
  | undefined;
63
- public blockRootRollupStarted: boolean = false;
64
- public block: L2Block | undefined;
65
- public spongeBlobState: SpongeBlob | undefined;
66
- public startBlobAccumulator: BatchedBlobAccumulator | undefined;
67
- public endBlobAccumulator: BatchedBlobAccumulator | undefined;
68
- public blobsHash: Fr | undefined;
69
- public totalNumTxs: number;
57
+ private builtBlockHeader: BlockHeader | undefined;
58
+ private endSpongeBlob: SpongeBlob | undefined;
70
59
  private txs: TxProvingState[] = [];
71
- public error: string | undefined;
60
+ private isFirstBlock: boolean;
61
+ private error: string | undefined;
72
62
 
73
63
  constructor(
74
64
  public readonly index: number,
75
- public readonly globalVariables: GlobalVariables,
76
- public readonly newL1ToL2Messages: Fr[],
77
- public readonly l1ToL2MessageTreeSnapshot: AppendOnlyTreeSnapshot,
78
- private readonly l1ToL2MessageSubtreeSiblingPath: Tuple<Fr, typeof L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH>,
79
- public readonly l1ToL2MessageTreeSnapshotAfterInsertion: AppendOnlyTreeSnapshot,
80
- private readonly lastArchiveSnapshot: AppendOnlyTreeSnapshot,
65
+ public readonly blockNumber: number,
66
+ public readonly totalNumTxs: number,
67
+ private readonly constants: CheckpointConstantData,
68
+ private readonly timestamp: UInt64,
69
+ public readonly lastArchiveTreeSnapshot: AppendOnlyTreeSnapshot,
81
70
  private readonly lastArchiveSiblingPath: Tuple<Fr, typeof ARCHIVE_HEIGHT>,
82
- private readonly newArchiveSiblingPath: Tuple<Fr, typeof ARCHIVE_HEIGHT>,
83
- private readonly previousBlockHeader: BlockHeader,
84
- private readonly proverId: EthAddress,
85
- private readonly parentEpoch: EpochProvingState,
71
+ private readonly lastL1ToL2MessageTreeSnapshot: AppendOnlyTreeSnapshot,
72
+ private readonly lastL1ToL2MessageSubtreeSiblingPath: Tuple<Fr, typeof L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH>,
73
+ public readonly newL1ToL2MessageTreeSnapshot: AppendOnlyTreeSnapshot,
74
+ private readonly headerOfLastBlockInPreviousCheckpoint: BlockHeader,
75
+ private readonly startSpongeBlob: SpongeBlob,
76
+ public parentCheckpoint: CheckpointProvingState,
86
77
  ) {
87
- this.baseParityProvingOutputs = Array.from({ length: NUM_BASE_PARITY_PER_ROOT_PARITY }).map(_ => undefined);
88
- this.totalNumTxs = 0;
89
- if (this.blockNumber == parentEpoch.firstBlockNumber) {
90
- this.startBlobAccumulator = BatchedBlobAccumulator.newWithChallenges(parentEpoch.finalBlobBatchingChallenges);
78
+ this.isFirstBlock = index === 0;
79
+ if (!totalNumTxs && !this.isFirstBlock) {
80
+ throw new Error(`Cannot create a block with 0 txs, unless it's the first block.`);
91
81
  }
92
- }
93
82
 
94
- public get blockNumber() {
95
- return this.globalVariables.blockNumber;
83
+ this.baseOrMergeProofs = new UnbalancedTreeStore(totalNumTxs);
96
84
  }
97
85
 
98
- public startNewBlock(numTxs: number, numBlobFields: number) {
99
- if (this.spongeBlobState) {
100
- throw new Error(`Block ${this.blockNumber} already initalised.`);
101
- }
102
-
103
- this.baseOrMergeProvingOutputs = new UnbalancedTreeStore(numTxs);
104
- // Initialize the sponge which will eventually absorb all tx effects to be added to the blob.
105
- // Like l1 to l2 messages, we need to know beforehand how many effects will be absorbed.
106
- this.spongeBlobState = SpongeBlob.init(numBlobFields);
107
- this.totalNumTxs = numTxs;
86
+ public get epochNumber(): number {
87
+ return this.parentCheckpoint.epochNumber;
108
88
  }
109
89
 
110
90
  // Adds a transaction to the proving state, returns it's index
111
91
  public addNewTx(tx: TxProvingState) {
112
- if (!this.spongeBlobState) {
113
- throw new Error(`Invalid block proving state, call startNewBlock before adding transactions.`);
92
+ if (!this.isAcceptingTxs()) {
93
+ throw new Error(`Cannot add more txs to block ${this.blockNumber}.`);
114
94
  }
115
95
  const txIndex = this.txs.length;
116
96
  this.txs[txIndex] = tx;
117
97
  return txIndex;
118
98
  }
119
99
 
100
+ public isAcceptingTxs() {
101
+ return this.txs.length < this.totalNumTxs;
102
+ }
103
+
104
+ public getProcessedTxs() {
105
+ return this.txs.map(t => t.processedTx);
106
+ }
107
+
108
+ public tryStartProvingBase(txIndex: number) {
109
+ if (this.baseOrMergeProofs.getLeaf(txIndex)?.isProving) {
110
+ return false;
111
+ } else {
112
+ this.baseOrMergeProofs.setLeaf(txIndex, { isProving: true });
113
+ return true;
114
+ }
115
+ }
116
+
120
117
  public setBaseRollupProof(
121
118
  txIndex: number,
122
119
  provingOutput: PublicInputsAndRecursiveProof<
123
- BaseOrMergeRollupPublicInputs,
120
+ TxRollupPublicInputs,
124
121
  typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH
125
122
  >,
126
123
  ): TreeNodeLocation {
127
- return this.baseOrMergeProvingOutputs.setLeaf(txIndex, provingOutput);
124
+ return this.baseOrMergeProofs.setLeaf(txIndex, { provingOutput });
125
+ }
126
+
127
+ public tryStartProvingMerge(location: TreeNodeLocation) {
128
+ if (this.baseOrMergeProofs.getNode(location)?.isProving) {
129
+ return false;
130
+ } else {
131
+ this.baseOrMergeProofs.setNode(location, { isProving: true });
132
+ return true;
133
+ }
128
134
  }
129
135
 
130
136
  public setMergeRollupProof(
131
137
  location: TreeNodeLocation,
132
138
  provingOutput: PublicInputsAndRecursiveProof<
133
- BaseOrMergeRollupPublicInputs,
139
+ TxRollupPublicInputs,
134
140
  typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH
135
141
  >,
136
142
  ) {
137
- this.baseOrMergeProvingOutputs.setNode(location, provingOutput);
143
+ this.baseOrMergeProofs.setNode(location, { provingOutput });
144
+ }
145
+
146
+ public tryStartProvingBaseParity(index: number) {
147
+ if (this.baseParityProofs[index]?.isProving) {
148
+ return false;
149
+ } else {
150
+ this.baseParityProofs[index] = { isProving: true };
151
+ return true;
152
+ }
138
153
  }
139
154
 
140
155
  // Stores a set of root parity inputs at the given index
@@ -144,144 +159,179 @@ export class BlockProvingState {
144
159
  `Unable to set a base parity proofs at index ${index}. Expected at most ${NUM_BASE_PARITY_PER_ROOT_PARITY} proofs.`,
145
160
  );
146
161
  }
147
- this.baseParityProvingOutputs[index] = provingOutput;
162
+ this.baseParityProofs[index] = { provingOutput };
163
+ }
164
+
165
+ public tryStartProvingRootParity() {
166
+ if (this.rootParityProof?.isProving) {
167
+ return false;
168
+ } else {
169
+ this.rootParityProof = { isProving: true };
170
+ return true;
171
+ }
148
172
  }
149
173
 
150
174
  public setRootParityProof(provingOutput: PublicInputsAndRecursiveProof<ParityPublicInputs>) {
151
- this.rootParityProvingOutput = provingOutput;
175
+ this.rootParityProof = { provingOutput };
176
+ }
177
+
178
+ public tryStartProvingBlockRoot() {
179
+ if (this.blockRootProof?.isProving) {
180
+ return false;
181
+ } else {
182
+ this.blockRootProof = { isProving: true };
183
+ return true;
184
+ }
152
185
  }
153
186
 
154
187
  public setBlockRootRollupProof(
155
188
  provingOutput: PublicInputsAndRecursiveProof<
156
- BlockRootOrBlockMergePublicInputs,
189
+ BlockRollupPublicInputs,
157
190
  typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH
158
191
  >,
159
- ) {
160
- this.blockRootProvingOutput = provingOutput;
192
+ ): TreeNodeLocation {
193
+ this.blockRootProof = { provingOutput };
194
+ return this.parentCheckpoint.setBlockRootRollupProof(this.index, provingOutput);
161
195
  }
162
196
 
163
- public setBlock(block: L2Block) {
164
- this.block = block;
197
+ public getBlockRootRollupOutput() {
198
+ return this.blockRootProof?.provingOutput?.inputs;
165
199
  }
166
200
 
167
- public setStartBlobAccumulator(accumulator: BatchedBlobAccumulator) {
168
- this.startBlobAccumulator = accumulator;
201
+ public setBuiltBlockHeader(blockHeader: BlockHeader) {
202
+ this.builtBlockHeader = blockHeader;
169
203
  }
170
204
 
171
- public setEndBlobAccumulator(accumulator: BatchedBlobAccumulator) {
172
- this.endBlobAccumulator = accumulator;
205
+ public getBuiltBlockHeader() {
206
+ return this.builtBlockHeader;
173
207
  }
174
208
 
175
- public async accumulateBlobs() {
176
- if (!this.block || !this.startBlobAccumulator) {
177
- // We only want to accumulate once we have all txs, so we wait until the block is set.
178
- return;
209
+ public getGlobalVariables() {
210
+ if (this.txs.length) {
211
+ return this.txs[0].processedTx.globalVariables;
179
212
  }
180
- const endBlobAccumulator = await accumulateBlobs(
181
- this.allTxs.map(t => t.processedTx),
182
- this.startBlobAccumulator,
183
- );
184
- this.setEndBlobAccumulator(endBlobAccumulator);
213
+
214
+ const constants = this.constants;
215
+ return GlobalVariables.from({
216
+ chainId: constants.chainId,
217
+ version: constants.version,
218
+ blockNumber: this.blockNumber,
219
+ slotNumber: constants.slotNumber,
220
+ timestamp: this.timestamp,
221
+ coinbase: constants.coinbase,
222
+ feeRecipient: constants.feeRecipient,
223
+ gasFees: constants.gasFees,
224
+ });
185
225
  }
186
226
 
187
- // Returns the complete set of transaction proving state objects
188
- public get allTxs() {
189
- return this.txs;
227
+ public getStartSpongeBlob() {
228
+ return this.startSpongeBlob;
190
229
  }
191
230
 
192
- /** Returns the block number as an epoch number. Used for prioritizing proof requests. */
193
- public get epochNumber(): number {
194
- return this.parentEpoch.epochNumber;
231
+ public setEndSpongeBlob(endSpongeBlob: SpongeBlob) {
232
+ this.endSpongeBlob = endSpongeBlob;
233
+ }
234
+
235
+ public getEndSpongeBlob() {
236
+ return this.endSpongeBlob;
237
+ }
238
+
239
+ public getBlockBlobFields() {
240
+ return getBlockBlobFields(this.txs.map(t => t.processedTx.txEffect));
195
241
  }
196
242
 
197
243
  public getParentLocation(location: TreeNodeLocation) {
198
- return this.baseOrMergeProvingOutputs.getParentLocation(location);
244
+ return this.baseOrMergeProofs.getParentLocation(location);
199
245
  }
200
246
 
201
247
  public getMergeRollupInputs(mergeLocation: TreeNodeLocation) {
202
- const [left, right] = this.baseOrMergeProvingOutputs.getChildren(mergeLocation);
248
+ const [left, right] = this.baseOrMergeProofs.getChildren(mergeLocation).map(c => c?.provingOutput);
203
249
  if (!left || !right) {
204
- throw new Error('At lease one child is not ready.');
250
+ throw new Error('At least one child is not ready for the merge rollup.');
205
251
  }
206
252
 
207
- return new MergeRollupInputs([this.#getPreviousRollupData(left), this.#getPreviousRollupData(right)]);
253
+ return new TxMergeRollupPrivateInputs([toProofData(left), toProofData(right)]);
208
254
  }
209
255
 
210
- public async getBlockRootRollupTypeAndInputs() {
211
- if (!this.rootParityProvingOutput) {
212
- throw new Error('Root parity is not ready.');
213
- }
214
-
215
- const proofs = this.#getChildProofsForBlockRoot();
216
- const nonEmptyProofs = proofs.filter(p => !!p);
217
- if (proofs.length !== nonEmptyProofs.length) {
218
- throw new Error('At lease one child is not ready for the block root.');
256
+ public getBlockRootRollupTypeAndInputs() {
257
+ const provingOutputs = this.#getChildProvingOutputsForBlockRoot();
258
+ if (!provingOutputs.every(p => !!p)) {
259
+ throw new Error('At least one child is not ready for the block root rollup.');
219
260
  }
220
261
 
221
- const data = this.#getBlockRootRollupData();
262
+ const previousRollups = provingOutputs.map(p => toProofData(p));
222
263
 
223
- if (this.totalNumTxs === 0) {
224
- const constants = BlockConstantData.from({
225
- lastArchive: this.lastArchiveSnapshot,
226
- newL1ToL2: this.l1ToL2MessageTreeSnapshotAfterInsertion,
227
- globalVariables: this.globalVariables,
228
- vkTreeRoot: getVKTreeRoot(),
229
- protocolContractTreeRoot,
230
- });
231
-
232
- this.blobsHash = await getEmptyBlockBlobsHash();
264
+ if (this.isFirstBlock) {
265
+ return this.#getFirstBlockRootRollupTypeAndInputs(previousRollups);
266
+ }
233
267
 
268
+ const [leftRollup, rightRollup] = previousRollups;
269
+ if (!rightRollup) {
270
+ return {
271
+ rollupType: 'rollup-block-root-single-tx' satisfies CircuitName,
272
+ inputs: new BlockRootSingleTxRollupPrivateInputs(leftRollup, this.lastArchiveSiblingPath),
273
+ };
274
+ } else {
234
275
  return {
235
- rollupType: 'empty-block-root-rollup' satisfies CircuitName,
236
- inputs: EmptyBlockRootRollupInputs.from({
237
- data,
238
- constants,
239
- }),
276
+ rollupType: 'rollup-block-root' satisfies CircuitName,
277
+ inputs: new BlockRootRollupPrivateInputs([leftRollup, rightRollup], this.lastArchiveSiblingPath),
240
278
  };
241
279
  }
280
+ }
242
281
 
243
- const previousRollupData = await Promise.all(nonEmptyProofs.map(p => this.#getPreviousRollupData(p!)));
244
- const blobData = await this.#getBlockRootRollupBlobData();
245
- this.blobsHash = blobData.blobsHash;
282
+ #getFirstBlockRootRollupTypeAndInputs([leftRollup, rightRollup]: RollupHonkProofData<TxRollupPublicInputs>[]) {
283
+ if (!this.rootParityProof?.provingOutput) {
284
+ throw new Error('Root parity is not ready.');
285
+ }
286
+ const l1ToL2Roots = toProofData(this.rootParityProof.provingOutput);
246
287
 
247
- if (previousRollupData.length === 1) {
288
+ if (!leftRollup) {
289
+ return {
290
+ rollupType: 'rollup-block-root-first-empty-tx' satisfies CircuitName,
291
+ inputs: new BlockRootEmptyTxFirstRollupPrivateInputs(
292
+ l1ToL2Roots,
293
+ this.lastArchiveTreeSnapshot,
294
+ this.headerOfLastBlockInPreviousCheckpoint.state,
295
+ this.constants,
296
+ this.startSpongeBlob,
297
+ this.timestamp,
298
+ this.lastL1ToL2MessageSubtreeSiblingPath,
299
+ this.lastArchiveSiblingPath,
300
+ ),
301
+ };
302
+ } else if (!rightRollup) {
248
303
  return {
249
- rollupType: 'single-tx-block-root-rollup' satisfies CircuitName,
250
- inputs: new SingleTxBlockRootRollupInputs(previousRollupData as [PreviousRollupData], data, blobData),
304
+ rollupType: 'rollup-block-root-first-single-tx' satisfies CircuitName,
305
+ inputs: new BlockRootSingleTxFirstRollupPrivateInputs(
306
+ l1ToL2Roots,
307
+ leftRollup,
308
+ this.lastL1ToL2MessageTreeSnapshot,
309
+ this.lastL1ToL2MessageSubtreeSiblingPath,
310
+ this.lastArchiveSiblingPath,
311
+ ),
251
312
  };
252
313
  } else {
253
314
  return {
254
- rollupType: 'block-root-rollup' satisfies CircuitName,
255
- inputs: new BlockRootRollupInputs(
256
- previousRollupData as [PreviousRollupData, PreviousRollupData],
257
- data,
258
- blobData,
315
+ rollupType: 'rollup-block-root-first' satisfies CircuitName,
316
+ inputs: new BlockRootFirstRollupPrivateInputs(
317
+ l1ToL2Roots,
318
+ [leftRollup, rightRollup],
319
+ this.lastL1ToL2MessageTreeSnapshot,
320
+ this.lastL1ToL2MessageSubtreeSiblingPath,
321
+ this.lastArchiveSiblingPath,
259
322
  ),
260
323
  };
261
324
  }
262
325
  }
263
326
 
264
- public getPaddingBlockRootInputs() {
265
- const constants = EpochConstantData.from({
266
- vkTreeRoot: getVKTreeRoot(),
267
- protocolContractTreeRoot,
268
- proverId: this.proverId.toField(),
269
- });
270
-
271
- return PaddingBlockRootRollupInputs.from({
272
- constants,
273
- });
274
- }
275
-
276
- public getRootParityInputs() {
277
- if (!this.baseParityProvingOutputs.every(p => !!p)) {
327
+ public getParityRootInputs() {
328
+ const baseParityProvingOutputs = this.baseParityProofs.filter(p => !!p?.provingOutput).map(p => p!.provingOutput!);
329
+ if (baseParityProvingOutputs.length !== this.baseParityProofs.length) {
278
330
  throw new Error('At lease one base parity is not ready.');
279
331
  }
280
332
 
281
- const children = this.baseParityProvingOutputs.map(p => this.#getRootParityData(p!));
282
- return new RootParityInputs(
283
- children as Tuple<RootParityInput<typeof RECURSIVE_PROOF_LENGTH>, typeof NUM_BASE_PARITY_PER_ROOT_PARITY>,
284
- );
333
+ const children = baseParityProvingOutputs.map(p => toProofData(p));
334
+ return new ParityRootPrivateInputs(assertLength(children, NUM_BASE_PARITY_PER_ROOT_PARITY));
285
335
  }
286
336
 
287
337
  // Returns a specific transaction proving state
@@ -290,89 +340,46 @@ export class BlockProvingState {
290
340
  }
291
341
 
292
342
  public async buildHeaderFromProvingOutputs() {
293
- const previousRollupData =
294
- this.totalNumTxs === 0
295
- ? []
296
- : await Promise.all(this.#getChildProofsForBlockRoot().map(p => this.#getPreviousRollupData(p!)));
297
-
298
- let endPartialState = this.previousBlockHeader.state.partial;
299
- if (this.totalNumTxs !== 0) {
300
- const previousRollupData = this.#getChildProofsForBlockRoot();
301
- const lastRollup = previousRollupData[previousRollupData.length - 1];
302
- if (!lastRollup) {
303
- throw new Error('End state of the block is not available. Last rollup is not ready yet.');
304
- }
305
- endPartialState = lastRollup.inputs.end;
343
+ if (!this.blockRootProof?.provingOutput) {
344
+ throw new Error('Block root rollup is not ready.');
306
345
  }
307
- const endState = new StateReference(this.l1ToL2MessageTreeSnapshotAfterInsertion, endPartialState);
308
346
 
309
- return buildHeaderFromCircuitOutputs(
310
- previousRollupData.map(d => d.baseOrMergeRollupPublicInputs),
311
- this.rootParityProvingOutput!.inputs,
312
- this.blockRootProvingOutput!.inputs,
313
- this.blobsHash!,
314
- endState,
315
- );
347
+ return await buildHeaderFromCircuitOutputs(this.blockRootProof.provingOutput.inputs);
316
348
  }
317
349
 
318
350
  public isReadyForMergeRollup(location: TreeNodeLocation) {
319
- return this.baseOrMergeProvingOutputs.getSibling(location) !== undefined;
351
+ return !!this.baseOrMergeProofs.getSibling(location)?.provingOutput;
320
352
  }
321
353
 
322
354
  // Returns true if we have sufficient inputs to execute the block root rollup
323
355
  public isReadyForBlockRootRollup() {
324
- const childProofs = this.#getChildProofsForBlockRoot();
325
- return (
326
- this.block !== undefined &&
327
- this.rootParityProvingOutput !== undefined &&
328
- this.endBlobAccumulator !== undefined &&
329
- childProofs.every(p => !!p)
330
- );
356
+ const childProofs = this.#getChildProvingOutputsForBlockRoot();
357
+ return (!this.isFirstBlock || !!this.rootParityProof?.provingOutput) && childProofs.every(p => !!p);
331
358
  }
332
359
 
333
360
  // Returns true if we have sufficient root parity inputs to execute the root parity circuit
334
361
  public isReadyForRootParity() {
335
- return this.baseParityProvingOutputs.every(p => !!p);
362
+ return this.baseParityProofs.every(p => !!p?.provingOutput);
336
363
  }
337
364
 
338
365
  public isComplete() {
339
- return !!this.blockRootProvingOutput;
366
+ return !!this.blockRootProof;
340
367
  }
341
368
 
342
- // Returns whether the proving state is still valid
343
369
  public verifyState() {
344
- return this.parentEpoch.verifyState();
370
+ return this.parentCheckpoint.verifyState();
345
371
  }
346
372
 
347
- public reject(reason: string) {
348
- this.error = reason;
349
- this.parentEpoch.reject(reason);
350
- }
351
-
352
- #getBlockRootRollupData() {
353
- return BlockRootRollupData.from({
354
- l1ToL2Roots: this.#getRootParityData(this.rootParityProvingOutput!),
355
- l1ToL2MessageSubtreeSiblingPath: this.l1ToL2MessageSubtreeSiblingPath,
356
- previousArchiveSiblingPath: this.lastArchiveSiblingPath,
357
- newArchiveSiblingPath: this.newArchiveSiblingPath,
358
- previousBlockHeader: this.previousBlockHeader,
359
- startBlobAccumulator: BlobAccumulatorPublicInputs.fromBatchedBlobAccumulator(this.startBlobAccumulator!),
360
- finalBlobChallenges: this.startBlobAccumulator!.finalBlobChallenges,
361
- proverId: this.proverId.toField(),
362
- });
373
+ public getError() {
374
+ return this.error;
363
375
  }
364
376
 
365
- async #getBlockRootRollupBlobData() {
366
- const txEffects = this.txs.map(txProvingState => txProvingState.processedTx.txEffect);
367
- const { blobFields, blobCommitments, blobsHash } = await buildBlobHints(txEffects);
368
- return BlockRootRollupBlobData.from({
369
- blobFields: padArrayEnd(blobFields, Fr.ZERO, FIELDS_PER_BLOB * BLOBS_PER_BLOCK),
370
- blobCommitments: padArrayEnd(blobCommitments, BLS12Point.ZERO, BLOBS_PER_BLOCK),
371
- blobsHash,
372
- });
377
+ public reject(reason: string) {
378
+ this.error = reason;
379
+ this.parentCheckpoint.reject(reason);
373
380
  }
374
381
 
375
- #getChildProofsForBlockRoot() {
382
+ #getChildProvingOutputsForBlockRoot() {
376
383
  if (this.totalNumTxs === 0) {
377
384
  return [];
378
385
  }
@@ -380,26 +387,7 @@ export class BlockProvingState {
380
387
  const rootLocation = { level: 0, index: 0 };
381
388
  // If there's only 1 tx, its base rollup proof will be stored at the root.
382
389
  return this.totalNumTxs === 1
383
- ? [this.baseOrMergeProvingOutputs.getNode(rootLocation)]
384
- : this.baseOrMergeProvingOutputs.getChildren(rootLocation);
385
- }
386
-
387
- #getPreviousRollupData({
388
- inputs,
389
- proof,
390
- verificationKey,
391
- }: PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs, typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH>) {
392
- const leafIndex = getVKIndex(verificationKey.keyAsFields);
393
- const vkData = new VkData(verificationKey, leafIndex, getVKSiblingPath(leafIndex));
394
- return new PreviousRollupData(inputs, proof, vkData);
395
- }
396
-
397
- #getRootParityData({ inputs, proof, verificationKey }: PublicInputsAndRecursiveProof<ParityPublicInputs>) {
398
- return new RootParityInput(
399
- proof,
400
- verificationKey.keyAsFields,
401
- getVKSiblingPath(getVKIndex(verificationKey)),
402
- inputs,
403
- );
390
+ ? [this.baseOrMergeProofs.getNode(rootLocation)?.provingOutput]
391
+ : this.baseOrMergeProofs.getChildren(rootLocation).map(c => c?.provingOutput);
404
392
  }
405
393
  }