@aztec/prover-client 4.0.0-nightly.20250907 → 4.0.0-nightly.20260107

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 (129) hide show
  1. package/dest/block-factory/index.d.ts +1 -1
  2. package/dest/block-factory/light.d.ts +5 -3
  3. package/dest/block-factory/light.d.ts.map +1 -1
  4. package/dest/block-factory/light.js +32 -11
  5. package/dest/config.d.ts +2 -2
  6. package/dest/config.d.ts.map +1 -1
  7. package/dest/config.js +2 -2
  8. package/dest/index.d.ts +1 -1
  9. package/dest/light/index.d.ts +2 -0
  10. package/dest/light/index.d.ts.map +1 -0
  11. package/dest/light/index.js +1 -0
  12. package/dest/light/lightweight_checkpoint_builder.d.ts +36 -0
  13. package/dest/light/lightweight_checkpoint_builder.d.ts.map +1 -0
  14. package/dest/light/lightweight_checkpoint_builder.js +147 -0
  15. package/dest/mocks/fixtures.d.ts +5 -5
  16. package/dest/mocks/fixtures.d.ts.map +1 -1
  17. package/dest/mocks/fixtures.js +33 -15
  18. package/dest/mocks/test_context.d.ts +38 -33
  19. package/dest/mocks/test_context.d.ts.map +1 -1
  20. package/dest/mocks/test_context.js +133 -82
  21. package/dest/orchestrator/block-building-helpers.d.ts +35 -35
  22. package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
  23. package/dest/orchestrator/block-building-helpers.js +151 -187
  24. package/dest/orchestrator/block-proving-state.d.ts +68 -55
  25. package/dest/orchestrator/block-proving-state.d.ts.map +1 -1
  26. package/dest/orchestrator/block-proving-state.js +273 -185
  27. package/dest/orchestrator/checkpoint-proving-state.d.ts +63 -0
  28. package/dest/orchestrator/checkpoint-proving-state.d.ts.map +1 -0
  29. package/dest/orchestrator/checkpoint-proving-state.js +210 -0
  30. package/dest/orchestrator/epoch-proving-state.d.ts +38 -31
  31. package/dest/orchestrator/epoch-proving-state.d.ts.map +1 -1
  32. package/dest/orchestrator/epoch-proving-state.js +128 -84
  33. package/dest/orchestrator/index.d.ts +1 -1
  34. package/dest/orchestrator/orchestrator.d.ts +35 -34
  35. package/dest/orchestrator/orchestrator.d.ts.map +1 -1
  36. package/dest/orchestrator/orchestrator.js +777 -292
  37. package/dest/orchestrator/orchestrator_metrics.d.ts +1 -3
  38. package/dest/orchestrator/orchestrator_metrics.d.ts.map +1 -1
  39. package/dest/orchestrator/orchestrator_metrics.js +0 -9
  40. package/dest/orchestrator/tx-proving-state.d.ts +12 -10
  41. package/dest/orchestrator/tx-proving-state.d.ts.map +1 -1
  42. package/dest/orchestrator/tx-proving-state.js +23 -29
  43. package/dest/prover-client/factory.d.ts +3 -3
  44. package/dest/prover-client/factory.d.ts.map +1 -1
  45. package/dest/prover-client/index.d.ts +1 -1
  46. package/dest/prover-client/prover-client.d.ts +3 -3
  47. package/dest/prover-client/prover-client.d.ts.map +1 -1
  48. package/dest/prover-client/server-epoch-prover.d.ts +13 -11
  49. package/dest/prover-client/server-epoch-prover.d.ts.map +1 -1
  50. package/dest/prover-client/server-epoch-prover.js +9 -9
  51. package/dest/proving_broker/broker_prover_facade.d.ts +23 -18
  52. package/dest/proving_broker/broker_prover_facade.d.ts.map +1 -1
  53. package/dest/proving_broker/broker_prover_facade.js +42 -33
  54. package/dest/proving_broker/config.d.ts +18 -14
  55. package/dest/proving_broker/config.d.ts.map +1 -1
  56. package/dest/proving_broker/config.js +12 -6
  57. package/dest/proving_broker/factory.d.ts +1 -1
  58. package/dest/proving_broker/factory.js +1 -1
  59. package/dest/proving_broker/fixtures.d.ts +3 -2
  60. package/dest/proving_broker/fixtures.d.ts.map +1 -1
  61. package/dest/proving_broker/fixtures.js +3 -2
  62. package/dest/proving_broker/index.d.ts +1 -1
  63. package/dest/proving_broker/proof_store/factory.d.ts +2 -2
  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/index.d.ts +2 -1
  67. package/dest/proving_broker/proof_store/index.d.ts.map +1 -1
  68. package/dest/proving_broker/proof_store/index.js +1 -0
  69. package/dest/proving_broker/proof_store/inline_proof_store.d.ts +1 -1
  70. package/dest/proving_broker/proof_store/inline_proof_store.d.ts.map +1 -1
  71. package/dest/proving_broker/proof_store/proof_store.d.ts +1 -1
  72. package/dest/proving_broker/proving_agent.d.ts +1 -1
  73. package/dest/proving_broker/proving_agent.d.ts.map +1 -1
  74. package/dest/proving_broker/proving_agent.js +383 -8
  75. package/dest/proving_broker/proving_agent_instrumentation.d.ts +1 -1
  76. package/dest/proving_broker/proving_agent_instrumentation.d.ts.map +1 -1
  77. package/dest/proving_broker/proving_broker.d.ts +2 -2
  78. package/dest/proving_broker/proving_broker.d.ts.map +1 -1
  79. package/dest/proving_broker/proving_broker.js +418 -29
  80. package/dest/proving_broker/proving_broker_database/memory.d.ts +3 -2
  81. package/dest/proving_broker/proving_broker_database/memory.d.ts.map +1 -1
  82. package/dest/proving_broker/proving_broker_database/persisted.d.ts +3 -2
  83. package/dest/proving_broker/proving_broker_database/persisted.d.ts.map +1 -1
  84. package/dest/proving_broker/proving_broker_database/persisted.js +8 -7
  85. package/dest/proving_broker/proving_broker_database.d.ts +3 -2
  86. package/dest/proving_broker/proving_broker_database.d.ts.map +1 -1
  87. package/dest/proving_broker/proving_broker_instrumentation.d.ts +1 -1
  88. package/dest/proving_broker/proving_broker_instrumentation.d.ts.map +1 -1
  89. package/dest/proving_broker/proving_job_controller.d.ts +3 -2
  90. package/dest/proving_broker/proving_job_controller.d.ts.map +1 -1
  91. package/dest/proving_broker/proving_job_controller.js +40 -21
  92. package/dest/proving_broker/rpc.d.ts +4 -4
  93. package/dest/test/mock_proof_store.d.ts +3 -3
  94. package/dest/test/mock_proof_store.d.ts.map +1 -1
  95. package/dest/test/mock_prover.d.ts +23 -19
  96. package/dest/test/mock_prover.d.ts.map +1 -1
  97. package/dest/test/mock_prover.js +36 -21
  98. package/package.json +21 -19
  99. package/src/block-factory/light.ts +40 -17
  100. package/src/config.ts +2 -2
  101. package/src/light/index.ts +1 -0
  102. package/src/light/lightweight_checkpoint_builder.ts +198 -0
  103. package/src/mocks/fixtures.ts +41 -36
  104. package/src/mocks/test_context.ts +196 -114
  105. package/src/orchestrator/block-building-helpers.ts +233 -313
  106. package/src/orchestrator/block-proving-state.ts +315 -247
  107. package/src/orchestrator/checkpoint-proving-state.ts +303 -0
  108. package/src/orchestrator/epoch-proving-state.ts +176 -129
  109. package/src/orchestrator/orchestrator.ts +558 -348
  110. package/src/orchestrator/orchestrator_metrics.ts +1 -20
  111. package/src/orchestrator/tx-proving-state.ts +47 -55
  112. package/src/prover-client/factory.ts +6 -2
  113. package/src/prover-client/prover-client.ts +3 -2
  114. package/src/prover-client/server-epoch-prover.ts +30 -21
  115. package/src/proving_broker/broker_prover_facade.ts +175 -112
  116. package/src/proving_broker/config.ts +14 -7
  117. package/src/proving_broker/factory.ts +1 -1
  118. package/src/proving_broker/fixtures.ts +8 -3
  119. package/src/proving_broker/proof_store/index.ts +1 -0
  120. package/src/proving_broker/proving_broker.ts +41 -19
  121. package/src/proving_broker/proving_broker_database/memory.ts +2 -1
  122. package/src/proving_broker/proving_broker_database/persisted.ts +10 -9
  123. package/src/proving_broker/proving_broker_database.ts +2 -1
  124. package/src/proving_broker/proving_job_controller.ts +42 -22
  125. package/src/test/mock_prover.ts +143 -66
  126. package/dest/bin/get-proof-inputs.d.ts +0 -2
  127. package/dest/bin/get-proof-inputs.d.ts.map +0 -1
  128. package/dest/bin/get-proof-inputs.js +0 -51
  129. package/src/bin/get-proof-inputs.ts +0 -59
