@aztec/prover-client 0.70.0 → 0.71.0

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 (84) hide show
  1. package/dest/bin/get-proof-inputs.d.ts +2 -0
  2. package/dest/bin/get-proof-inputs.d.ts.map +1 -0
  3. package/dest/bin/get-proof-inputs.js +50 -0
  4. package/dest/block_builder/light.d.ts +3 -4
  5. package/dest/block_builder/light.d.ts.map +1 -1
  6. package/dest/block_builder/light.js +8 -11
  7. package/dest/mocks/test_context.d.ts.map +1 -1
  8. package/dest/mocks/test_context.js +9 -10
  9. package/dest/orchestrator/block-building-helpers.d.ts +8 -7
  10. package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
  11. package/dest/orchestrator/block-building-helpers.js +20 -16
  12. package/dest/orchestrator/orchestrator.d.ts +1 -1
  13. package/dest/orchestrator/orchestrator.d.ts.map +1 -1
  14. package/dest/orchestrator/orchestrator.js +5 -11
  15. package/dest/prover-agent/memory-proving-queue.d.ts +1 -1
  16. package/dest/prover-agent/memory-proving-queue.d.ts.map +1 -1
  17. package/dest/prover-agent/memory-proving-queue.js +2 -2
  18. package/dest/prover-agent/prover-agent.d.ts +0 -2
  19. package/dest/prover-agent/prover-agent.d.ts.map +1 -1
  20. package/dest/prover-agent/prover-agent.js +4 -6
  21. package/dest/prover-client/factory.d.ts.map +1 -1
  22. package/dest/prover-client/factory.js +3 -3
  23. package/dest/prover-client/prover-client.d.ts +4 -2
  24. package/dest/prover-client/prover-client.d.ts.map +1 -1
  25. package/dest/prover-client/prover-client.js +13 -15
  26. package/dest/proving_broker/broker_prover_facade.d.ts +4 -3
  27. package/dest/proving_broker/broker_prover_facade.d.ts.map +1 -1
  28. package/dest/proving_broker/broker_prover_facade.js +25 -6
  29. package/dest/proving_broker/factory.d.ts.map +1 -1
  30. package/dest/proving_broker/factory.js +3 -3
  31. package/dest/proving_broker/index.d.ts +1 -1
  32. package/dest/proving_broker/index.d.ts.map +1 -1
  33. package/dest/proving_broker/index.js +2 -2
  34. package/dest/proving_broker/proof_store/factory.d.ts +6 -0
  35. package/dest/proving_broker/proof_store/factory.d.ts.map +1 -0
  36. package/dest/proving_broker/proof_store/factory.js +39 -0
  37. package/dest/proving_broker/proof_store/gcs_proof_store.d.ts +13 -0
  38. package/dest/proving_broker/proof_store/gcs_proof_store.d.ts.map +1 -0
  39. package/dest/proving_broker/proof_store/gcs_proof_store.js +46 -0
  40. package/dest/proving_broker/proof_store/index.d.ts +4 -0
  41. package/dest/proving_broker/proof_store/index.d.ts.map +1 -0
  42. package/dest/proving_broker/proof_store/index.js +4 -0
  43. package/dest/proving_broker/proof_store/inline_proof_store.d.ts +14 -0
  44. package/dest/proving_broker/proof_store/inline_proof_store.d.ts.map +1 -0
  45. package/dest/proving_broker/proof_store/inline_proof_store.js +37 -0
  46. package/dest/proving_broker/{proof_store.d.ts → proof_store/proof_store.d.ts} +1 -12
  47. package/dest/proving_broker/proof_store/proof_store.d.ts.map +1 -0
  48. package/dest/proving_broker/proof_store/proof_store.js +2 -0
  49. package/dest/proving_broker/proving_agent.d.ts +4 -4
  50. package/dest/proving_broker/proving_agent.d.ts.map +1 -1
  51. package/dest/proving_broker/proving_agent.js +5 -5
  52. package/dest/proving_broker/proving_broker.d.ts +1 -1
  53. package/dest/proving_broker/proving_broker.d.ts.map +1 -1
  54. package/dest/proving_broker/proving_broker.js +3 -3
  55. package/dest/proving_broker/proving_broker_database/persisted.d.ts +1 -1
  56. package/dest/proving_broker/proving_broker_database/persisted.d.ts.map +1 -1
  57. package/dest/proving_broker/proving_broker_database/persisted.js +4 -4
  58. package/dest/test/mock_prover.d.ts +1 -1
  59. package/dest/test/mock_prover.d.ts.map +1 -1
  60. package/dest/test/mock_prover.js +4 -5
  61. package/package.json +14 -12
  62. package/src/bin/get-proof-inputs.ts +60 -0
  63. package/src/block_builder/light.ts +6 -11
  64. package/src/mocks/test_context.ts +7 -9
  65. package/src/orchestrator/block-building-helpers.ts +358 -326
  66. package/src/orchestrator/orchestrator.ts +11 -15
  67. package/src/prover-agent/memory-proving-queue.ts +1 -1
  68. package/src/prover-agent/prover-agent.ts +10 -4
  69. package/src/prover-client/factory.ts +2 -3
  70. package/src/prover-client/prover-client.ts +14 -15
  71. package/src/proving_broker/broker_prover_facade.ts +28 -5
  72. package/src/proving_broker/factory.ts +9 -5
  73. package/src/proving_broker/index.ts +1 -1
  74. package/src/proving_broker/proof_store/factory.ts +42 -0
  75. package/src/proving_broker/proof_store/gcs_proof_store.ts +72 -0
  76. package/src/proving_broker/proof_store/index.ts +3 -0
  77. package/src/proving_broker/{proof_store.ts → proof_store/inline_proof_store.ts} +1 -44
  78. package/src/proving_broker/proof_store/proof_store.ts +54 -0
  79. package/src/proving_broker/proving_agent.ts +11 -5
  80. package/src/proving_broker/proving_broker.ts +8 -2
  81. package/src/proving_broker/proving_broker_database/persisted.ts +3 -3
  82. package/src/test/mock_prover.ts +3 -4
  83. package/dest/proving_broker/proof_store.d.ts.map +0 -1
  84. package/dest/proving_broker/proof_store.js +0 -37
