@aztec-labs/prover-client 6.0.0-nightly.20260829

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 (170) hide show
  1. package/README.md +1 -0
  2. package/dest/config.d.ts +17 -0
  3. package/dest/config.d.ts.map +1 -0
  4. package/dest/config.js +63 -0
  5. package/dest/index.d.ts +4 -0
  6. package/dest/index.d.ts.map +1 -0
  7. package/dest/index.js +2 -0
  8. package/dest/light/index.d.ts +2 -0
  9. package/dest/light/index.d.ts.map +1 -0
  10. package/dest/light/index.js +1 -0
  11. package/dest/light/lightweight_checkpoint_builder.d.ts +58 -0
  12. package/dest/light/lightweight_checkpoint_builder.d.ts.map +1 -0
  13. package/dest/light/lightweight_checkpoint_builder.js +243 -0
  14. package/dest/mocks/fixtures.d.ts +20 -0
  15. package/dest/mocks/fixtures.d.ts.map +1 -0
  16. package/dest/mocks/fixtures.js +96 -0
  17. package/dest/mocks/test_context.d.ts +93 -0
  18. package/dest/mocks/test_context.d.ts.map +1 -0
  19. package/dest/mocks/test_context.js +354 -0
  20. package/dest/orchestrator/block-building-helpers.d.ts +67 -0
  21. package/dest/orchestrator/block-building-helpers.d.ts.map +1 -0
  22. package/dest/orchestrator/block-building-helpers.js +274 -0
  23. package/dest/orchestrator/block-proving-state.d.ts +107 -0
  24. package/dest/orchestrator/block-proving-state.d.ts.map +1 -0
  25. package/dest/orchestrator/block-proving-state.js +339 -0
  26. package/dest/orchestrator/checkpoint-proving-state.d.ts +67 -0
  27. package/dest/orchestrator/checkpoint-proving-state.d.ts.map +1 -0
  28. package/dest/orchestrator/checkpoint-proving-state.js +175 -0
  29. package/dest/orchestrator/checkpoint-sub-tree-orchestrator.d.ts +169 -0
  30. package/dest/orchestrator/checkpoint-sub-tree-orchestrator.d.ts.map +1 -0
  31. package/dest/orchestrator/checkpoint-sub-tree-orchestrator.js +1047 -0
  32. package/dest/orchestrator/chonk-cache.d.ts +39 -0
  33. package/dest/orchestrator/chonk-cache.d.ts.map +1 -0
  34. package/dest/orchestrator/chonk-cache.js +80 -0
  35. package/dest/orchestrator/index.d.ts +4 -0
  36. package/dest/orchestrator/index.d.ts.map +1 -0
  37. package/dest/orchestrator/index.js +3 -0
  38. package/dest/orchestrator/orchestrator_metrics.d.ts +8 -0
  39. package/dest/orchestrator/orchestrator_metrics.d.ts.map +1 -0
  40. package/dest/orchestrator/orchestrator_metrics.js +13 -0
  41. package/dest/orchestrator/proving-scheduler.d.ts +81 -0
  42. package/dest/orchestrator/proving-scheduler.d.ts.map +1 -0
  43. package/dest/orchestrator/proving-scheduler.js +120 -0
  44. package/dest/orchestrator/top-tree-orchestrator.d.ts +89 -0
  45. package/dest/orchestrator/top-tree-orchestrator.d.ts.map +1 -0
  46. package/dest/orchestrator/top-tree-orchestrator.js +233 -0
  47. package/dest/orchestrator/top-tree-proving-state.d.ts +61 -0
  48. package/dest/orchestrator/top-tree-proving-state.d.ts.map +1 -0
  49. package/dest/orchestrator/top-tree-proving-state.js +185 -0
  50. package/dest/orchestrator/tx-proving-state.d.ts +37 -0
  51. package/dest/orchestrator/tx-proving-state.d.ts.map +1 -0
  52. package/dest/orchestrator/tx-proving-state.js +77 -0
  53. package/dest/prover-client/factory.d.ts +6 -0
  54. package/dest/prover-client/factory.d.ts.map +1 -0
  55. package/dest/prover-client/factory.js +5 -0
  56. package/dest/prover-client/index.d.ts +3 -0
  57. package/dest/prover-client/index.d.ts.map +1 -0
  58. package/dest/prover-client/index.js +2 -0
  59. package/dest/prover-client/prover-client.d.ts +99 -0
  60. package/dest/prover-client/prover-client.d.ts.map +1 -0
  61. package/dest/prover-client/prover-client.js +163 -0
  62. package/dest/proving_broker/broker_prover_facade.d.ts +52 -0
  63. package/dest/proving_broker/broker_prover_facade.d.ts.map +1 -0
  64. package/dest/proving_broker/broker_prover_facade.js +360 -0
  65. package/dest/proving_broker/config.d.ts +40 -0
  66. package/dest/proving_broker/config.d.ts.map +1 -0
  67. package/dest/proving_broker/config.js +138 -0
  68. package/dest/proving_broker/factory.d.ts +5 -0
  69. package/dest/proving_broker/factory.d.ts.map +1 -0
  70. package/dest/proving_broker/factory.js +13 -0
  71. package/dest/proving_broker/fixtures.d.ts +6 -0
  72. package/dest/proving_broker/fixtures.d.ts.map +1 -0
  73. package/dest/proving_broker/fixtures.js +13 -0
  74. package/dest/proving_broker/index.d.ts +11 -0
  75. package/dest/proving_broker/index.d.ts.map +1 -0
  76. package/dest/proving_broker/index.js +10 -0
  77. package/dest/proving_broker/proof_store/factory.d.ts +3 -0
  78. package/dest/proving_broker/proof_store/factory.d.ts.map +1 -0
  79. package/dest/proving_broker/proof_store/factory.js +13 -0
  80. package/dest/proving_broker/proof_store/file_store_proof_store.d.ts +18 -0
  81. package/dest/proving_broker/proof_store/file_store_proof_store.d.ts.map +1 -0
  82. package/dest/proving_broker/proof_store/file_store_proof_store.js +60 -0
  83. package/dest/proving_broker/proof_store/index.d.ts +5 -0
  84. package/dest/proving_broker/proof_store/index.d.ts.map +1 -0
  85. package/dest/proving_broker/proof_store/index.js +4 -0
  86. package/dest/proving_broker/proof_store/inline_proof_store.d.ts +15 -0
  87. package/dest/proving_broker/proof_store/inline_proof_store.d.ts.map +1 -0
  88. package/dest/proving_broker/proof_store/inline_proof_store.js +41 -0
  89. package/dest/proving_broker/proof_store/proof_store.d.ts +36 -0
  90. package/dest/proving_broker/proof_store/proof_store.d.ts.map +1 -0
  91. package/dest/proving_broker/proof_store/proof_store.js +3 -0
  92. package/dest/proving_broker/proving_agent.d.ts +42 -0
  93. package/dest/proving_broker/proving_agent.d.ts.map +1 -0
  94. package/dest/proving_broker/proving_agent.js +155 -0
  95. package/dest/proving_broker/proving_broker.d.ts +77 -0
  96. package/dest/proving_broker/proving_broker.d.ts.map +1 -0
  97. package/dest/proving_broker/proving_broker.js +780 -0
  98. package/dest/proving_broker/proving_broker_database/memory.d.ts +20 -0
  99. package/dest/proving_broker/proving_broker_database/memory.d.ts.map +1 -0
  100. package/dest/proving_broker/proving_broker_database/memory.js +67 -0
  101. package/dest/proving_broker/proving_broker_database/persisted.d.ts +40 -0
  102. package/dest/proving_broker/proving_broker_database/persisted.d.ts.map +1 -0
  103. package/dest/proving_broker/proving_broker_database/persisted.js +623 -0
  104. package/dest/proving_broker/proving_broker_database.d.ts +66 -0
  105. package/dest/proving_broker/proving_broker_database.d.ts.map +1 -0
  106. package/dest/proving_broker/proving_broker_database.js +3 -0
  107. package/dest/proving_broker/proving_broker_instrumentation.d.ts +31 -0
  108. package/dest/proving_broker/proving_broker_instrumentation.d.ts.map +1 -0
  109. package/dest/proving_broker/proving_broker_instrumentation.js +97 -0
  110. package/dest/proving_broker/proving_job_controller.d.ts +34 -0
  111. package/dest/proving_broker/proving_job_controller.d.ts.map +1 -0
  112. package/dest/proving_broker/proving_job_controller.js +184 -0
  113. package/dest/proving_broker/rpc.d.ts +38 -0
  114. package/dest/proving_broker/rpc.d.ts.map +1 -0
  115. package/dest/proving_broker/rpc.js +138 -0
  116. package/dest/test/epoch_settlement.d.ts +36 -0
  117. package/dest/test/epoch_settlement.d.ts.map +1 -0
  118. package/dest/test/epoch_settlement.js +52 -0
  119. package/dest/test/index.d.ts +2 -0
  120. package/dest/test/index.d.ts.map +1 -0
  121. package/dest/test/index.js +1 -0
  122. package/dest/test/mock_proof_store.d.ts +9 -0
  123. package/dest/test/mock_proof_store.d.ts.map +1 -0
  124. package/dest/test/mock_proof_store.js +10 -0
  125. package/dest/test/mock_prover.d.ts +38 -0
  126. package/dest/test/mock_prover.d.ts.map +1 -0
  127. package/dest/test/mock_prover.js +91 -0
  128. package/package.json +113 -0
  129. package/src/config.ts +87 -0
  130. package/src/index.ts +4 -0
  131. package/src/light/index.ts +1 -0
  132. package/src/light/lightweight_checkpoint_builder.ts +342 -0
  133. package/src/mocks/fixtures.ts +120 -0
  134. package/src/mocks/test_context.ts +477 -0
  135. package/src/orchestrator/block-building-helpers.ts +486 -0
  136. package/src/orchestrator/block-proving-state.ts +457 -0
  137. package/src/orchestrator/checkpoint-proving-state.ts +247 -0
  138. package/src/orchestrator/checkpoint-sub-tree-orchestrator.ts +1010 -0
  139. package/src/orchestrator/chonk-cache.ts +99 -0
  140. package/src/orchestrator/index.ts +12 -0
  141. package/src/orchestrator/orchestrator_metrics.ts +18 -0
  142. package/src/orchestrator/proving-scheduler.ts +160 -0
  143. package/src/orchestrator/top-tree-orchestrator.ts +394 -0
  144. package/src/orchestrator/top-tree-proving-state.ts +219 -0
  145. package/src/orchestrator/tx-proving-state.ts +121 -0
  146. package/src/prover-client/factory.ts +18 -0
  147. package/src/prover-client/index.ts +2 -0
  148. package/src/prover-client/prover-client.ts +286 -0
  149. package/src/proving_broker/broker_prover_facade.ts +626 -0
  150. package/src/proving_broker/config.ts +178 -0
  151. package/src/proving_broker/factory.ts +19 -0
  152. package/src/proving_broker/fixtures.ts +20 -0
  153. package/src/proving_broker/index.ts +10 -0
  154. package/src/proving_broker/proof_store/factory.ts +20 -0
  155. package/src/proving_broker/proof_store/file_store_proof_store.ts +78 -0
  156. package/src/proving_broker/proof_store/index.ts +4 -0
  157. package/src/proving_broker/proof_store/inline_proof_store.ts +63 -0
  158. package/src/proving_broker/proof_store/proof_store.ts +54 -0
  159. package/src/proving_broker/proving_agent.ts +210 -0
  160. package/src/proving_broker/proving_broker.ts +888 -0
  161. package/src/proving_broker/proving_broker_database/memory.ts +78 -0
  162. package/src/proving_broker/proving_broker_database/persisted.ts +296 -0
  163. package/src/proving_broker/proving_broker_database.ts +75 -0
  164. package/src/proving_broker/proving_broker_instrumentation.ts +133 -0
  165. package/src/proving_broker/proving_job_controller.ts +199 -0
  166. package/src/proving_broker/rpc.ts +131 -0
  167. package/src/test/epoch_settlement.ts +82 -0
  168. package/src/test/index.ts +1 -0
  169. package/src/test/mock_proof_store.ts +14 -0
  170. package/src/test/mock_prover.ts +304 -0