@@ -1,140 +1,159 @@
1
- import { BatchedBlobAccumulator, BlobAccumulatorPublicInputs, SpongeBlob } from '@aztec/blob-lib';
1
+ import { type BlockBlobData, type BlockEndBlobData, type SpongeBlob, encodeBlockEndBlobData } from '@aztec/blob-lib';
2
2
  import {
3
3
  type ARCHIVE_HEIGHT,
4
- BLOBS_PER_BLOCK,
5
- FIELDS_PER_BLOB,
6
- type L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH,
4
+ type L1_TO_L2_MSG_SUBTREE_ROOT_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 { BlockNumber } from '@aztec/foundation/branded-types';
10
+ import { Fr } from '@aztec/foundation/curves/bn254';
11
+ import { type Tuple, assertLength } from '@aztec/foundation/serialize';
14
12
  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';
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 { BlockHeader, GlobalVariables, StateReference } 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 endState: StateReference | undefined;
59
+ private endSpongeBlob: SpongeBlob | undefined;
70
60
  private txs: TxProvingState[] = [];
71
- public error: string | undefined;
61
+ private isFirstBlock: boolean;
62
+ private error: string | undefined;
72
63
 
73
64
  constructor(
74
65
  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,
66
+ public readonly blockNumber: BlockNumber,
67
+ public readonly totalNumTxs: number,
68
+ private readonly constants: CheckpointConstantData,
69
+ private readonly timestamp: UInt64,
70
+ public readonly lastArchiveTreeSnapshot: AppendOnlyTreeSnapshot,
81
71
  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,
72
+ private readonly lastL1ToL2MessageTreeSnapshot: AppendOnlyTreeSnapshot,
73
+ private readonly lastL1ToL2MessageSubtreeRootSiblingPath: Tuple<
74
+ Fr,
75
+ typeof L1_TO_L2_MSG_SUBTREE_ROOT_SIBLING_PATH_LENGTH
76
+ >,
77
+ public readonly newL1ToL2MessageTreeSnapshot: AppendOnlyTreeSnapshot,
78
+ private readonly headerOfLastBlockInPreviousCheckpoint: BlockHeader,
79
+ private readonly startSpongeBlob: SpongeBlob,
80
+ public parentCheckpoint: CheckpointProvingState,
86
81
  ) {
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);
82
+ this.isFirstBlock = index === 0;
83
+ if (!totalNumTxs && !this.isFirstBlock) {
84
+ throw new Error(`Cannot create a block with 0 txs, unless it's the first block.`);
91
85
  }
92
- }
93
86
 