@@ -53,6 +53,7 @@ import { computeUnbalancedMerkleRoot } from '@aztec/foundation/trees';
53
53
  import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vks';
54
54
  import { protocolContractTreeRoot } from '@aztec/protocol-contracts';
55
55
  import { computeFeePayerBalanceLeafSlot } from '@aztec/simulator/server';
56
+ import { Attributes, type Span, runInSpan } from '@aztec/telemetry-client';
56
57
  import { type MerkleTreeReadOperations } from '@aztec/world-state';
57
58
 
58
59
  import { inspect } from 'util';
@@ -67,185 +68,191 @@ type BaseTreeNames = 'NoteHashTree' | 'ContractTree' | 'NullifierTree' | 'Public
67
68
  export type TreeNames = BaseTreeNames | 'L1ToL2MessageTree' | 'Archive';
68
69
 
69
70
  // Builds the hints for base rollup. Updating the contract, nullifier, and data trees in the process.
70
- export async function buildBaseRollupHints(
71
- tx: ProcessedTx,
72
- globalVariables: GlobalVariables,
73
- db: MerkleTreeWriteOperations,
74
- startSpongeBlob: SpongeBlob,
75
- ) {
76
- // Get trees info before any changes hit
77
- const constants = await getConstantRollupData(globalVariables, db);
78
- const start = new PartialStateReference(
79
- await getTreeSnapshot(MerkleTreeId.NOTE_HASH_TREE, db),
80
- await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE, db),
81
- await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE, db),
82
- );
83
- // Get the subtree sibling paths for the circuit
84
- const noteHashSubtreeSiblingPathArray = await getSubtreeSiblingPath(
85
- MerkleTreeId.NOTE_HASH_TREE,
86
- NOTE_HASH_SUBTREE_HEIGHT,
87
- db,
88
- );
89
-
90
- const noteHashSubtreeSiblingPath = makeTuple(NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, i =>
91
- i < noteHashSubtreeSiblingPathArray.length ? noteHashSubtreeSiblingPathArray[i] : Fr.ZERO,
92
- );
93
-
94
- // Update the note hash trees with the new items being inserted to get the new roots
95
- // that will be used by the next iteration of the base rollup circuit, skipping the empty ones
96
- const noteHashes = padArrayEnd(tx.txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX);
97
- await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, noteHashes);
98
-
99
- // The read witnesses for a given TX should be generated before the writes of the same TX are applied.
100
- // All reads that refer to writes in the same tx are transient and can be simplified out.
101
- const txPublicDataUpdateRequestInfo = await processPublicDataUpdateRequests(tx, db);
102
-
103
- // Update the nullifier tree, capturing the low nullifier info for each individual operation
104
- const {
105
- lowLeavesWitnessData: nullifierWitnessLeaves,
106
- newSubtreeSiblingPath: nullifiersSubtreeSiblingPath,
107
- sortedNewLeaves: sortednullifiers,
108
- sortedNewLeavesIndexes,
109
- } = await db.batchInsert(
110
- MerkleTreeId.NULLIFIER_TREE,
111
- padArrayEnd(tx.txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX).map(n => n.toBuffer()),
112
- NULLIFIER_SUBTREE_HEIGHT,
113
- );
114
-
115
- if (nullifierWitnessLeaves === undefined) {
116
- throw new Error(`Could not craft nullifier batch insertion proofs`);
117
- }
118
-
119
- // Extract witness objects from returned data
120
- const nullifierPredecessorMembershipWitnessesWithoutPadding: MembershipWitness<typeof NULLIFIER_TREE_HEIGHT>[] =
121
- nullifierWitnessLeaves.map(l =>
122
- MembershipWitness.fromBufferArray(l.index, assertLength(l.siblingPath.toBufferArray(), NULLIFIER_TREE_HEIGHT)),
71
+ export const buildBaseRollupHints = runInSpan(
72
+ 'BlockBuilderHelpers',
73
+ 'buildBaseRollupHints',
74
+ async (
75
+ span: Span,
76
+ tx: ProcessedTx,
77
+ globalVariables: GlobalVariables,
78
+ db: MerkleTreeWriteOperations,
79
+ startSpongeBlob: SpongeBlob,
80
+ ) => {
81
+ span.setAttribute(Attributes.TX_HASH, tx.hash.toString());
82
+ // Get trees info before any changes hit
83
+ const constants = await getConstantRollupData(globalVariables, db);
84
+ const start = new PartialStateReference(
85
+ await getTreeSnapshot(MerkleTreeId.NOTE_HASH_TREE, db),
86
+ await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE, db),
87
+ await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE, db),
88
+ );
89
+ // Get the subtree sibling paths for the circuit
90
+ const noteHashSubtreeSiblingPathArray = await getSubtreeSiblingPath(
91
+ MerkleTreeId.NOTE_HASH_TREE,
92
+ NOTE_HASH_SUBTREE_HEIGHT,
93
+ db,
123
94
  );
124
95
 
125
- const nullifierSubtreeSiblingPathArray = nullifiersSubtreeSiblingPath.toFields();
126
-
127
- const nullifierSubtreeSiblingPath = makeTuple(NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, i =>
128
- i < nullifierSubtreeSiblingPathArray.length ? nullifierSubtreeSiblingPathArray[i] : Fr.ZERO,
129
- );
130
-
131
- // Append new data to startSpongeBlob
132
- const inputSpongeBlob = startSpongeBlob.clone();
133
- startSpongeBlob.absorb(tx.txEffect.toBlobFields());
134
-
135
- if (tx.avmProvingRequest) {
136
- // Build public base rollup hints
137
- const stateDiffHints = PublicBaseStateDiffHints.from({
138
- nullifierPredecessorPreimages: makeTuple(MAX_NULLIFIERS_PER_TX, i =>
139
- i < nullifierWitnessLeaves.length
140
- ? (nullifierWitnessLeaves[i].leafPreimage as NullifierLeafPreimage)
141
- : NullifierLeafPreimage.empty(),
142
- ),
143
- nullifierPredecessorMembershipWitnesses: makeTuple(MAX_NULLIFIERS_PER_TX, i =>
144
- i < nullifierPredecessorMembershipWitnessesWithoutPadding.length
145
- ? nullifierPredecessorMembershipWitnessesWithoutPadding[i]
146
- : makeEmptyMembershipWitness(NULLIFIER_TREE_HEIGHT),
147
- ),
148
- sortedNullifiers: makeTuple(MAX_NULLIFIERS_PER_TX, i => Fr.fromBuffer(sortednullifiers[i])),
149
- sortedNullifierIndexes: makeTuple(MAX_NULLIFIERS_PER_TX, i => sortedNewLeavesIndexes[i]),
150
- noteHashSubtreeSiblingPath,
151
- nullifierSubtreeSiblingPath,
152
- lowPublicDataWritesPreimages: padArrayEnd(
153
- txPublicDataUpdateRequestInfo.lowPublicDataWritesPreimages,
154
- PublicDataTreeLeafPreimage.empty(),
155
- MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
156
- ),
157
- lowPublicDataWritesMembershipWitnesses: padArrayEnd(
158
- txPublicDataUpdateRequestInfo.lowPublicDataWritesMembershipWitnesses,
159
- MembershipWitness.empty(PUBLIC_DATA_TREE_HEIGHT),
160
- MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
161
- ),
162
- publicDataTreeSiblingPaths: padArrayEnd(
163
- txPublicDataUpdateRequestInfo.publicDataWritesSiblingPaths,
164
- makeTuple(PUBLIC_DATA_TREE_HEIGHT, () => Fr.ZERO),
165
- MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
166
- ),
167
- });
96
+ const noteHashSubtreeSiblingPath = makeTuple(NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, i =>
97
+ i < noteHashSubtreeSiblingPathArray.length ? noteHashSubtreeSiblingPathArray[i] : Fr.ZERO,
98
+ );
168
99
 
169
- const blockHash = tx.constants.historicalHeader.hash();
170
- const archiveRootMembershipWitness = await getMembershipWitnessFor(
171
- blockHash,
172
- MerkleTreeId.ARCHIVE,
173
- ARCHIVE_HEIGHT,
174
- db,
100
+ // Update the note hash trees with the new items being inserted to get the new roots
101
+ // that will be used by the next iteration of the base rollup circuit, skipping the empty ones
102
+ const noteHashes = padArrayEnd(tx.txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX);
103
+ await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, noteHashes);
104
+
105
+ // The read witnesses for a given TX should be generated before the writes of the same TX are applied.
106
+ // All reads that refer to writes in the same tx are transient and can be simplified out.
107
+ const txPublicDataUpdateRequestInfo = await processPublicDataUpdateRequests(tx, db);
108
+
109
+ // Update the nullifier tree, capturing the low nullifier info for each individual operation
110
+ const {
111
+ lowLeavesWitnessData: nullifierWitnessLeaves,
112
+ newSubtreeSiblingPath: nullifiersSubtreeSiblingPath,
113
+ sortedNewLeaves: sortednullifiers,
114
+ sortedNewLeavesIndexes,
115
+ } = await db.batchInsert(
116
+ MerkleTreeId.NULLIFIER_TREE,
117
+ padArrayEnd(tx.txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX).map(n => n.toBuffer()),
118
+ NULLIFIER_SUBTREE_HEIGHT,
175
119
  );
176
120
 
177
- return PublicBaseRollupHints.from({
178
- start,
179
- startSpongeBlob: inputSpongeBlob,
180
- stateDiffHints,
181
- archiveRootMembershipWitness,
182
- constants,
183
- });
184
- } else {
185
- if (
186
- txPublicDataUpdateRequestInfo.lowPublicDataWritesMembershipWitnesses.length > 1 ||
187
- txPublicDataUpdateRequestInfo.lowPublicDataWritesPreimages.length > 1 ||
188
- txPublicDataUpdateRequestInfo.publicDataWritesSiblingPaths.length > 1
189
- ) {
190
- throw new Error(`More than one public data write in a private only tx`);
121
+ if (nullifierWitnessLeaves === undefined) {
122
+ throw new Error(`Could not craft nullifier batch insertion proofs`);
191
123
  }
192
124
 
193
- // Create data hint for reading fee payer initial balance in Fee Juice
194
- // If no fee payer is set, read hint should be empty
195
- const leafSlot = computeFeePayerBalanceLeafSlot(tx.data.feePayer);
196
- const feePayerFeeJuiceBalanceReadHint = tx.data.feePayer.isZero()
197
- ? PublicDataHint.empty()
198
- : await getPublicDataHint(db, leafSlot.toBigInt());
199
-
200
- const feeWriteLowLeafPreimage =
201
- txPublicDataUpdateRequestInfo.lowPublicDataWritesPreimages[0] || PublicDataTreeLeafPreimage.empty();
202
- const feeWriteLowLeafMembershipWitness =
203
- txPublicDataUpdateRequestInfo.lowPublicDataWritesMembershipWitnesses[0] ||
204
- MembershipWitness.empty<typeof PUBLIC_DATA_TREE_HEIGHT>(PUBLIC_DATA_TREE_HEIGHT);
205
- const feeWriteSiblingPath =
206
- txPublicDataUpdateRequestInfo.publicDataWritesSiblingPaths[0] ||
207
- makeTuple(PUBLIC_DATA_TREE_HEIGHT, () => Fr.ZERO);
208
-
209
- const stateDiffHints = PrivateBaseStateDiffHints.from({
210
- nullifierPredecessorPreimages: makeTuple(MAX_NULLIFIERS_PER_TX, i =>
211
- i < nullifierWitnessLeaves.length
212
- ? (nullifierWitnessLeaves[i].leafPreimage as NullifierLeafPreimage)
213
- : NullifierLeafPreimage.empty(),
214
- ),
215
- nullifierPredecessorMembershipWitnesses: makeTuple(MAX_NULLIFIERS_PER_TX, i =>
216
- i < nullifierPredecessorMembershipWitnessesWithoutPadding.length
217
- ? nullifierPredecessorMembershipWitnessesWithoutPadding[i]
218
- : makeEmptyMembershipWitness(NULLIFIER_TREE_HEIGHT),
219
- ),
220
- sortedNullifiers: makeTuple(MAX_NULLIFIERS_PER_TX, i => Fr.fromBuffer(sortednullifiers[i])),
221
- sortedNullifierIndexes: makeTuple(MAX_NULLIFIERS_PER_TX, i => sortedNewLeavesIndexes[i]),
222
- noteHashSubtreeSiblingPath,
223
- nullifierSubtreeSiblingPath,
224
- feeWriteLowLeafPreimage,
225
- feeWriteLowLeafMembershipWitness,
226
- feeWriteSiblingPath,
227
- });
125
+ // Extract witness objects from returned data
126
+ const nullifierPredecessorMembershipWitnessesWithoutPadding: MembershipWitness<typeof NULLIFIER_TREE_HEIGHT>[] =
127
+ nullifierWitnessLeaves.map(l =>
128
+ MembershipWitness.fromBufferArray(l.index, assertLength(l.siblingPath.toBufferArray(), NULLIFIER_TREE_HEIGHT)),
129
+ );
228
130
 
229
- const blockHash = tx.constants.historicalHeader.hash();
230
- const archiveRootMembershipWitness = await getMembershipWitnessFor(
231
- blockHash,
232
- MerkleTreeId.ARCHIVE,
233
- ARCHIVE_HEIGHT,
234
- db,
131
+ const nullifierSubtreeSiblingPathArray = nullifiersSubtreeSiblingPath.toFields();
132
+
133
+ const nullifierSubtreeSiblingPath = makeTuple(NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, i =>
134
+ i < nullifierSubtreeSiblingPathArray.length ? nullifierSubtreeSiblingPathArray[i] : Fr.ZERO,
235
135
  );
236
136
 
237
- return PrivateBaseRollupHints.from({
238
- start,
239
- startSpongeBlob: inputSpongeBlob,
240
- stateDiffHints,
241
- feePayerFeeJuiceBalanceReadHint: feePayerFeeJuiceBalanceReadHint,
242
- archiveRootMembershipWitness,
243
- constants,
244
- });
245
- }
246
- }
137
+ // Append new data to startSpongeBlob
138
+ const inputSpongeBlob = startSpongeBlob.clone();
139
+ startSpongeBlob.absorb(tx.txEffect.toBlobFields());
140
+
141
+ if (tx.avmProvingRequest) {
142
+ // Build public base rollup hints
143
+ const stateDiffHints = PublicBaseStateDiffHints.from({
144
+ nullifierPredecessorPreimages: makeTuple(MAX_NULLIFIERS_PER_TX, i =>
145
+ i < nullifierWitnessLeaves.length
146
+ ? (nullifierWitnessLeaves[i].leafPreimage as NullifierLeafPreimage)
147
+ : NullifierLeafPreimage.empty(),
148
+ ),
149
+ nullifierPredecessorMembershipWitnesses: makeTuple(MAX_NULLIFIERS_PER_TX, i =>
150
+ i < nullifierPredecessorMembershipWitnessesWithoutPadding.length
151
+ ? nullifierPredecessorMembershipWitnessesWithoutPadding[i]
152
+ : makeEmptyMembershipWitness(NULLIFIER_TREE_HEIGHT),
153
+ ),
154
+ sortedNullifiers: makeTuple(MAX_NULLIFIERS_PER_TX, i => Fr.fromBuffer(sortednullifiers[i])),
155
+ sortedNullifierIndexes: makeTuple(MAX_NULLIFIERS_PER_TX, i => sortedNewLeavesIndexes[i]),
156
+ noteHashSubtreeSiblingPath,
157
+ nullifierSubtreeSiblingPath,
158
+ lowPublicDataWritesPreimages: padArrayEnd(
159
+ txPublicDataUpdateRequestInfo.lowPublicDataWritesPreimages,
160
+ PublicDataTreeLeafPreimage.empty(),
161
+ MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
162
+ ),
163
+ lowPublicDataWritesMembershipWitnesses: padArrayEnd(
164
+ txPublicDataUpdateRequestInfo.lowPublicDataWritesMembershipWitnesses,
165
+ MembershipWitness.empty(PUBLIC_DATA_TREE_HEIGHT),
166
+ MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
167
+ ),
168
+ publicDataTreeSiblingPaths: padArrayEnd(
169
+ txPublicDataUpdateRequestInfo.publicDataWritesSiblingPaths,
170
+ makeTuple(PUBLIC_DATA_TREE_HEIGHT, () => Fr.ZERO),
171
+ MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
172
+ ),
173
+ });
174
+
175
+ const blockHash = tx.constants.historicalHeader.hash();
176
+ const archiveRootMembershipWitness = await getMembershipWitnessFor(
177
+ blockHash,
178
+ MerkleTreeId.ARCHIVE,
179
+ ARCHIVE_HEIGHT,
180
+ db,
181
+ );
182
+
183
+ return PublicBaseRollupHints.from({
184
+ start,
185
+ startSpongeBlob: inputSpongeBlob,
186
+ stateDiffHints,
187
+ archiveRootMembershipWitness,
188
+ constants,
189
+ });
190
+ } else {
191
+ if (
192
+ txPublicDataUpdateRequestInfo.lowPublicDataWritesMembershipWitnesses.length > 1 ||
193
+ txPublicDataUpdateRequestInfo.lowPublicDataWritesPreimages.length > 1 ||
194
+ txPublicDataUpdateRequestInfo.publicDataWritesSiblingPaths.length > 1
195
+ ) {
196
+ throw new Error(`More than one public data write in a private only tx`);
197
+ }
198
+
199
+ // Create data hint for reading fee payer initial balance in Fee Juice
200
+ // If no fee payer is set, read hint should be empty
201
+ const leafSlot = computeFeePayerBalanceLeafSlot(tx.data.feePayer);
202
+ const feePayerFeeJuiceBalanceReadHint = tx.data.feePayer.isZero()
203
+ ? PublicDataHint.empty()
204
+ : await getPublicDataHint(db, leafSlot.toBigInt());
205
+
206
+ const feeWriteLowLeafPreimage =
207
+ txPublicDataUpdateRequestInfo.lowPublicDataWritesPreimages[0] || PublicDataTreeLeafPreimage.empty();
208
+ const feeWriteLowLeafMembershipWitness =
209
+ txPublicDataUpdateRequestInfo.lowPublicDataWritesMembershipWitnesses[0] ||
210
+ MembershipWitness.empty<typeof PUBLIC_DATA_TREE_HEIGHT>(PUBLIC_DATA_TREE_HEIGHT);
211
+ const feeWriteSiblingPath =
212
+ txPublicDataUpdateRequestInfo.publicDataWritesSiblingPaths[0] ||
213
+ makeTuple(PUBLIC_DATA_TREE_HEIGHT, () => Fr.ZERO);
214
+
215
+ const stateDiffHints = PrivateBaseStateDiffHints.from({
216
+ nullifierPredecessorPreimages: makeTuple(MAX_NULLIFIERS_PER_TX, i =>
217
+ i < nullifierWitnessLeaves.length
218
+ ? (nullifierWitnessLeaves[i].leafPreimage as NullifierLeafPreimage)
219
+ : NullifierLeafPreimage.empty(),
220
+ ),
221
+ nullifierPredecessorMembershipWitnesses: makeTuple(MAX_NULLIFIERS_PER_TX, i =>
222
+ i < nullifierPredecessorMembershipWitnessesWithoutPadding.length
223
+ ? nullifierPredecessorMembershipWitnessesWithoutPadding[i]
224
+ : makeEmptyMembershipWitness(NULLIFIER_TREE_HEIGHT),
225
+ ),
226
+ sortedNullifiers: makeTuple(MAX_NULLIFIERS_PER_TX, i => Fr.fromBuffer(sortednullifiers[i])),
227
+ sortedNullifierIndexes: makeTuple(MAX_NULLIFIERS_PER_TX, i => sortedNewLeavesIndexes[i]),
228
+ noteHashSubtreeSiblingPath,
229
+ nullifierSubtreeSiblingPath,
230
+ feeWriteLowLeafPreimage,
231
+ feeWriteLowLeafMembershipWitness,
232
+ feeWriteSiblingPath,
233
+ });
234
+
235
+ const blockHash = tx.constants.historicalHeader.hash();
236
+ const archiveRootMembershipWitness = await getMembershipWitnessFor(
237
+ blockHash,
238
+ MerkleTreeId.ARCHIVE,
239
+ ARCHIVE_HEIGHT,
240
+ db,
241
+ );
242
+
243
+ return PrivateBaseRollupHints.from({
244
+ start,
245
+ startSpongeBlob: inputSpongeBlob,
246
+ stateDiffHints,
247
+ feePayerFeeJuiceBalanceReadHint: feePayerFeeJuiceBalanceReadHint,
248
+ archiveRootMembershipWitness,
249
+ constants,
250
+ });
251
+ }
252
+ },
253
+ );
247
254
 