@@ -0,0 +1,486 @@
1
+ import {
2
+ BatchedBlobAccumulator,
3
+ SpongeBlob,
4
+ computeBlobsHashFromBlobs,
5
+ encodeBlockBlobData,
6
+ getBlobCommitmentsFromBlobs,
7
+ getBlobsPerL1Block,
8
+ } from '@aztec-labs/blob-lib';
9
+ import {
10
+ ARCHIVE_HEIGHT,
11
+ CHONK_PROOF_LENGTH,
12
+ MAX_CONTRACT_CLASS_LOGS_PER_TX,
13
+ MAX_NOTE_HASHES_PER_TX,
14
+ MAX_NULLIFIERS_PER_TX,
15
+ NOTE_HASH_SUBTREE_HEIGHT,
16
+ NOTE_HASH_SUBTREE_ROOT_SIBLING_PATH_LENGTH,
17
+ NULLIFIER_SUBTREE_HEIGHT,
18
+ NULLIFIER_SUBTREE_ROOT_SIBLING_PATH_LENGTH,
19
+ NULLIFIER_TREE_HEIGHT,
20
+ PUBLIC_DATA_TREE_HEIGHT,
21
+ } from '@aztec-labs/constants';
22
+ import { makeTuple } from '@aztec-labs/foundation/array';
23
+ import { BlockNumber } from '@aztec-labs/foundation/branded-types';
24
+ import { padArrayEnd } from '@aztec-labs/foundation/collection';
25
+ import { Fr } from '@aztec-labs/foundation/curves/bn254';
26
+ import { type Bufferable, assertLength, toFriendlyJSON } from '@aztec-labs/foundation/serialize';
27
+ import { MembershipWitness } from '@aztec-labs/foundation/trees';
28
+ import { getVkData } from '@aztec-labs/noir-protocol-circuits-types/server/vks';
29
+ import { getVKIndex, getVKSiblingPath } from '@aztec-labs/noir-protocol-circuits-types/vk-tree';
30
+ import { computeFeePayerBalanceLeafSlot } from '@aztec-labs/protocol-contracts/fee-juice';
31
+ import { Body } from '@aztec-labs/stdlib/block';
32
+ import type { MerkleTreeWriteOperations, PublicInputsAndRecursiveProof } from '@aztec-labs/stdlib/interfaces/server';
33
+ import { ContractClassLogFields } from '@aztec-labs/stdlib/logs';
34
+ import { Proof, ProofData, RecursiveProof } from '@aztec-labs/stdlib/proofs';
35
+ import {
36
+ BlockConstantData,
37
+ BlockRollupPublicInputs,
38
+ PrivateBaseRollupHints,
39
+ PublicBaseRollupHints,
40
+ PublicChonkVerifierPrivateInputs,
41
+ TreeSnapshotDiffHints,
42
+ } from '@aztec-labs/stdlib/rollup';
43
+ import {
44
+ AppendOnlyTreeSnapshot,
45
+ MerkleTreeId,
46
+ NullifierLeafPreimage,
47
+ PublicDataTreeLeafPreimage,
48
+ getTreeHeight,
49
+ } from '@aztec-labs/stdlib/trees';
50
+ import {
51
+ BlockHeader,
52
+ GlobalVariables,
53
+ PartialStateReference,
54
+ type ProcessedTx,
55
+ StateReference,
56
+ Tx,
57
+ } from '@aztec-labs/stdlib/tx';
58
+ import { VkData } from '@aztec-labs/stdlib/vks';
59
+ import { Attributes, type Span, runInSpan } from '@aztec-labs/telemetry-client';
60
+ import type { MerkleTreeReadOperations } from '@aztec-labs/world-state';
61
+
62
+ /**
63
+ * Type representing the names of the trees for the base rollup.
64
+ */
65
+ type BaseTreeNames = 'NoteHashTree' | 'ContractTree' | 'NullifierTree' | 'PublicDataTree';
66
+ /**
67
+ * Type representing the names of the trees.
68
+ */
69
+ export type TreeNames = BaseTreeNames | 'L1ToL2MessageTree' | 'Archive';
70
+
71
+ // Builds the hints for base rollup. Updating the contract, nullifier, and data trees in the process.
72
+ export const insertSideEffectsAndBuildBaseRollupHints = runInSpan(
73
+ 'BlockBuilderHelpers',
74
+ 'buildBaseRollupHints',
75
+ async (
76
+ span: Span,
77
+ tx: ProcessedTx,
78
+ lastArchive: AppendOnlyTreeSnapshot,
79
+ newL1ToL2MessageTreeSnapshot: AppendOnlyTreeSnapshot,
80
+ startSpongeBlob: SpongeBlob,
81
+ proverId: Fr,
82
+ db: MerkleTreeWriteOperations,
83
+ ) => {
84
+ span.setAttribute(Attributes.TX_HASH, tx.hash.toString());
85
+ // Get trees info before any changes hit
86
+ const start = new PartialStateReference(
87
+ await getTreeSnapshot(MerkleTreeId.NOTE_HASH_TREE, db),
88
+ await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE, db),
89
+ await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE, db),
90
+ );
91
+
92
+ // Get the note hash subtree root sibling path for insertion.
93
+ const noteHashSubtreeRootSiblingPath = assertLength(
94
+ await getSubtreeSiblingPath(MerkleTreeId.NOTE_HASH_TREE, NOTE_HASH_SUBTREE_HEIGHT, db),
95
+ NOTE_HASH_SUBTREE_ROOT_SIBLING_PATH_LENGTH,
96
+ );
97
+
98
+ const { nullifierInsertionResult, publicDataInsertionResult } = await insertSideEffects(tx, db);
99
+
100
+ const blockHash = await tx.data.constants.anchorBlockHeader.hash();
101
+ const anchorBlockArchiveSiblingPath = (
102
+ await getMembershipWitnessFor(blockHash.toFr(), MerkleTreeId.ARCHIVE, ARCHIVE_HEIGHT, db)
103
+ ).siblingPath;
104
+
105
+ const contractClassLogsFields = makeTuple(
106
+ MAX_CONTRACT_CLASS_LOGS_PER_TX,
107
+ i => tx.txEffect.contractClassLogs[i]?.fields || ContractClassLogFields.empty(),
108
+ );
109
+
110
+ if (tx.avmProvingRequest) {
111
+ return PublicBaseRollupHints.from({
112
+ startSpongeBlob,
113
+ lastArchive,
114
+ anchorBlockArchiveSiblingPath,
115
+ contractClassLogsFields,
116
+ });
117
+ } else {
118
+ if (tx.txEffect.publicDataWrites.length > 1) {
119
+ throw new Error(`More than one public data write in a private only tx`);
120
+ }
121
+
122
+ // Get hints for reading fee payer's balance in the public data tree.
123
+ const feePayerBalanceLeafWitnessData = publicDataInsertionResult.lowLeavesWitnessData[0];
124
+ const feePayerBalanceMembershipWitness = MembershipWitness.fromBufferArray<typeof PUBLIC_DATA_TREE_HEIGHT>(
125
+ feePayerBalanceLeafWitnessData.index,
126
+ assertLength(feePayerBalanceLeafWitnessData.siblingPath.toBufferArray(), PUBLIC_DATA_TREE_HEIGHT),
127
+ );
128
+ const feePayerBalanceLeafPreimage = feePayerBalanceLeafWitnessData.leafPreimage as PublicDataTreeLeafPreimage;
129
+ const leafSlot = await computeFeePayerBalanceLeafSlot(tx.data.feePayer);
130
+ if (!leafSlot.equals(feePayerBalanceLeafPreimage.leaf.slot)) {
131
+ throw new Error(`Cannot find the public data tree leaf for the fee payer's balance`);
132
+ }
133
+
134
+ // Get hints for inserting the nullifiers.
135
+ const nullifierLowLeavesWitnessData = nullifierInsertionResult.lowLeavesWitnessData!;
136
+ const nullifierPredecessorPreimages = padArrayEnd(
137
+ nullifierLowLeavesWitnessData.map(l => l.leafPreimage as NullifierLeafPreimage),
138
+ NullifierLeafPreimage.empty(),
139
+ MAX_NULLIFIERS_PER_TX,
140
+ );
141
+ const nullifierPredecessorMembershipWitnesses = padArrayEnd(
142
+ nullifierLowLeavesWitnessData.map(l =>
143
+ MembershipWitness.fromBufferArray<typeof NULLIFIER_TREE_HEIGHT>(
144
+ l.index,
145
+ assertLength(l.siblingPath.toBufferArray(), NULLIFIER_TREE_HEIGHT),
146
+ ),
147
+ ),
148
+ makeEmptyMembershipWitness(NULLIFIER_TREE_HEIGHT),
149
+ MAX_NULLIFIERS_PER_TX,
150
+ );
151
+ const sortedNullifiers = assertLength(
152
+ nullifierInsertionResult.sortedNewLeaves.map(n => Fr.fromBuffer(n)),
153
+ MAX_NULLIFIERS_PER_TX,
154
+ );
155
+ const sortedNullifierIndexes = assertLength(
156
+ nullifierInsertionResult.sortedNewLeavesIndexes,
157
+ MAX_NULLIFIERS_PER_TX,
158
+ );
159
+ const nullifierSubtreeRootSiblingPath = assertLength(
160
+ nullifierInsertionResult.newSubtreeSiblingPath.toFields(),
161
+ NULLIFIER_SUBTREE_ROOT_SIBLING_PATH_LENGTH,
162
+ );
163
+
164
+ const treeSnapshotDiffHints = TreeSnapshotDiffHints.from({
165
+ noteHashSubtreeRootSiblingPath,
166
+ nullifierPredecessorPreimages,
167
+ nullifierPredecessorMembershipWitnesses,
168
+ sortedNullifiers,
169
+ sortedNullifierIndexes,
170
+ nullifierSubtreeRootSiblingPath,
171
+ feePayerBalanceMembershipWitness,
172
+ });
173
+
174
+ const constants = BlockConstantData.from({
175
+ lastArchive,
176
+ l1ToL2TreeSnapshot: newL1ToL2MessageTreeSnapshot,
177
+ vkTreeRoot: tx.data.constants.vkTreeRoot,
178
+ protocolContractsHash: tx.data.constants.protocolContractsHash,
179
+ globalVariables: tx.globalVariables,
180
+ proverId,
181
+ });
182
+
183
+ return PrivateBaseRollupHints.from({
184
+ start,
185
+ startSpongeBlob,
186
+ treeSnapshotDiffHints,
187
+ feePayerBalanceLeafPreimage,
188
+ anchorBlockArchiveSiblingPath,
189
+ contractClassLogsFields,
190
+ constants,
191
+ });
192
+ }
193
+ },
194
+ );
195
+
196
+ export const insertSideEffects = runInSpan(
197
+ 'BlockBuilderHelpers',
198
+ 'buildBaseRollupHints',
199
+ async (span: Span, tx: ProcessedTx, db: MerkleTreeWriteOperations) => {
200
+ span.setAttribute(Attributes.TX_HASH, tx.hash.toString());
201
+
202
+ // Insert the note hashes. Padded with zeros to the max number of note hashes per tx.
203
+ const noteHashes = padArrayEnd(tx.txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX);
204
+ await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, noteHashes);
205
+
206
+ // Insert the nullifiers. Padded with zeros to the max number of nullifiers per tx.
207
+ // Capturing the low nullifier info for each individual operation.
208
+ const nullifierInsertionResult = await db.batchInsert(
209
+ MerkleTreeId.NULLIFIER_TREE,
210
+ padArrayEnd(tx.txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX).map(n => n.toBuffer()),
211
+ NULLIFIER_SUBTREE_HEIGHT,
212
+ );
213
+ if (nullifierInsertionResult.lowLeavesWitnessData === undefined) {
214
+ throw new Error(`Failed to batch insert nullifiers.`);
215
+ }
216
+
217
+ if (tx.txEffect.publicDataWrites.some(write => write.isEmpty())) {
218
+ throw new Error(`Empty public data write in tx: ${toFriendlyJSON(tx)}.`);
219
+ }
220
+ // Insert the public data writes sequentially. No need to pad them to the max array size.
221
+ // Capturing the low leaf info for each individual operation.
222
+ const publicDataInsertionResult = await db.sequentialInsert(
223
+ MerkleTreeId.PUBLIC_DATA_TREE,
224
+ tx.txEffect.publicDataWrites.map(write => write.toBuffer()),
225
+ );
226
+
227
+ return {
228
+ nullifierInsertionResult,
229
+ publicDataInsertionResult,
230
+ };
231
+ },
232
+ );
233
+
234
+ export function getChonkProofFromTx(tx: Tx | ProcessedTx) {
235
+ const publicInputs = tx.data.publicInputs().toFields();
236
+
237
+ const binaryProof = new Proof(
238
+ Buffer.concat(tx.chonkProof.attachPublicInputs(publicInputs).fieldsWithPublicInputs.map(field => field.toBuffer())),
239
+ publicInputs.length,
240
+ );
241
+ return new RecursiveProof(tx.chonkProof.fields, binaryProof, true, CHONK_PROOF_LENGTH);
242
+ }
243
+
244
+ export function getPublicChonkVerifierPrivateInputsFromTx(tx: Tx | ProcessedTx, proverId: Fr) {
245
+ const proofData = new ProofData(
246
+ tx.data.toPrivateToPublicKernelCircuitPublicInputs(),
247
+ getChonkProofFromTx(tx),
248
+ getVkData('HidingKernelToPublic'),
249
+ );
250
+ return new PublicChonkVerifierPrivateInputs(proofData, proverId);
251
+ }
252
+
253
+ // Build "hints" as the private inputs for the checkpoint root rollup circuit.
254
+ // The `blobCommitments` will be accumulated and checked in the root rollup against the `finalBlobChallenges`.
255
+ // The `blobsHash` will be validated on L1 against the submitted blob data.
256
+ export const buildBlobHints = async (blobFields: Fr[]) => {
257
+ const blobs = await getBlobsPerL1Block(blobFields);
258
+ const blobCommitments = getBlobCommitmentsFromBlobs(blobs);
259
+ const blobsHash = computeBlobsHashFromBlobs(blobs);
260
+ return { blobCommitments, blobs, blobsHash };
261
+ };
262
+
263
+ export const buildFinalBlobChallenges = async (blobFieldsPerCheckpoint: Fr[][]) => {
264
+ return await BatchedBlobAccumulator.precomputeBatchedBlobChallenges(blobFieldsPerCheckpoint);
265
+ };
266
+
267
+ export const accumulateBlobs = runInSpan(
268
+ 'BlockBuilderHelpers',
269
+ 'accumulateBlobs',
270
+ async (_span: Span, blobFields: Fr[], startBlobAccumulator: BatchedBlobAccumulator) => {
271
+ const endBlobAccumulator = await startBlobAccumulator.accumulateFields(blobFields);
272
+ return endBlobAccumulator;
273
+ },
274
+ );
275
+
276
+ export const buildHeaderFromCircuitOutputs = runInSpan(
277
+ 'BlockBuilderHelpers',
278
+ 'buildHeaderFromCircuitOutputs',
279
+ async (_span, blockRootRollupOutput: BlockRollupPublicInputs) => {
280
+ const constants = blockRootRollupOutput.constants;
281
+ const globalVariables = GlobalVariables.from({
282
+ chainId: constants.chainId,
283
+ version: constants.version,
284
+ blockNumber: BlockNumber(blockRootRollupOutput.previousArchive.nextAvailableLeafIndex),
285
+ timestamp: blockRootRollupOutput.timestamp,
286
+ slotNumber: constants.slotNumber,
287
+ coinbase: constants.coinbase,
288
+ feeRecipient: constants.feeRecipient,
289
+ gasFees: constants.gasFees,
290
+ });
291
+
292
+ const spongeBlobHash = await blockRootRollupOutput.endSpongeBlob.clone().squeeze();
293
+
294
+ return new BlockHeader(
295
+ blockRootRollupOutput.previousArchive,
296
+ blockRootRollupOutput.endState,
297
+ spongeBlobHash,
298
+ globalVariables,
299
+ blockRootRollupOutput.accumulatedFees,
300
+ blockRootRollupOutput.accumulatedManaUsed,
301
+ );
302
+ },
303
+ );
304
+
305
+ export const buildHeaderAndBodyFromTxs = runInSpan(
306
+ 'BlockBuilderHelpers',
307
+ 'buildHeaderAndBodyFromTxs',
308
+ async (
309
+ span,
310
+ txs: ProcessedTx[],
311
+ lastArchive: AppendOnlyTreeSnapshot,
312
+ endState: StateReference,
313
+ globalVariables: GlobalVariables,
314
+ startSpongeBlob: SpongeBlob,
315
+ ) => {
316
+ span.setAttribute(Attributes.BLOCK_NUMBER, globalVariables.blockNumber);
317
+
318
+ const txEffects = txs.map(tx => tx.txEffect);
319
+ const body = new Body(txEffects);
320
+
321
+ const totalFees = txEffects.reduce((acc, tx) => acc.add(tx.transactionFee), Fr.ZERO);
322
+ const totalManaUsed = txs.reduce((acc, tx) => acc.add(new Fr(tx.gasUsed.billedGas.l2Gas)), Fr.ZERO);
323
+
324
+ const { l1ToL2MessageTree, partial } = endState;
325
+
326
+ const blockBlobFields = encodeBlockBlobData({
327
+ blockEndMarker: {
328
+ timestamp: globalVariables.timestamp,
329
+ blockNumber: globalVariables.blockNumber,
330
+ numTxs: txs.length,
331
+ },
332
+ blockEndStateField: {
333
+ l1ToL2MessageNextAvailableLeafIndex: l1ToL2MessageTree.nextAvailableLeafIndex,
334
+ noteHashNextAvailableLeafIndex: partial.noteHashTree.nextAvailableLeafIndex,
335
+ nullifierNextAvailableLeafIndex: partial.nullifierTree.nextAvailableLeafIndex,
336
+ publicDataNextAvailableLeafIndex: partial.publicDataTree.nextAvailableLeafIndex,
337
+ totalManaUsed: totalManaUsed.toBigInt(),
338
+ },
339
+ lastArchiveRoot: lastArchive.root,
340
+ noteHashRoot: partial.noteHashTree.root,
341
+ nullifierRoot: partial.nullifierTree.root,
342
+ publicDataRoot: partial.publicDataTree.root,
343
+ // Every block carries its own post-bundle l1-to-l2 message tree root.
344
+ l1ToL2MessageRoot: l1ToL2MessageTree.root,
345
+ txs: body.toTxBlobData(),
346
+ });
347
+
348
+ const endSpongeBlob = startSpongeBlob.clone();
349
+ await endSpongeBlob.absorb(blockBlobFields);
350
+ const spongeBlobHash = await endSpongeBlob.squeeze();
351
+
352
+ const header = BlockHeader.from({
353
+ lastArchive,
354
+ state: endState,
355
+ spongeBlobHash,
356
+ globalVariables,
357
+ totalFees,
358
+ totalManaUsed,
359
+ });
360
+
361
+ return { header, body, blockBlobFields };
362
+ },
363
+ );
364
+
365
+ export async function getLastSiblingPath<TID extends MerkleTreeId>(treeId: TID, db: MerkleTreeReadOperations) {
366
+ const { size } = await db.getTreeInfo(treeId);
367
+ const path = await db.getSiblingPath(treeId, size - 1n);
368
+ return padArrayEnd(path.toFields(), Fr.ZERO, getTreeHeight(treeId));
369
+ }
370
+
371
+ export async function getRootTreeSiblingPath<TID extends MerkleTreeId>(treeId: TID, db: MerkleTreeReadOperations) {
372
+ const { size } = await db.getTreeInfo(treeId);
373
+ const path = await db.getSiblingPath(treeId, size);
374
+ return padArrayEnd(path.toFields(), Fr.ZERO, getTreeHeight(treeId));
375
+ }
376
+
377
+ export async function getTreeSnapshot(id: MerkleTreeId, db: MerkleTreeReadOperations): Promise<AppendOnlyTreeSnapshot> {
378
+ const treeInfo = await db.getTreeInfo(id);
379
+ return new AppendOnlyTreeSnapshot(Fr.fromBuffer(treeInfo.root), Number(treeInfo.size));
380
+ }
381
+
382
+ export function makeEmptyMembershipWitness<N extends number>(height: N) {
383
+ return new MembershipWitness(
384
+ height,
385
+ 0n,
386
+ makeTuple(height, () => Fr.ZERO),
387
+ );
388
+ }
389
+
390
+ export async function getSubtreeSiblingPath(
391
+ treeId: MerkleTreeId,
392
+ subtreeHeight: number,
393
+ db: MerkleTreeReadOperations,
394
+ ): Promise<Fr[]> {
395
+ const nextAvailableLeafIndex = await db.getTreeInfo(treeId).then(t => t.size);
396
+ const fullSiblingPath = await db.getSiblingPath(treeId, nextAvailableLeafIndex);
397
+
398
+ // Drop the first subtreeHeight items since we only care about the path to the subtree root
399
+ return fullSiblingPath.getSubtreeSiblingPath(subtreeHeight).toFields();
400
+ }
401
+
402
+ /**
403
+ * Returns the full-height frontier (left-sibling path) at a tree's next-available leaf index — the hint the append
404
+ * circuits re-hash against the snapshot root when appending leaves at a compact (unaligned) index.
405
+ */
406
+ export async function getFrontierSiblingPath(treeId: MerkleTreeId, db: MerkleTreeReadOperations): Promise<Fr[]> {
407
+ const nextAvailableLeafIndex = await db.getTreeInfo(treeId).then(t => t.size);
408
+ return (await db.getSiblingPath(treeId, nextAvailableLeafIndex)).toFields();
409
+ }
410
+
411
+ // Scan a tree searching for a specific value and return a membership witness proof for it
412
+ export async function getMembershipWitnessFor<N extends number>(
413
+ value: Fr,
414
+ treeId: MerkleTreeId,
415
+ height: N,
416
+ db: MerkleTreeReadOperations,
417
+ ): Promise<MembershipWitness<N>> {
418
+ // If this is an empty tx, then just return zeroes
419
+ if (value.isZero()) {
420
+ return makeEmptyMembershipWitness(height);
421
+ }
422
+
423
+ const index = (await db.findLeafIndices(treeId, [value.toBuffer()]))[0];
424
+ if (index === undefined) {
425
+ throw new Error(`Leaf with value ${value} not found in tree ${MerkleTreeId[treeId]}`);
426
+ }
427
+ const path = await db.getSiblingPath(treeId, index);
428
+ return new MembershipWitness(height, index, assertLength(path.toFields(), height));
429
+ }
430
+
431
+ export function validatePartialState(
432
+ partialState: PartialStateReference,
433
+ treeSnapshots: Map<MerkleTreeId, AppendOnlyTreeSnapshot>,
434
+ ) {
435
+ validateSimulatedTree(treeSnapshots.get(MerkleTreeId.NOTE_HASH_TREE)!, partialState.noteHashTree, 'NoteHashTree');
436
+ validateSimulatedTree(treeSnapshots.get(MerkleTreeId.NULLIFIER_TREE)!, partialState.nullifierTree, 'NullifierTree');
437
+ validateSimulatedTree(
438
+ treeSnapshots.get(MerkleTreeId.PUBLIC_DATA_TREE)!,
439
+ partialState.publicDataTree,
440
+ 'PublicDataTree',
441
+ );
442
+ }
443
+
444
+ // Helper for comparing two trees snapshots
445
+ function validateSimulatedTree(
446
+ localTree: AppendOnlyTreeSnapshot,
447
+ simulatedTree: AppendOnlyTreeSnapshot,
448
+ name: TreeNames,
449
+ label?: string,
450
+ ) {
451
+ if (!simulatedTree.root.toBuffer().equals(localTree.root.toBuffer())) {
452
+ throw new Error(`${label ?? name} tree root mismatch (local ${localTree.root}, simulated ${simulatedTree.root})`);
453
+ }
454
+ if (simulatedTree.nextAvailableLeafIndex !== localTree.nextAvailableLeafIndex) {
455
+ throw new Error(
456
+ `${label ?? name} tree next available leaf index mismatch (local ${localTree.nextAvailableLeafIndex}, simulated ${
457
+ simulatedTree.nextAvailableLeafIndex
458
+ })`,
459
+ );
460
+ }
461
+ }
462
+
463
+ export function validateTx(tx: ProcessedTx) {
464
+ const txHeader = tx.data.constants.anchorBlockHeader;
465
+ if (txHeader.state.l1ToL2MessageTree.isEmpty()) {
466
+ throw new Error(`Empty L1 to L2 messages tree in tx: ${toFriendlyJSON(tx)}`);
467
+ }
468
+ if (txHeader.state.partial.noteHashTree.isEmpty()) {
469
+ throw new Error(`Empty note hash tree in tx: ${toFriendlyJSON(tx)}`);
470
+ }
471
+ if (txHeader.state.partial.nullifierTree.isEmpty()) {
472
+ throw new Error(`Empty nullifier tree in tx: ${toFriendlyJSON(tx)}`);
473
+ }
474
+ if (txHeader.state.partial.publicDataTree.isEmpty()) {
475
+ throw new Error(`Empty public data tree in tx: ${toFriendlyJSON(tx)}`);
476
+ }
477
+ }
478
+
479
+ export function toProofData<T extends Bufferable, PROOF_LENGTH extends number>(
480
+ { inputs, proof, verificationKey }: PublicInputsAndRecursiveProof<T, PROOF_LENGTH>,
481
+ vkIndex?: number,
482
+ ) {
483
+ const leafIndex = vkIndex || getVKIndex(verificationKey.keyAsFields);
484
+ const vkData = new VkData(verificationKey, leafIndex, getVKSiblingPath(leafIndex));
485
+ return new ProofData(inputs, proof, vkData);
486
+ }