94
- public get blockNumber() {
95
- return this.globalVariables.blockNumber;
87
+ this.baseOrMergeProofs = new UnbalancedTreeStore(totalNumTxs);
96
88
  }
97
89
 
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;
90
+ public get epochNumber(): number {
91
+ return this.parentCheckpoint.epochNumber;
108
92
  }
109
93
 
110
94
  // Adds a transaction to the proving state, returns it's index
111
95
  public addNewTx(tx: TxProvingState) {
112
- if (!this.spongeBlobState) {
113
- throw new Error(`Invalid block proving state, call startNewBlock before adding transactions.`);
96
+ if (!this.isAcceptingTxs()) {
97
+ throw new Error(`Cannot add more txs to block ${this.blockNumber}.`);
114
98
  }
115
99
  const txIndex = this.txs.length;
116
100
  this.txs[txIndex] = tx;
117
101
  return txIndex;
118
102
  }
119
103
 
104
+ public isAcceptingTxs() {
105
+ return this.txs.length < this.totalNumTxs;
106
+ }
107
+
108
+ public getProcessedTxs() {
109
+ return this.txs.map(t => t.processedTx);
110
+ }
111
+
112
+ public tryStartProvingBase(txIndex: number) {
113
+ if (this.baseOrMergeProofs.getLeaf(txIndex)?.isProving) {
114
+ return false;
115
+ } else {
116
+ this.baseOrMergeProofs.setLeaf(txIndex, { isProving: true });
117
+ return true;
118
+ }
119
+ }
120
+
120
121
  public setBaseRollupProof(
121
122
  txIndex: number,
122
123
  provingOutput: PublicInputsAndRecursiveProof<
123
- BaseOrMergeRollupPublicInputs,
124
+ TxRollupPublicInputs,
124
125
  typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH
125
126
  >,
126
127
  ): TreeNodeLocation {
127
- return this.baseOrMergeProvingOutputs.setLeaf(txIndex, provingOutput);
128
+ return this.baseOrMergeProofs.setLeaf(txIndex, { provingOutput });
129
+ }
130
+
131
+ public tryStartProvingMerge(location: TreeNodeLocation) {
132
+ if (this.baseOrMergeProofs.getNode(location)?.isProving) {
133
+ return false;
134
+ } else {
135
+ this.baseOrMergeProofs.setNode(location, { isProving: true });
136
+ return true;
137
+ }
128
138
  }
129
139
 
130
140
  public setMergeRollupProof(
131
141
  location: TreeNodeLocation,
132
142
  provingOutput: PublicInputsAndRecursiveProof<
133
- BaseOrMergeRollupPublicInputs,
143
+ TxRollupPublicInputs,
134
144
  typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH
135
145
  >,
136
146
  ) {
137
- this.baseOrMergeProvingOutputs.setNode(location, provingOutput);
147
+ this.baseOrMergeProofs.setNode(location, { provingOutput });
148
+ }
149
+
150
+ public tryStartProvingBaseParity(index: number) {
151
+ if (this.baseParityProofs[index]?.isProving) {
152
+ return false;
153
+ } else {
154
+ this.baseParityProofs[index] = { isProving: true };
155
+ return true;
156
+ }
138
157
  }
139
158
 
140
159
  // Stores a set of root parity inputs at the given index
@@ -144,144 +163,228 @@ export class BlockProvingState {
144
163
  `Unable to set a base parity proofs at index ${index}. Expected at most ${NUM_BASE_PARITY_PER_ROOT_PARITY} proofs.`,
145
164
  );
146
165
  }