248
- async function getPublicDataHint(db: MerkleTreeWriteOperations, leafSlot: bigint) {
255
+ export async function getPublicDataHint(db: MerkleTreeWriteOperations, leafSlot: bigint) {
249
256
  const { index } = (await db.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot)) ?? {};
250
257
  if (index === undefined) {
251
258
  throw new Error(`Cannot find the previous value index for public data ${leafSlot}.`);
@@ -265,111 +272,126 @@ async function getPublicDataHint(db: MerkleTreeWriteOperations, leafSlot: bigint
265
272
  return new PublicDataHint(new Fr(leafSlot), value, membershipWitness, leafPreimage);
266
273
  }
267
274
 
268
- export function buildBlobHints(txEffects: TxEffect[]) {
269
- const blobFields = txEffects.flatMap(tx => tx.toBlobFields());
270
- const blobs = Blob.getBlobs(blobFields);
271
- const blobCommitments = blobs.map(b => b.commitmentToFields());
272
- const blobsHash = new Fr(getBlobsHashFromBlobs(blobs));
273
- return { blobFields, blobCommitments, blobs, blobsHash };
274
- }
275
-
276
- export function buildHeaderFromCircuitOutputs(
277
- previousRollupData: BaseOrMergeRollupPublicInputs[],
278
- parityPublicInputs: ParityPublicInputs,
279
- rootRollupOutputs: BlockRootOrBlockMergePublicInputs,
280
- endState: StateReference,
281
- logger?: Logger,
282
- ) {
283
- if (previousRollupData.length > 2) {
284
- throw new Error(`There can't be more than 2 previous rollups. Received ${previousRollupData.length}.`);
285
- }
286
-
287
- const blobsHash = rootRollupOutputs.blobPublicInputs[0].getBlobsHash();
288
- const numTxs = previousRollupData.reduce((sum, d) => sum + d.numTxs, 0);
289
- const outHash =
290
- previousRollupData.length === 0
291
- ? Fr.ZERO.toBuffer()
292
- : previousRollupData.length === 1
293
- ? previousRollupData[0].outHash.toBuffer()
294
- : sha256Trunc(
295
- Buffer.concat([previousRollupData[0].outHash.toBuffer(), previousRollupData[1].outHash.toBuffer()]),
296
- );
297
- const contentCommitment = new ContentCommitment(
298
- new Fr(numTxs),
299
- blobsHash,
300
- parityPublicInputs.shaRoot.toBuffer(),
301
- outHash,
302
- );
275
+ export const buildBlobHints = runInSpan(
276
+ 'BlockBuilderHelpers',
277
+ 'buildBlobHints',
278
+ (_span: Span, txEffects: TxEffect[]) => {
279
+ const blobFields = txEffects.flatMap(tx => tx.toBlobFields());
280
+ const blobs = Blob.getBlobs(blobFields);
281
+ const blobCommitments = blobs.map(b => b.commitmentToFields());
282
+ const blobsHash = new Fr(getBlobsHashFromBlobs(blobs));
283
+ return { blobFields, blobCommitments, blobs, blobsHash };
284
+ },
285
+ );
286
+
287
+ export const buildHeaderFromCircuitOutputs = runInSpan(
288
+ 'BlockBuilderHelpers',
289
+ 'buildHeaderFromCircuitOutputs',
290
+ (
291
+ _span,
292
+ previousRollupData: BaseOrMergeRollupPublicInputs[],
293
+ parityPublicInputs: ParityPublicInputs,
294
+ rootRollupOutputs: BlockRootOrBlockMergePublicInputs,
295
+ endState: StateReference,
296
+ logger?: Logger,
297
+ ) => {
298
+ if (previousRollupData.length > 2) {
299
+ throw new Error(`There can't be more than 2 previous rollups. Received ${previousRollupData.length}.`);
300
+ }
303
301
 
304
- const accumulatedFees = previousRollupData.reduce((sum, d) => sum.add(d.accumulatedFees), Fr.ZERO);
305
- const accumulatedManaUsed = previousRollupData.reduce((sum, d) => sum.add(d.accumulatedManaUsed), Fr.ZERO);
306
- const header = new BlockHeader(
307
- rootRollupOutputs.previousArchive,
308
- contentCommitment,
309
- endState,
310
- rootRollupOutputs.endGlobalVariables,
311
- accumulatedFees,
312
- accumulatedManaUsed,
313
- );
314
- if (!header.hash().equals(rootRollupOutputs.endBlockHash)) {
315
- logger?.error(
316
- `Block header mismatch when building header from circuit outputs.` +
317
- `\n\nHeader: ${inspect(header)}` +
318
- `\n\nCircuit: ${toFriendlyJSON(rootRollupOutputs)}`,
302
+ const blobsHash = rootRollupOutputs.blobPublicInputs[0].getBlobsHash();
303
+ const numTxs = previousRollupData.reduce((sum, d) => sum + d.numTxs, 0);
304
+ const outHash =
305
+ previousRollupData.length === 0
306
+ ? Fr.ZERO.toBuffer()
307
+ : previousRollupData.length === 1
308
+ ? previousRollupData[0].outHash.toBuffer()
309
+ : sha256Trunc(
310
+ Buffer.concat([previousRollupData[0].outHash.toBuffer(), previousRollupData[1].outHash.toBuffer()]),
311
+ );
312
+ const contentCommitment = new ContentCommitment(
313
+ new Fr(numTxs),
314
+ blobsHash,
315
+ parityPublicInputs.shaRoot.toBuffer(),
316
+ outHash,
319
317
  );
320
- throw new Error(`Block header mismatch when building from circuit outputs`);
321
- }
322
- return header;
323
- }
324
318
 
325
- export async function buildHeaderAndBodyFromTxs(
326
- txs: ProcessedTx[],
327
- globalVariables: GlobalVariables,
328
- l1ToL2Messages: Fr[],
329
- db: MerkleTreeReadOperations,
330
- ) {
331
- const stateReference = new StateReference(
332
- await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, db),
333
- new PartialStateReference(
334
- await getTreeSnapshot(MerkleTreeId.NOTE_HASH_TREE, db),
335
- await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE, db),
336
- await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE, db),
337
- ),
338
- );
319
+ const accumulatedFees = previousRollupData.reduce((sum, d) => sum.add(d.accumulatedFees), Fr.ZERO);
320
+ const accumulatedManaUsed = previousRollupData.reduce((sum, d) => sum.add(d.accumulatedManaUsed), Fr.ZERO);
321
+ const header = new BlockHeader(
322
+ rootRollupOutputs.previousArchive,
323
+ contentCommitment,
324
+ endState,
325
+ rootRollupOutputs.endGlobalVariables,
326
+ accumulatedFees,
327
+ accumulatedManaUsed,
328
+ );
329
+ if (!header.hash().equals(rootRollupOutputs.endBlockHash)) {
330
+ logger?.error(
331
+ `Block header mismatch when building header from circuit outputs.` +
332
+ `\n\nHeader: ${inspect(header)}` +
333
+ `\n\nCircuit: ${toFriendlyJSON(rootRollupOutputs)}`,
334
+ );
335
+ throw new Error(`Block header mismatch when building from circuit outputs`);
336
+ }
337
+ return header;
338
+ },
339
+ );
340
+
341
+ export const buildHeaderAndBodyFromTxs = runInSpan(
342
+ 'BlockBuilderHelpers',
343
+ 'buildHeaderAndBodyFromTxs',
344
+ async (
345
+ span,
346
+ txs: ProcessedTx[],
347
+ globalVariables: GlobalVariables,
348
+ l1ToL2Messages: Fr[],
349
+ db: MerkleTreeReadOperations,
350
+ ) => {
351
+ span.setAttribute(Attributes.BLOCK_NUMBER, globalVariables.blockNumber.toNumber());
352
+ const stateReference = new StateReference(
353
+ await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, db),
354
+ new PartialStateReference(
355
+ await getTreeSnapshot(MerkleTreeId.NOTE_HASH_TREE, db),
356
+ await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE, db),
357
+ await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE, db),
358
+ ),
359
+ );
339
360
 