147
- this.baseParityProvingOutputs[index] = provingOutput;
166
+ this.baseParityProofs[index] = { provingOutput };
167
+ }
168
+
169
+ public tryStartProvingRootParity() {
170
+ if (this.rootParityProof?.isProving) {
171
+ return false;
172
+ } else {
173
+ this.rootParityProof = { isProving: true };
174
+ return true;
175
+ }
148
176
  }
149
177
 
150
178
  public setRootParityProof(provingOutput: PublicInputsAndRecursiveProof<ParityPublicInputs>) {
151
- this.rootParityProvingOutput = provingOutput;
179
+ this.rootParityProof = { provingOutput };
180
+ }
181
+
182
+ public tryStartProvingBlockRoot() {
183
+ if (this.blockRootProof?.isProving) {
184
+ return false;
185
+ } else {
186
+ this.blockRootProof = { isProving: true };
187
+ return true;
188
+ }
152
189
  }
153
190
 
154
191
  public setBlockRootRollupProof(
155
192
  provingOutput: PublicInputsAndRecursiveProof<
156
- BlockRootOrBlockMergePublicInputs,
193
+ BlockRollupPublicInputs,
157
194
  typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH
158
195
  >,
159
- ) {
160
- this.blockRootProvingOutput = provingOutput;
196
+ ): TreeNodeLocation {
197
+ this.blockRootProof = { provingOutput };
198
+ return this.parentCheckpoint.setBlockRootRollupProof(this.index, provingOutput);
161
199
  }