340
- const previousArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
341
-
342
- const txEffects = txs.map(tx => tx.txEffect);
343
- const body = new Body(txEffects);
344
-
345
- const numTxs = body.txEffects.length;
346
- const outHash =
347
- numTxs === 0
348
- ? Fr.ZERO.toBuffer()
349
- : numTxs === 1
350
- ? body.txEffects[0].txOutHash()
351
- : computeUnbalancedMerkleRoot(
352
- body.txEffects.map(tx => tx.txOutHash()),
353
- TxEffect.empty().txOutHash(),
354
- );
355
-
356
- l1ToL2Messages = padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
357
- const hasher = (left: Buffer, right: Buffer) => sha256Trunc(Buffer.concat([left, right]));
358
- const parityHeight = Math.ceil(Math.log2(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP));
359
- const parityShaRoot = new MerkleTreeCalculator(parityHeight, Fr.ZERO.toBuffer(), hasher).computeTreeRoot(
360
- l1ToL2Messages.map(msg => msg.toBuffer()),
361
- );
362
- const blobsHash = getBlobsHashFromBlobs(Blob.getBlobs(body.toBlobFields()));
361
+ const previousArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
362
+
363
+ const txEffects = txs.map(tx => tx.txEffect);
364
+ const body = new Body(txEffects);
365
+
366
+ const numTxs = body.txEffects.length;
367
+ const outHash =
368
+ numTxs === 0
369
+ ? Fr.ZERO.toBuffer()
370
+ : numTxs === 1
371
+ ? body.txEffects[0].txOutHash()
372
+ : computeUnbalancedMerkleRoot(
373
+ body.txEffects.map(tx => tx.txOutHash()),
374
+ TxEffect.empty().txOutHash(),
375
+ );
376
+
377
+ l1ToL2Messages = padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
378
+ const hasher = (left: Buffer, right: Buffer) => sha256Trunc(Buffer.concat([left, right]));
379
+ const parityHeight = Math.ceil(Math.log2(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP));
380
+ const parityShaRoot = new MerkleTreeCalculator(parityHeight, Fr.ZERO.toBuffer(), hasher).computeTreeRoot(
381
+ l1ToL2Messages.map(msg => msg.toBuffer()),
382
+ );
383
+ const blobsHash = getBlobsHashFromBlobs(Blob.getBlobs(body.toBlobFields()));
363
384
 
364
- const contentCommitment = new ContentCommitment(new Fr(numTxs), blobsHash, parityShaRoot, outHash);
385
+ const contentCommitment = new ContentCommitment(new Fr(numTxs), blobsHash, parityShaRoot, outHash);
365
386
 
366
- const fees = body.txEffects.reduce((acc, tx) => acc.add(tx.transactionFee), Fr.ZERO);
367
- const manaUsed = txs.reduce((acc, tx) => acc.add(new Fr(tx.gasUsed.totalGas.l2Gas)), Fr.ZERO);
387
+ const fees = body.txEffects.reduce((acc, tx) => acc.add(tx.transactionFee), Fr.ZERO);
388
+ const manaUsed = txs.reduce((acc, tx) => acc.add(new Fr(tx.gasUsed.totalGas.l2Gas)), Fr.ZERO);
368
389
 
369
- const header = new BlockHeader(previousArchive, contentCommitment, stateReference, globalVariables, fees, manaUsed);
390
+ const header = new BlockHeader(previousArchive, contentCommitment, stateReference, globalVariables, fees, manaUsed);
370
391
 
371
- return { header, body };
372
- }
392
+ return { header, body };
393
+ },
394
+ );
373
395
 
374
396
  export function getBlobsHashFromBlobs(inputs: Blob[]): Buffer {
375
397
  const blobHashes = serializeToBuffer(inputs.map(b => b.getEthVersionedBlobHash()));
@@ -388,22 +410,26 @@ export async function validateBlockRootOutput(
388
410
  ]);