162
200
 
163
- public setBlock(block: L2Block) {
164
- this.block = block;
201
+ public getBlockRootRollupOutput() {
202
+ return this.blockRootProof?.provingOutput?.inputs;
165
203
  }
166
204
 
167
- public setStartBlobAccumulator(accumulator: BatchedBlobAccumulator) {
168
- this.startBlobAccumulator = accumulator;
205
+ public async buildBlockHeader() {
206
+ if (this.isAcceptingTxs()) {
207
+ throw new Error('All txs must be added to the block before building the header.');
208
+ }
209
+ if (!this.endState) {
210
+ throw new Error('Call `setEndState` first.');
211
+ }
212
+ if (!this.endSpongeBlob) {
213
+ throw new Error('Call `setEndSpongeBlob` first.');
214
+ }
215
+
216
+ const endSpongeBlob = this.endSpongeBlob.clone();
217
+ const endSpongeBlobHash = await endSpongeBlob.squeeze();
218
+
219
+ this.builtBlockHeader = new BlockHeader(
220
+ this.lastArchiveTreeSnapshot,
221
+ this.endState,
222
+ endSpongeBlobHash,
223
+ this.#getGlobalVariables(),
224
+ this.#getTotalFees(),
225
+ new Fr(this.#getTotalManaUsed()),
226
+ );
227
+
228
+ return this.builtBlockHeader;
169
229
  }
170
230
 
171
- public setEndBlobAccumulator(accumulator: BatchedBlobAccumulator) {
172
- this.endBlobAccumulator = accumulator;
231
+ public getBuiltBlockHeader() {
232
+ return this.builtBlockHeader;
173
233
  }
174
234
 
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;
179
- }
180
- const endBlobAccumulator = await accumulateBlobs(
181
- this.allTxs.map(t => t.processedTx),
182
- this.startBlobAccumulator,
183
- );
184
- this.setEndBlobAccumulator(endBlobAccumulator);
235
+ public getStartSpongeBlob() {
236
+ return this.startSpongeBlob;
185
237
  }
186
238
 
187
- // Returns the complete set of transaction proving state objects
188
- public get allTxs() {
189
- return this.txs;
239
+ public setEndSpongeBlob(endSpongeBlob: SpongeBlob) {
240
+ this.endSpongeBlob = endSpongeBlob;
190
241
  }
191
242
 
192
- /** Returns the block number as an epoch number. Used for prioritizing proof requests. */
193
- public get epochNumber(): number {
194
- return this.parentEpoch.epochNumber;
243
+ public getEndSpongeBlob() {
244
+ return this.endSpongeBlob;
245
+ }
246
+
247
+ public setEndState(endState: StateReference) {
248
+ this.endState = endState;
249
+ }
250
+
251
+ public hasEndState() {
252
+ return !!this.endState;
253
+ }
254
+
255
+ public getBlockEndBlobFields(): Fr[] {
256
+ return encodeBlockEndBlobData(this.getBlockEndBlobData());
257
+ }
258
+
259
+ getBlockEndBlobData(): BlockEndBlobData {
260
+ if (!this.endState) {
261
+ throw new Error('Call `setEndState` first.');
262
+ }
263
+
264
+ const partial = this.endState.partial;
265
+ return {
266
+ blockEndMarker: {
267
+ numTxs: this.totalNumTxs,
268
+ timestamp: this.timestamp,
269
+ blockNumber: this.blockNumber,
270
+ },
271
+ blockEndStateField: {
272
+ l1ToL2MessageNextAvailableLeafIndex: this.newL1ToL2MessageTreeSnapshot.nextAvailableLeafIndex,
273
+ noteHashNextAvailableLeafIndex: partial.noteHashTree.nextAvailableLeafIndex,
274
+ nullifierNextAvailableLeafIndex: partial.nullifierTree.nextAvailableLeafIndex,
275
+ publicDataNextAvailableLeafIndex: partial.publicDataTree.nextAvailableLeafIndex,
276
+ totalManaUsed: this.#getTotalManaUsed(),
277
+ },
278
+ lastArchiveRoot: this.lastArchiveTreeSnapshot.root,
279
+ noteHashRoot: partial.noteHashTree.root,
280
+ nullifierRoot: partial.nullifierTree.root,
281
+ publicDataRoot: partial.publicDataTree.root,
282
+ l1ToL2MessageRoot: this.isFirstBlock ? this.newL1ToL2MessageTreeSnapshot.root : undefined,
283
+ };
284
+ }
285
+
286
+ public getBlockBlobData(): BlockBlobData {
287
+ return {
288
+ ...this.getBlockEndBlobData(),
289
+ txs: this.getTxEffects().map(t => t.toTxBlobData()),
290
+ };
291
+ }
292
+
293
+ public getTxEffects() {
294
+ return this.txs.map(t => t.processedTx.txEffect);
195
295
  }
196
296
 
197
297
  public getParentLocation(location: TreeNodeLocation) {
198
- return this.baseOrMergeProvingOutputs.getParentLocation(location);
298
+ return this.baseOrMergeProofs.getParentLocation(location);
199
299
  }
200
300
 
201
301
  public getMergeRollupInputs(mergeLocation: TreeNodeLocation) {
202
- const [left, right] = this.baseOrMergeProvingOutputs.getChildren(mergeLocation);
302
+ const [left, right] = this.baseOrMergeProofs.getChildren(mergeLocation).map(c => c?.provingOutput);
203
303
  if (!left || !right) {
204
- throw new Error('At lease one child is not ready.');
304
+ throw new Error('At least one child is not ready for the merge rollup.');
205
305
  }
206
306
 
207
- return new MergeRollupInputs([this.#getPreviousRollupData(left), this.#getPreviousRollupData(right)]);
307
+ return new TxMergeRollupPrivateInputs([toProofData(left), toProofData(right)]);
208
308
  }
209
309
 
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.');
310
+ public getBlockRootRollupTypeAndInputs() {
311
+ const provingOutputs = this.#getChildProvingOutputsForBlockRoot();
312
+ if (!provingOutputs.every(p => !!p)) {
313
+ throw new Error('At least one child is not ready for the block root rollup.');
219
314
  }
220
315
 
221
- const data = this.#getBlockRootRollupData();
222
-
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
- });
316
+ const previousRollups = provingOutputs.map(p => toProofData(p));
231
317
 
232
- this.blobsHash = await getEmptyBlockBlobsHash();
318
+ if (this.isFirstBlock) {
319
+ return this.#getFirstBlockRootRollupTypeAndInputs(previousRollups);
320
+ }
233
321
 
322
+ const [leftRollup, rightRollup] = previousRollups;
323
+ if (!rightRollup) {
234
324
  return {
235
- rollupType: 'empty-block-root-rollup' satisfies CircuitName,
236
- inputs: EmptyBlockRootRollupInputs.from({
237
- data,
238
- constants,
239
- }),
325
+ rollupType: 'rollup-block-root-single-tx' satisfies CircuitName,
326
+ inputs: new BlockRootSingleTxRollupPrivateInputs(leftRollup, this.lastArchiveSiblingPath),
327
+ };
328
+ } else {
329
+ return {
330
+ rollupType: 'rollup-block-root' satisfies CircuitName,
331
+ inputs: new BlockRootRollupPrivateInputs([leftRollup, rightRollup], this.lastArchiveSiblingPath),
240
332
  };
241
333
  }
334
+ }
242
335
 
243
- const previousRollupData = await Promise.all(nonEmptyProofs.map(p => this.#getPreviousRollupData(p!)));
244
- const blobData = await this.#getBlockRootRollupBlobData();
245
- this.blobsHash = blobData.blobsHash;
336
+ #getFirstBlockRootRollupTypeAndInputs([leftRollup, rightRollup]: RollupHonkProofData<TxRollupPublicInputs>[]) {
337
+ if (!this.rootParityProof?.provingOutput) {
338
+ throw new Error('Root parity is not ready.');
339
+ }
340
+ const l1ToL2Roots = toProofData(this.rootParityProof.provingOutput);
246
341
 
247
- if (previousRollupData.length === 1) {
342
+ if (!leftRollup) {
248
343
  return {
249
- rollupType: 'single-tx-block-root-rollup' satisfies CircuitName,
250
- inputs: new SingleTxBlockRootRollupInputs(previousRollupData as [PreviousRollupData], data, blobData),
344
+ rollupType: 'rollup-block-root-first-empty-tx' satisfies CircuitName,
345
+ inputs: new BlockRootEmptyTxFirstRollupPrivateInputs(
346
+ l1ToL2Roots,
347
+ this.lastArchiveTreeSnapshot,
348
+ this.headerOfLastBlockInPreviousCheckpoint.state,
349
+ this.constants,
350
+ this.timestamp,
351
+ this.lastL1ToL2MessageSubtreeRootSiblingPath,
352
+ this.lastArchiveSiblingPath,
353
+ ),
354
+ };
355
+ } else if (!rightRollup) {
356
+ return {
357
+ rollupType: 'rollup-block-root-first-single-tx' satisfies CircuitName,
358
+ inputs: new BlockRootSingleTxFirstRollupPrivateInputs(
359
+ l1ToL2Roots,
360
+ leftRollup,
361
+ this.lastL1ToL2MessageTreeSnapshot,
362
+ this.lastL1ToL2MessageSubtreeRootSiblingPath,
363
+ this.lastArchiveSiblingPath,
364
+ ),
251
365
  };
252
366
  } else {
253
367
  return {
254
- rollupType: 'block-root-rollup' satisfies CircuitName,
255
- inputs: new BlockRootRollupInputs(
256
- previousRollupData as [PreviousRollupData, PreviousRollupData],
257
- data,
258
- blobData,
368
+ rollupType: 'rollup-block-root-first' satisfies CircuitName,
369
+ inputs: new BlockRootFirstRollupPrivateInputs(
370
+ l1ToL2Roots,
371
+ [leftRollup, rightRollup],
372
+ this.lastL1ToL2MessageTreeSnapshot,
373
+ this.lastL1ToL2MessageSubtreeRootSiblingPath,
374
+ this.lastArchiveSiblingPath,
259
375
  ),
260
376
  };
261
377
  }
262
378
  }
263
379
 
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)) {
380
+ public getParityRootInputs() {
381
+ const baseParityProvingOutputs = this.baseParityProofs.filter(p => !!p?.provingOutput).map(p => p!.provingOutput!);
382
+ if (baseParityProvingOutputs.length !== this.baseParityProofs.length) {
278
383
  throw new Error('At lease one base parity is not ready.');
279
384
  }
280
385
 
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
- );
386
+ const children = baseParityProvingOutputs.map(p => toProofData(p));
387
+ return new ParityRootPrivateInputs(assertLength(children, NUM_BASE_PARITY_PER_ROOT_PARITY));
285
388
  }
286
389
 
287
390
  // Returns a specific transaction proving state
@@ -290,89 +393,46 @@ export class BlockProvingState {
290
393
  }
291
394
 
292
395
  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;
396
+ if (!this.blockRootProof?.provingOutput) {
397
+ throw new Error('Block root rollup is not ready.');
306
398
  }
307
- const endState = new StateReference(this.l1ToL2MessageTreeSnapshotAfterInsertion, endPartialState);
308
-
309
- return buildHeaderFromCircuitOutputs(
310
- previousRollupData.map(d => d.baseOrMergeRollupPublicInputs),
311
- this.rootParityProvingOutput!.inputs,
312
- this.blockRootProvingOutput!.inputs,
313
- this.blobsHash!,
314
- endState,
315
- );
399
+
400
+ return await buildHeaderFromCircuitOutputs(this.blockRootProof.provingOutput.inputs);
316
401
  }
317
402
 
318
403
  public isReadyForMergeRollup(location: TreeNodeLocation) {
319
- return this.baseOrMergeProvingOutputs.getSibling(location) !== undefined;
404
+ return !!this.baseOrMergeProofs.getSibling(location)?.provingOutput;
320
405
  }
321
406
 
322
407
  // Returns true if we have sufficient inputs to execute the block root rollup
323
408
  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
- );
409
+ const childProofs = this.#getChildProvingOutputsForBlockRoot();
410
+ return (!this.isFirstBlock || !!this.rootParityProof?.provingOutput) && childProofs.every(p => !!p);
331
411
  }
332
412
 
333
413
  // Returns true if we have sufficient root parity inputs to execute the root parity circuit
334
414
  public isReadyForRootParity() {
335
- return this.baseParityProvingOutputs.every(p => !!p);
415
+ return this.baseParityProofs.every(p => !!p?.provingOutput);
336
416
  }
337
417
 
338
418
  public isComplete() {
339
- return !!this.blockRootProvingOutput;
419
+ return !!this.blockRootProof;
340
420
  }
341
421
 
342
- // Returns whether the proving state is still valid
343
422
  public verifyState() {
344
- return this.parentEpoch.verifyState();
423
+ return this.parentCheckpoint.verifyState();
345
424
  }
346
425
 
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
- });
426
+ public getError() {
427
+ return this.error;
363
428
  }
364
429
 
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
- });
430
+ public reject(reason: string) {
431
+ this.error = reason;
432
+ this.parentCheckpoint.reject(reason);
373
433
  }