389
411
  }
390
412
 
391
- export async function validateState(state: StateReference, db: MerkleTreeReadOperations) {
392
- const promises = [MerkleTreeId.NOTE_HASH_TREE, MerkleTreeId.NULLIFIER_TREE, MerkleTreeId.PUBLIC_DATA_TREE].map(
393
- async (id: MerkleTreeId) => {
394
- return { key: id, value: await getTreeSnapshot(id, db) };
395
- },
396
- );
397
- const snapshots: Map<MerkleTreeId, AppendOnlyTreeSnapshot> = new Map(
398
- (await Promise.all(promises)).map(obj => [obj.key, obj.value]),
399
- );
400
- validatePartialState(state.partial, snapshots);
401
- validateSimulatedTree(
402
- await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, db),
403
- state.l1ToL2MessageTree,
404
- 'L1ToL2MessageTree',
405
- );
406
- }
413
+ export const validateState = runInSpan(
414
+ 'BlockBuilderHelpers',
415
+ 'validateState',
416
+ async (_span, state: StateReference, db: MerkleTreeReadOperations) => {
417
+ const promises = [MerkleTreeId.NOTE_HASH_TREE, MerkleTreeId.NULLIFIER_TREE, MerkleTreeId.PUBLIC_DATA_TREE].map(
418
+ async (id: MerkleTreeId) => {
419
+ return { key: id, value: await getTreeSnapshot(id, db) };
420
+ },
421
+ );
422
+ const snapshots: Map<MerkleTreeId, AppendOnlyTreeSnapshot> = new Map(
423
+ (await Promise.all(promises)).map(obj => [obj.key, obj.value]),
424
+ );
425
+ validatePartialState(state.partial, snapshots);
426
+ validateSimulatedTree(
427
+ await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, db),
428
+ state.l1ToL2MessageTree,
429
+ 'L1ToL2MessageTree',
430
+ );
431
+ },
432
+ );
407
433
 