374
434
 
375
- #getChildProofsForBlockRoot() {
435
+ #getChildProvingOutputsForBlockRoot() {
376
436
  if (this.totalNumTxs === 0) {
377
437
  return [];
378
438
  }
@@ -380,26 +440,34 @@ export class BlockProvingState {
380
440
  const rootLocation = { level: 0, index: 0 };
381
441
  // If there's only 1 tx, its base rollup proof will be stored at the root.
382
442
  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
- );
443
+ ? [this.baseOrMergeProofs.getNode(rootLocation)?.provingOutput]
444
+ : this.baseOrMergeProofs.getChildren(rootLocation).map(c => c?.provingOutput);
445
+ }
446
+
447
+ #getGlobalVariables() {
448
+ if (this.txs.length) {
449
+ return this.txs[0].processedTx.globalVariables;
450
+ }
451
+
452
+ const constants = this.constants;
453
+
454
+ return GlobalVariables.from({
455
+ chainId: constants.chainId,
456
+ version: constants.version,
457
+ blockNumber: this.blockNumber,
458
+ slotNumber: constants.slotNumber,
459
+ timestamp: this.timestamp,
460
+ coinbase: constants.coinbase,
461
+ feeRecipient: constants.feeRecipient,
462
+ gasFees: constants.gasFees,
463
+ });
464
+ }
465
+
466
+ #getTotalFees() {
467
+ return this.txs.reduce((acc, tx) => acc.add(tx.processedTx.txEffect.transactionFee), Fr.ZERO);
468
+ }
469
+
470
+ #getTotalManaUsed() {
471
+ return this.txs.reduce((acc, tx) => acc + BigInt(tx.processedTx.gasUsed.billedGas.l2Gas), 0n);
404
472
  }
405
473
  }