408
434
  export async function getRootTreeSiblingPath<TID extends MerkleTreeId>(treeId: TID, db: MerkleTreeReadOperations) {
409
435
  const { size } = await db.getTreeInfo(treeId);
@@ -411,17 +437,18 @@ export async function getRootTreeSiblingPath<TID extends MerkleTreeId>(treeId: T
411
437
  return padArrayEnd(path.toFields(), Fr.ZERO, getTreeHeight(treeId));
412
438
  }
413
439
 
414
- export async function getConstantRollupData(
415
- globalVariables: GlobalVariables,
416
- db: MerkleTreeReadOperations,
417
- ): Promise<ConstantRollupData> {
418
- return ConstantRollupData.from({
419
- vkTreeRoot: getVKTreeRoot(),
420
- protocolContractTreeRoot,
421
- lastArchive: await getTreeSnapshot(MerkleTreeId.ARCHIVE, db),
422
- globalVariables,
423
- });
424
- }
440
+ export const getConstantRollupData = runInSpan(
441
+ 'BlockBuilderHelpers',
442
+ 'getConstantRollupData',
443
+ async (_span, globalVariables: GlobalVariables, db: MerkleTreeReadOperations): Promise<ConstantRollupData> => {
444
+ return ConstantRollupData.from({
445
+ vkTreeRoot: getVKTreeRoot(),
446
+ protocolContractTreeRoot,
447
+ lastArchive: await getTreeSnapshot(MerkleTreeId.ARCHIVE, db),
448
+ globalVariables,
449
+ });
450
+ },
451
+ );
425
452
 
426
453
  export async function getTreeSnapshot(id: MerkleTreeId, db: MerkleTreeReadOperations): Promise<AppendOnlyTreeSnapshot> {
427
454
  const treeInfo = await db.getTreeInfo(id);
@@ -436,42 +463,47 @@ export function makeEmptyMembershipWitness<N extends number>(height: N) {
436
463
  );
437
464
  }
438
465
 
439
- async function processPublicDataUpdateRequests(tx: ProcessedTx, db: MerkleTreeWriteOperations) {
440
- const allPublicDataWrites = tx.txEffect.publicDataWrites.map(
441
- ({ leafSlot, value }) => new PublicDataTreeLeaf(leafSlot, value),
442
- );
466
+ const processPublicDataUpdateRequests = runInSpan(
467
+ 'BlockBuilderHelpers',
468
+ 'processPublicDataUpdateRequests',
469
+ async (span, tx: ProcessedTx, db: MerkleTreeWriteOperations) => {
470
+ span.setAttribute(Attributes.TX_HASH, tx.hash.toString());
471
+ const allPublicDataWrites = tx.txEffect.publicDataWrites.map(
472
+ ({ leafSlot, value }) => new PublicDataTreeLeaf(leafSlot, value),
473
+ );
443
474
 
444
- const { lowLeavesWitnessData, insertionWitnessData } = await db.sequentialInsert(
445
- MerkleTreeId.PUBLIC_DATA_TREE,
446
- allPublicDataWrites.map(write => {
447
- if (write.isEmpty()) {
448
- throw new Error(`Empty public data write in tx: ${toFriendlyJSON(tx)}`);
449
- }
450
- return write.toBuffer();
451
- }),
452
- );
475
+ const { lowLeavesWitnessData, insertionWitnessData } = await db.sequentialInsert(
476
+ MerkleTreeId.PUBLIC_DATA_TREE,
477
+ allPublicDataWrites.map(write => {
478
+ if (write.isEmpty()) {
479
+ throw new Error(`Empty public data write in tx: ${toFriendlyJSON(tx)}`);
480
+ }
481
+ return write.toBuffer();
482
+ }),
483
+ );
453
484
 
454
- const lowPublicDataWritesPreimages = lowLeavesWitnessData.map(
455
- lowLeafWitness => lowLeafWitness.leafPreimage as PublicDataTreeLeafPreimage,
456
- );
457
- const lowPublicDataWritesMembershipWitnesses = lowLeavesWitnessData.map(lowLeafWitness =>
458
- MembershipWitness.fromBufferArray<typeof PUBLIC_DATA_TREE_HEIGHT>(
459
- lowLeafWitness.index,
460
- assertLength(lowLeafWitness.siblingPath.toBufferArray(), PUBLIC_DATA_TREE_HEIGHT),
461
- ),
462
- );
463
- const publicDataWritesSiblingPaths = insertionWitnessData.map(w => {
464
- const insertionSiblingPath = w.siblingPath.toFields();
465
- assertLength(insertionSiblingPath, PUBLIC_DATA_TREE_HEIGHT);
466
- return insertionSiblingPath as Tuple<Fr, typeof PUBLIC_DATA_TREE_HEIGHT>;
467
- });
468
-
469
- return {
470
- lowPublicDataWritesPreimages,
471
- lowPublicDataWritesMembershipWitnesses,
472
- publicDataWritesSiblingPaths,
473
- };
474
- }
485
+ const lowPublicDataWritesPreimages = lowLeavesWitnessData.map(
486
+ lowLeafWitness => lowLeafWitness.leafPreimage as PublicDataTreeLeafPreimage,
487
+ );
488
+ const lowPublicDataWritesMembershipWitnesses = lowLeavesWitnessData.map(lowLeafWitness =>
489
+ MembershipWitness.fromBufferArray<typeof PUBLIC_DATA_TREE_HEIGHT>(
490
+ lowLeafWitness.index,
491
+ assertLength(lowLeafWitness.siblingPath.toBufferArray(), PUBLIC_DATA_TREE_HEIGHT),
492
+ ),
493
+ );
494
+ const publicDataWritesSiblingPaths = insertionWitnessData.map(w => {
495
+ const insertionSiblingPath = w.siblingPath.toFields();
496
+ assertLength(insertionSiblingPath, PUBLIC_DATA_TREE_HEIGHT);
497
+ return insertionSiblingPath as Tuple<Fr, typeof PUBLIC_DATA_TREE_HEIGHT>;
498
+ });
499
+
500
+ return {
501
+ lowPublicDataWritesPreimages,
502
+ lowPublicDataWritesMembershipWitnesses,
503
+ publicDataWritesSiblingPaths,
504
+ };
505
+ },
506
+ );
475
507
 
476
508
  export async function getSubtreeSiblingPath(
477
509
  treeId: MerkleTreeId,