@aztec/merkle-tree 0.16.0 → 0.16.2

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 (68) hide show
  1. package/dest/index.d.ts +5 -1
  2. package/dest/index.d.ts.map +1 -1
  3. package/dest/index.js +6 -2
  4. package/dest/interfaces/append_only_tree.d.ts +2 -1
  5. package/dest/interfaces/append_only_tree.d.ts.map +1 -1
  6. package/dest/interfaces/indexed_tree.d.ts +38 -17
  7. package/dest/interfaces/indexed_tree.d.ts.map +1 -1
  8. package/dest/interfaces/merkle_tree.d.ts +7 -0
  9. package/dest/interfaces/merkle_tree.d.ts.map +1 -1
  10. package/dest/interfaces/update_only_tree.d.ts +3 -3
  11. package/dest/interfaces/update_only_tree.d.ts.map +1 -1
  12. package/dest/load_tree.d.ts +2 -1
  13. package/dest/load_tree.d.ts.map +1 -1
  14. package/dest/load_tree.js +1 -2
  15. package/dest/new_tree.d.ts +1 -1
  16. package/dest/new_tree.d.ts.map +1 -1
  17. package/dest/new_tree.js +2 -2
  18. package/dest/snapshots/append_only_snapshot.d.ts +30 -0
  19. package/dest/snapshots/append_only_snapshot.d.ts.map +1 -0
  20. package/dest/snapshots/append_only_snapshot.js +200 -0
  21. package/dest/snapshots/base_full_snapshot.d.ts +50 -0
  22. package/dest/snapshots/base_full_snapshot.d.ts.map +1 -0
  23. package/dest/snapshots/base_full_snapshot.js +179 -0
  24. package/dest/snapshots/full_snapshot.d.ts +22 -0
  25. package/dest/snapshots/full_snapshot.d.ts.map +1 -0
  26. package/dest/snapshots/full_snapshot.js +21 -0
  27. package/dest/snapshots/indexed_tree_snapshot.d.ts +15 -0
  28. package/dest/snapshots/indexed_tree_snapshot.d.ts.map +1 -0
  29. package/dest/snapshots/indexed_tree_snapshot.js +75 -0
  30. package/dest/snapshots/snapshot_builder.d.ts +76 -0
  31. package/dest/snapshots/snapshot_builder.d.ts.map +1 -0
  32. package/dest/snapshots/snapshot_builder.js +2 -0
  33. package/dest/snapshots/snapshot_builder_test_suite.d.ts +5 -0
  34. package/dest/snapshots/snapshot_builder_test_suite.d.ts.map +1 -0
  35. package/dest/snapshots/snapshot_builder_test_suite.js +163 -0
  36. package/dest/sparse_tree/sparse_tree.d.ts +5 -0
  37. package/dest/sparse_tree/sparse_tree.d.ts.map +1 -1
  38. package/dest/sparse_tree/sparse_tree.js +18 -1
  39. package/dest/standard_indexed_tree/standard_indexed_tree.d.ts +111 -81
  40. package/dest/standard_indexed_tree/standard_indexed_tree.d.ts.map +1 -1
  41. package/dest/standard_indexed_tree/standard_indexed_tree.js +225 -255
  42. package/dest/standard_indexed_tree/test/standard_indexed_tree_with_append.d.ts.map +1 -1
  43. package/dest/standard_indexed_tree/test/standard_indexed_tree_with_append.js +13 -19
  44. package/dest/standard_tree/standard_tree.d.ts +5 -0
  45. package/dest/standard_tree/standard_tree.d.ts.map +1 -1
  46. package/dest/standard_tree/standard_tree.js +24 -1
  47. package/dest/tree_base.d.ts +9 -4
  48. package/dest/tree_base.d.ts.map +1 -1
  49. package/dest/tree_base.js +16 -7
  50. package/package.json +4 -3
  51. package/src/index.ts +5 -1
  52. package/src/interfaces/append_only_tree.ts +2 -1
  53. package/src/interfaces/indexed_tree.ts +50 -28
  54. package/src/interfaces/merkle_tree.ts +8 -0
  55. package/src/interfaces/update_only_tree.ts +3 -4
  56. package/src/load_tree.ts +2 -2
  57. package/src/new_tree.ts +2 -2
  58. package/src/snapshots/append_only_snapshot.ts +243 -0
  59. package/src/snapshots/base_full_snapshot.ts +232 -0
  60. package/src/snapshots/full_snapshot.ts +26 -0
  61. package/src/snapshots/indexed_tree_snapshot.ts +108 -0
  62. package/src/snapshots/snapshot_builder.ts +84 -0
  63. package/src/snapshots/snapshot_builder_test_suite.ts +218 -0
  64. package/src/sparse_tree/sparse_tree.ts +16 -0
  65. package/src/standard_indexed_tree/standard_indexed_tree.ts +325 -299
  66. package/src/standard_indexed_tree/test/standard_indexed_tree_with_append.ts +23 -21
  67. package/src/standard_tree/standard_tree.ts +21 -0
  68. package/src/tree_base.ts +28 -7
@@ -1,53 +1,39 @@
1
+ var _StandardIndexedTree_snapshotBuilder;
2
+ import { __classPrivateFieldGet } from "tslib";
1
3
  import { toBigIntBE, toBufferBE } from '@aztec/foundation/bigint-buffer';
2
4
  import { createDebugLogger } from '@aztec/foundation/log';
3
5
  import { SiblingPath } from '@aztec/types';
6
+ import { IndexedTreeSnapshotBuilder, } from '../index.js';
4
7
  import { TreeBase } from '../tree_base.js';
5
8
  const log = createDebugLogger('aztec:standard-indexed-tree');
6
- const indexToKeyLeaf = (name, index) => {
7
- return `${name}:leaf:${index}`;
9
+ export const buildDbKeyForPreimage = (name, index) => {
10
+ return `${name}:leaf_by_index:${toBufferBE(index, 32).toString('hex')}`;
8
11
  };
9
- const zeroLeaf = {
10
- value: 0n,
11
- nextValue: 0n,
12
- nextIndex: 0n,
12
+ export const buildDbKeyForLeafIndex = (name, key) => {
13
+ return `${name}:leaf_index_by_leaf_key:${toBufferBE(key, 32).toString('hex')}`;
13
14
  };
14
15
  /**
15
16
  * Pre-compute empty witness.
16
17
  * @param treeHeight - Height of tree for sibling path.
17
18
  * @returns An empty witness.
18
19
  */
19
- function getEmptyLowLeafWitness(treeHeight) {
20
+ function getEmptyLowLeafWitness(treeHeight, leafPreimageFactory) {
20
21
  return {
21
- leafData: zeroLeaf,
22
+ leafPreimage: leafPreimageFactory.empty(),
22
23
  index: 0n,
23
24
  siblingPath: new SiblingPath(treeHeight, Array(treeHeight).fill(toBufferBE(0n, 32))),
24
25
  };
25
26
  }
26
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
27
- const encodeTreeValue = (leafData) => {
28
- const valueAsBuffer = toBufferBE(leafData.value, 32);
29
- const indexAsBuffer = toBufferBE(leafData.nextIndex, 32);
30
- const nextValueAsBuffer = toBufferBE(leafData.nextValue, 32);
31
- return Buffer.concat([valueAsBuffer, indexAsBuffer, nextValueAsBuffer]);
32
- };
33
- const decodeTreeValue = (buf) => {
34
- const value = toBigIntBE(buf.subarray(0, 32));
35
- const nextIndex = toBigIntBE(buf.subarray(32, 64));
36
- const nextValue = toBigIntBE(buf.subarray(64, 96));
37
- return {
38
- value,
39
- nextIndex,
40
- nextValue,
41
- };
42
- };
43
27
  /**
44
- * Indexed merkle tree.
28
+ * Standard implementation of an indexed tree.
45
29
  */
46
30
  export class StandardIndexedTree extends TreeBase {
47
- constructor() {
48
- super(...arguments);
49
- this.leaves = [];
50
- this.cachedLeaves = {};
31
+ constructor(db, hasher, name, depth, size = 0n, leafPreimageFactory, leafFactory, root) {
32
+ super(db, hasher, name, depth, size, root);
33
+ this.leafPreimageFactory = leafPreimageFactory;
34
+ this.leafFactory = leafFactory;
35
+ _StandardIndexedTree_snapshotBuilder.set(this, new IndexedTreeSnapshotBuilder(this.db, this, this.leafPreimageFactory));
36
+ this.cachedLeafPreimages = {};
51
37
  }
52
38
  /**
53
39
  * Appends the given leaves to the tree.
@@ -80,74 +66,119 @@ export class StandardIndexedTree extends TreeBase {
80
66
  * @param includeUncommitted - Indicates whether to include uncommitted leaves in the computation.
81
67
  * @returns The value of the leaf at the given index or undefined if the leaf is empty.
82
68
  */
83
- getLeafValue(index, includeUncommitted) {
84
- const leaf = this.getLatestLeafDataCopy(Number(index), includeUncommitted);
85
- if (!leaf) {
86
- return Promise.resolve(undefined);
87
- }
88
- return Promise.resolve(toBufferBE(leaf.value, 32));
69
+ async getLeafValue(index, includeUncommitted) {
70
+ const preimage = await this.getLatestLeafPreimageCopy(index, includeUncommitted);
71
+ return preimage && preimage.toBuffer();
89
72
  }
90
73
  /**
91
74
  * Finds the index of the largest leaf whose value is less than or equal to the provided value.
92
- * @param newValue - The new value to be inserted into the tree.
75
+ * @param newKey - The new key to be inserted into the tree.
93
76
  * @param includeUncommitted - If true, the uncommitted changes are included in the search.
94
77
  * @returns The found leaf index and a flag indicating if the corresponding leaf's value is equal to `newValue`.
95
78
  */
96
- findIndexOfPreviousValue(newValue, includeUncommitted) {
97
- const numLeaves = this.getNumLeaves(includeUncommitted);
98
- const diff = [];
99
- for (let i = 0; i < numLeaves; i++) {
100
- const storedLeaf = this.getLatestLeafDataCopy(i, includeUncommitted);
101
- // The stored leaf can be undefined if it addresses an empty leaf
102
- // If the leaf is empty we do the same as if the leaf was larger
103
- if (storedLeaf === undefined) {
104
- diff.push(newValue);
105
- }
106
- else if (storedLeaf.value > newValue) {
107
- diff.push(newValue);
108
- }
109
- else if (storedLeaf.value === newValue) {
110
- return { index: i, alreadyPresent: true };
111
- }
112
- else {
113
- diff.push(newValue - storedLeaf.value);
79
+ async findIndexOfPreviousKey(newKey, includeUncommitted) {
80
+ let lowLeafIndex = await this.getDbLowLeafIndex(newKey);
81
+ let lowLeafPreimage = lowLeafIndex !== undefined ? await this.getDbPreimage(lowLeafIndex) : undefined;
82
+ if (includeUncommitted) {
83
+ const cachedLowLeafIndex = this.getCachedLowLeafIndex(newKey);
84
+ if (cachedLowLeafIndex !== undefined) {
85
+ const cachedLowLeafPreimage = this.getCachedPreimage(cachedLowLeafIndex);
86
+ if (!lowLeafPreimage || cachedLowLeafPreimage.getKey() > lowLeafPreimage.getKey()) {
87
+ lowLeafIndex = cachedLowLeafIndex;
88
+ lowLeafPreimage = cachedLowLeafPreimage;
89
+ }
114
90
  }
115
91
  }
116
- const minIndex = this.findMinIndex(diff);
117
- return { index: minIndex, alreadyPresent: false };
92
+ if (lowLeafIndex === undefined || !lowLeafPreimage) {
93
+ return undefined;
94
+ }
95
+ return {
96
+ index: lowLeafIndex,
97
+ alreadyPresent: lowLeafPreimage.getKey() === newKey,
98
+ };
99
+ }
100
+ getCachedLowLeafIndex(key) {
101
+ const indexes = Object.getOwnPropertyNames(this.cachedLeafPreimages);
102
+ const lowLeafIndexes = indexes
103
+ .map(index => ({
104
+ index: BigInt(index),
105
+ key: this.cachedLeafPreimages[index].getKey(),
106
+ }))
107
+ .filter(({ key: candidateKey }) => candidateKey <= key)
108
+ .sort((a, b) => Number(b.key - a.key));
109
+ return lowLeafIndexes[0]?.index;
110
+ }
111
+ getCachedLeafIndex(key) {
112
+ const index = Object.keys(this.cachedLeafPreimages).find(index => {
113
+ return this.cachedLeafPreimages[index].getKey() === key;
114
+ });
115
+ if (index) {
116
+ return BigInt(index);
117
+ }
118
+ return undefined;
119
+ }
120
+ async getDbLowLeafIndex(key) {
121
+ return await new Promise((resolve, reject) => {
122
+ let lowLeafIndex;
123
+ this.db
124
+ .createReadStream({
125
+ gte: buildDbKeyForLeafIndex(this.getName(), 0n),
126
+ lte: buildDbKeyForLeafIndex(this.getName(), key),
127
+ limit: 1,
128
+ reverse: true,
129
+ })
130
+ .on('data', data => {
131
+ lowLeafIndex = toBigIntBE(data.value);
132
+ })
133
+ .on('close', function () { })
134
+ .on('end', function () {
135
+ resolve(lowLeafIndex);
136
+ })
137
+ .on('error', function () {
138
+ log.error('stream error');
139
+ reject();
140
+ });
141
+ });
142
+ }
143
+ async getDbPreimage(index) {
144
+ const dbPreimage = await this.db
145
+ .get(buildDbKeyForPreimage(this.getName(), index))
146
+ .then(data => this.leafPreimageFactory.fromBuffer(data))
147
+ .catch(() => undefined);
148
+ return dbPreimage;
149
+ }
150
+ getCachedPreimage(index) {
151
+ return this.cachedLeafPreimages[index.toString()];
118
152
  }
119
153
  /**
120
- * Gets the latest LeafData copy.
121
- * @param index - Index of the leaf of which to obtain the LeafData copy.
154
+ * Gets the latest LeafPreimage copy.
155
+ * @param index - Index of the leaf of which to obtain the LeafPreimage copy.
122
156
  * @param includeUncommitted - If true, the uncommitted changes are included in the search.
123
- * @returns A copy of the leaf data at the given index or undefined if the leaf was not found.
157
+ * @returns A copy of the leaf preimage at the given index or undefined if the leaf was not found.
124
158
  */
125
- getLatestLeafDataCopy(index, includeUncommitted) {
126
- const leaf = !includeUncommitted ? this.leaves[index] : this.cachedLeaves[index] ?? this.leaves[index];
127
- return leaf
128
- ? {
129
- value: leaf.value,
130
- nextIndex: leaf.nextIndex,
131
- nextValue: leaf.nextValue,
132
- }
133
- : undefined;
159
+ async getLatestLeafPreimageCopy(index, includeUncommitted) {
160
+ const preimage = !includeUncommitted
161
+ ? await this.getDbPreimage(index)
162
+ : this.getCachedPreimage(index) ?? (await this.getDbPreimage(index));
163
+ return preimage && this.leafPreimageFactory.clone(preimage);
134
164
  }
135
165
  /**
136
- * Finds the index of the minimum value in an array.
137
- * @param values - The collection of values to be searched.
138
- * @returns The index of the minimum value in the array.
166
+ * Returns the index of a leaf given its value, or undefined if no leaf with that value is found.
167
+ * @param value - The leaf value to look for.
168
+ * @param includeUncommitted - Indicates whether to include uncommitted data.
169
+ * @returns The index of the first leaf found with a given value (undefined if not found).
139
170
  */
140
- findMinIndex(values) {
141
- if (!values.length) {
142
- return 0;
143
- }
144
- let minIndex = 0;
145
- for (let i = 1; i < values.length; i++) {
146
- if (values[minIndex] > values[i]) {
147
- minIndex = i;
148
- }
171
+ async findLeafIndex(value, includeUncommitted) {
172
+ const leaf = this.leafFactory.fromBuffer(value);
173
+ let index = await this.db
174
+ .get(buildDbKeyForLeafIndex(this.getName(), leaf.getKey()))
175
+ .then(data => toBigIntBE(data))
176
+ .catch(() => undefined);
177
+ if (includeUncommitted && index === undefined) {
178
+ const cachedIndex = this.getCachedLeafIndex(leaf.getKey());
179
+ index = cachedIndex;
149
180
  }
150
- return minIndex;
181
+ return index;
151
182
  }
152
183
  /**
153
184
  * Initializes the tree.
@@ -169,59 +200,26 @@ export class StandardIndexedTree extends TreeBase {
169
200
  }
170
201
  const leaves = [];
171
202
  for (let i = 0n; i < prefilledSize; i++) {
172
- const newLeaf = {
173
- value: toBigIntBE(Buffer.from([Number(i)])),
174
- nextIndex: i + 1n,
175
- nextValue: i + 1n,
176
- };
177
- leaves.push(newLeaf);
203
+ const newLeaf = this.leafFactory.buildDummy(i);
204
+ const newLeafPreimage = this.leafPreimageFactory.fromLeaf(newLeaf, i + 1n, i + 1n);
205
+ leaves.push(newLeafPreimage);
178
206
  }
179
- // Make the first leaf have 0 value
180
- leaves[0].value = 0n;
181
207
  // Make the last leaf point to the first leaf
182
- leaves[prefilledSize - 1].nextIndex = 0n;
183
- leaves[prefilledSize - 1].nextValue = 0n;
208
+ leaves[prefilledSize - 1] = this.leafPreimageFactory.fromLeaf(leaves[prefilledSize - 1].asLeaf(), 0n, 0n);
184
209
  await this.encodeAndAppendLeaves(leaves, true);
185
210
  await this.commit();
186
211
  }
187
- /**
188
- * Loads Merkle tree data from a database and assigns them to this object.
189
- */
190
- async initFromDb() {
191
- const startingIndex = 0n;
192
- const values = [];
193
- const promise = new Promise((resolve, reject) => {
194
- this.db
195
- .createReadStream({
196
- gte: indexToKeyLeaf(this.getName(), startingIndex),
197
- lte: indexToKeyLeaf(this.getName(), 2n ** BigInt(this.getDepth())),
198
- })
199
- .on('data', function (data) {
200
- const index = Number(data.key);
201
- values[index] = decodeTreeValue(data.value);
202
- })
203
- .on('close', function () { })
204
- .on('end', function () {
205
- resolve();
206
- })
207
- .on('error', function () {
208
- log.error('stream error');
209
- reject();
210
- });
211
- });
212
- await promise;
213
- this.leaves = values;
214
- }
215
212
  /**
216
213
  * Commits all the leaves to the database and removes them from a cache.
217
214
  */
218
215
  async commitLeaves() {
219
216
  const batch = this.db.batch();
220
- const keys = Object.getOwnPropertyNames(this.cachedLeaves);
217
+ const keys = Object.getOwnPropertyNames(this.cachedLeafPreimages);
221
218
  for (const key of keys) {
222
- const index = Number(key);
223
- batch.put(key, this.cachedLeaves[index]);
224
- this.leaves[index] = this.cachedLeaves[index];
219
+ const leaf = this.cachedLeafPreimages[key];
220
+ const index = BigInt(key);
221
+ batch.put(buildDbKeyForPreimage(this.getName(), index), leaf.toBuffer());
222
+ batch.put(buildDbKeyForLeafIndex(this.getName(), leaf.getKey()), toBufferBE(index, 32));
225
223
  }
226
224
  await batch.write();
227
225
  this.clearCachedLeaves();
@@ -230,18 +228,19 @@ export class StandardIndexedTree extends TreeBase {
230
228
  * Clears the cache.
231
229
  */
232
230
  clearCachedLeaves() {
233
- this.cachedLeaves = {};
231
+ this.cachedLeafPreimages = {};
234
232
  }
235
233
  /**
236
234
  * Updates a leaf in the tree.
237
- * @param leaf - New contents of the leaf.
235
+ * @param preimage - New contents of the leaf.
238
236
  * @param index - Index of the leaf to be updated.
239
237
  */
240
- async updateLeaf(leaf, index) {
238
+ async updateLeaf(preimage, index) {
241
239
  if (index > this.maxIndex) {
242
240
  throw Error(`Index out of bounds. Index ${index}, max index: ${this.maxIndex}.`);
243
241
  }
244
- const encodedLeaf = this.encodeLeaf(leaf, true);
242
+ this.cachedLeafPreimages[index.toString()] = preimage;
243
+ const encodedLeaf = this.encodeLeaf(preimage, true);
245
244
  await this.addLeafToCacheAndHashToRoot(encodedLeaf, index);
246
245
  const numLeaves = this.getNumLeaves(true);
247
246
  if (index >= numLeaves) {
@@ -258,8 +257,6 @@ export class StandardIndexedTree extends TreeBase {
258
257
  *
259
258
  * This offers massive circuit performance savings over doing incremental insertions.
260
259
  *
261
- * A description of the algorithm can be found here: https://colab.research.google.com/drive/1A0gizduSi4FIiIJZ8OylwIpO9-OTqV-R
262
- *
263
260
  * WARNING: This function has side effects, it will insert values into the tree.
264
261
  *
265
262
  * Assumptions:
@@ -279,81 +276,78 @@ export class StandardIndexedTree extends TreeBase {
279
276
  * roots.
280
277
  *
281
278
  * This become tricky when two items that are being batch inserted need to update the same low nullifier, or need to use
282
- * a value that is part of the same batch insertion as their low nullifier. In this case a zero low nullifier path is given
283
- * to the circuit, and it must determine from the set of batch inserted values if the insertion is valid.
279
+ * a value that is part of the same batch insertion as their low nullifier. What we do to avoid this case is to
280
+ * update the existing leaves in the tree with the nullifiers in high to low order, ensuring that this case never occurs.
281
+ * The circuit has to sort the nullifiers (or take a hint of the sorted nullifiers and prove that it's a valid permutation).
282
+ * Then we just batch insert the new nullifiers in the original order.
284
283
  *
285
284
  * The following example will illustrate attempting to insert 2,3,20,19 into a tree already containing 0,5,10,15
286
285
  *
287
286
  * The example will explore two cases. In each case the values low nullifier will exist within the batch insertion,
288
287
  * One where the low nullifier comes before the item in the set (2,3), and one where it comes after (20,19).
289
288
  *
289
+ * First, we sort the nullifiers high to low, that's 20,19,3,2
290
+ *
290
291
  * The original tree: Pending insertion subtree
291
292
  *
292
- * index 0 2 3 4 - - - -
293
+ * index 0 1 2 3 - - - -
293
294
  * ------------------------------------- ----------------------------
294
295
  * val 0 5 10 15 - - - -
295
296
  * nextIdx 1 2 3 0 - - - -
296
297
  * nextVal 5 10 15 0 - - - -
297
298
  *
298
299
  *
299
- * Inserting 2: (happy path)
300
- * 1. Find the low nullifier (0) - provide inclusion proof
300
+ * Inserting 20:
301
+ * 1. Find the low nullifier (3) - provide inclusion proof
301
302
  * 2. Update its pointers
302
- * 3. Insert 2 into the pending subtree
303
+ * 3. Insert 20 into the pending subtree
303
304
  *
304
- * index 0 2 3 4 5 - - -
305
+ * index 0 1 2 3 - - 6 -
305
306
  * ------------------------------------- ----------------------------
306
- * val 0 5 10 15 2 - - -
307
- * nextIdx 5 2 3 0 2 - - -
308
- * nextVal 2 10 15 0 5 - - -
307
+ * val 0 5 10 15 - - 20 -
308
+ * nextIdx 1 2 3 6 - - 0 -
309
+ * nextVal 5 10 15 20 - - 0 -
309
310
  *
310
- * Inserting 3: The low nullifier exists within the insertion current subtree
311
- * 1. When looking for the low nullifier for 3, we will receive 0 again as we have not inserted 2 into the main tree
312
- * This is problematic, as we cannot use either 0 or 2 as our inclusion proof.
313
- * Why cant we?
314
- * - Index 0 has a val 0 and nextVal of 2. This is NOT enough to prove non inclusion of 2.
315
- * - Our existing tree is in a state where we cannot prove non inclusion of 3.
316
- * We do not provide a non inclusion proof to out circuit, but prompt it to look within the insertion subtree.
317
- * 2. Update pending insertion subtree
318
- * 3. Insert 3 into pending subtree
311
+ * Inserting 19:
312
+ * 1. Find the low nullifier (3) - provide inclusion proof
313
+ * 2. Update its pointers
314
+ * 3. Insert 19 into the pending subtree
319
315
  *
320
- * (no inclusion proof provided)
321
- * index 0 2 3 4 5 6 - -
316
+ * index 0 1 2 3 - - 6 7
322
317
  * ------------------------------------- ----------------------------
323
- * val 0 5 10 15 2 3 - -
324
- * nextIdx 5 2 3 0 6 2 - -
325
- * nextVal 2 10 15 0 3 5 - -
318
+ * val 0 5 10 15 - - 20 19
319
+ * nextIdx 1 2 3 7 - - 0 6
320
+ * nextVal 5 10 15 19 - - 0 20
326
321
  *
327
- * Inserting 20: (happy path)
328
- * 1. Find the low nullifier (15) - provide inclusion proof
322
+ * Inserting 3:
323
+ * 1. Find the low nullifier (0) - provide inclusion proof
329
324
  * 2. Update its pointers
330
- * 3. Insert 20 into the pending subtree
325
+ * 3. Insert 3 into the pending subtree
331
326
  *
332
- * index 0 2 3 4 5 6 7 -
327
+ * index 0 1 2 3 - 5 6 7
333
328
  * ------------------------------------- ----------------------------
334
- * val 0 5 10 15 2 3 20 -
335
- * nextIdx 5 2 3 7 6 2 0 -
336
- * nextVal 2 10 15 20 3 5 0 -
329
+ * val 0 5 10 15 - 3 20 19
330
+ * nextIdx 5 2 3 7 - 1 0 6
331
+ * nextVal 3 10 15 19 - 5 0 20
337
332
  *
338
- * Inserting 19:
339
- * 1. In this case we can find a low nullifier, but we are updating a low nullifier that has already been updated
340
- * We can provide an inclusion proof of this intermediate tree state.
333
+ * Inserting 2:
334
+ * 1. Find the low nullifier (0) - provide inclusion proof
341
335
  * 2. Update its pointers
342
- * 3. Insert 19 into the pending subtree
336
+ * 3. Insert 2 into the pending subtree
343
337
  *
344
- * index 0 2 3 4 5 6 7 8
338
+ * index 0 1 2 3 4 5 6 7
345
339
  * ------------------------------------- ----------------------------
346
- * val 0 5 10 15 2 3 20 19
347
- * nextIdx 5 2 3 8 6 2 0 7
348
- * nextVal 2 10 15 19 3 5 0 20
340
+ * val 0 5 10 15 2 3 20 19
341
+ * nextIdx 4 2 3 7 5 1 0 6
342
+ * nextVal 2 10 15 19 3 5 0 20
349
343
  *
350
344
  * Perform subtree insertion
351
345
  *
352
- * index 0 2 3 4 5 6 7 8
346
+ * index 0 1 2 3 4 5 6 7
353
347
  * ---------------------------------------------------------------------
354
- * val 0 5 10 15 2 3 20 19
355
- * nextIdx 5 2 3 8 6 2 0 7
356
- * nextVal 2 10 15 19 3 5 0 20
348
+ * val 0 5 10 15 2 3 20 19
349
+ * nextIdx 4 2 3 7 5 1 0 6
350
+ * nextVal 2 10 15 19 3 5 0 20
357
351
  *
358
352
  * TODO: this implementation will change once the zero value is changed from h(0,0,0). Changes incoming over the next sprint
359
353
  * @param leaves - Values to insert into the tree.
@@ -361,92 +355,61 @@ export class StandardIndexedTree extends TreeBase {
361
355
  * @returns The data for the leaves to be updated when inserting the new ones.
362
356
  */
363
357
  async batchInsert(leaves, subtreeHeight) {
364
- // Keep track of touched low leaves
365
- const touched = new Map();
366
- const emptyLowLeafWitness = getEmptyLowLeafWitness(this.getDepth());
358
+ const emptyLowLeafWitness = getEmptyLowLeafWitness(this.getDepth(), this.leafPreimageFactory);
367
359
  // Accumulators
368
- const lowLeavesWitnesses = [];
369
- const pendingInsertionSubtree = [];
360
+ const lowLeavesWitnesses = leaves.map(() => emptyLowLeafWitness);
361
+ const pendingInsertionSubtree = leaves.map(() => this.leafPreimageFactory.empty());
370
362
  // Start info
371
363
  const startInsertionIndex = this.getNumLeaves(true);
364
+ const leavesToInsert = leaves.map(leaf => this.leafFactory.fromBuffer(leaf));
365
+ const sortedDescendingLeafTuples = leavesToInsert
366
+ .map((leaf, index) => ({ leaf, index }))
367
+ .sort((a, b) => Number(b.leaf.getKey() - a.leaf.getKey()));
368
+ const sortedDescendingLeaves = sortedDescendingLeafTuples.map(leafTuple => leafTuple.leaf);
372
369
  // Get insertion path for each leaf
373
- for (let i = 0; i < leaves.length; i++) {
374
- const newValue = toBigIntBE(leaves[i]);
375
- // Keep space and just insert zero values
376
- if (newValue === 0n) {
377
- pendingInsertionSubtree.push(zeroLeaf);
378
- lowLeavesWitnesses.push(emptyLowLeafWitness);
370
+ for (let i = 0; i < leavesToInsert.length; i++) {
371
+ const newLeaf = sortedDescendingLeaves[i];
372
+ const originalIndex = leavesToInsert.indexOf(newLeaf);
373
+ if (newLeaf.isEmpty()) {
379
374
  continue;
380
375
  }
381
- const indexOfPrevious = this.findIndexOfPreviousValue(newValue, true);
382
- // If a touched node has a value that is less than the current value
383
- const prevNodes = touched.get(indexOfPrevious.index);
384
- if (prevNodes && prevNodes.some(v => v < newValue)) {
385
- // check the pending low nullifiers for a low nullifier that works
386
- // This is the case where the next value is less than the pending
387
- for (let j = 0; j < pendingInsertionSubtree.length; j++) {
388
- if (pendingInsertionSubtree[j].value === 0n) {
389
- continue;
390
- }
391
- if (pendingInsertionSubtree[j].value < newValue &&
392
- (pendingInsertionSubtree[j].nextValue > newValue || pendingInsertionSubtree[j].nextValue === 0n)) {
393
- // add the new value to the pending low nullifiers
394
- const currentLowLeaf = {
395
- value: newValue,
396
- nextValue: pendingInsertionSubtree[j].nextValue,
397
- nextIndex: pendingInsertionSubtree[j].nextIndex,
398
- };
399
- pendingInsertionSubtree.push(currentLowLeaf);
400
- // Update the pending low leaf to point at the new value
401
- pendingInsertionSubtree[j].nextValue = newValue;
402
- pendingInsertionSubtree[j].nextIndex = startInsertionIndex + BigInt(i);
403
- break;
404
- }
405
- }
406
- // Any node updated in this space will need to calculate its low nullifier from a previously inserted value
407
- lowLeavesWitnesses.push(emptyLowLeafWitness);
408
- }
409
- else {
410
- // Update the touched mapping
411
- if (prevNodes) {
412
- prevNodes.push(newValue);
413
- touched.set(indexOfPrevious.index, prevNodes);
414
- }
415
- else {
416
- touched.set(indexOfPrevious.index, [newValue]);
417
- }
418
- // get the low leaf
419
- const lowLeaf = this.getLatestLeafDataCopy(indexOfPrevious.index, true);
420
- if (lowLeaf === undefined) {
421
- return [undefined, await this.getSubtreeSiblingPath(subtreeHeight, true)];
422
- }
423
- const siblingPath = await this.getSiblingPath(BigInt(indexOfPrevious.index), true);
424
- const witness = {
425
- leafData: { ...lowLeaf },
426
- index: BigInt(indexOfPrevious.index),
427
- siblingPath,
428
- };
429
- // Update the running paths
430
- lowLeavesWitnesses.push(witness);
431
- const currentLowLeaf = {
432
- value: newValue,
433
- nextValue: lowLeaf.nextValue,
434
- nextIndex: lowLeaf.nextIndex,
376
+ const indexOfPrevious = await this.findIndexOfPreviousKey(newLeaf.getKey(), true);
377
+ if (indexOfPrevious === undefined) {
378
+ return {
379
+ lowLeavesWitnessData: undefined,
380
+ sortedNewLeaves: sortedDescendingLeafTuples.map(leafTuple => leafTuple.leaf.toBuffer()),
381
+ sortedNewLeavesIndexes: sortedDescendingLeafTuples.map(leafTuple => leafTuple.index),
382
+ newSubtreeSiblingPath: await this.getSubtreeSiblingPath(subtreeHeight, true),
435
383
  };
436
- pendingInsertionSubtree.push(currentLowLeaf);
437
- lowLeaf.nextValue = newValue;
438
- lowLeaf.nextIndex = startInsertionIndex + BigInt(i);
439
- const lowLeafIndex = indexOfPrevious.index;
440
- this.cachedLeaves[lowLeafIndex] = lowLeaf;
441
- await this.updateLeaf(lowLeaf, BigInt(lowLeafIndex));
442
384
  }
385
+ // get the low leaf (existence checked in getting index)
386
+ const lowLeafPreimage = (await this.getLatestLeafPreimageCopy(indexOfPrevious.index, true));
387
+ const siblingPath = await this.getSiblingPath(BigInt(indexOfPrevious.index), true);
388
+ const witness = {
389
+ leafPreimage: lowLeafPreimage,
390
+ index: BigInt(indexOfPrevious.index),
391
+ siblingPath,
392
+ };
393
+ // Update the running paths
394
+ lowLeavesWitnesses[i] = witness;
395
+ const currentPendingPreimageLeaf = this.leafPreimageFactory.fromLeaf(newLeaf, lowLeafPreimage.getNextKey(), lowLeafPreimage.getNextIndex());
396
+ pendingInsertionSubtree[originalIndex] = currentPendingPreimageLeaf;
397
+ const newLowLeafPreimage = this.leafPreimageFactory.fromLeaf(lowLeafPreimage.asLeaf(), newLeaf.getKey(), startInsertionIndex + BigInt(originalIndex));
398
+ const lowLeafIndex = indexOfPrevious.index;
399
+ this.cachedLeafPreimages[lowLeafIndex.toString()] = newLowLeafPreimage;
400
+ await this.updateLeaf(newLowLeafPreimage, lowLeafIndex);
443
401
  }
444
402
  const newSubtreeSiblingPath = await this.getSubtreeSiblingPath(subtreeHeight, true);
445
403
  // Perform batch insertion of new pending values
446
404
  // Note: In this case we set `hash0Leaf` param to false because batch insertion algorithm use forced null leaf
447
405
  // inclusion. See {@link encodeLeaf} for a more through param explanation.
448
406
  await this.encodeAndAppendLeaves(pendingInsertionSubtree, false);
449
- return [lowLeavesWitnesses, newSubtreeSiblingPath];
407
+ return {
408
+ lowLeavesWitnessData: lowLeavesWitnesses,
409
+ sortedNewLeaves: sortedDescendingLeafTuples.map(leafTuple => leafTuple.leaf.toBuffer()),
410
+ sortedNewLeavesIndexes: sortedDescendingLeafTuples.map(leafTuple => leafTuple.index),
411
+ newSubtreeSiblingPath,
412
+ };
450
413
  }
451
414
  async getSubtreeSiblingPath(subtreeHeight, includeUncommitted) {
452
415
  const nextAvailableLeafIndex = this.getNumLeaves(includeUncommitted);
@@ -454,19 +417,25 @@ export class StandardIndexedTree extends TreeBase {
454
417
  // Drop the first subtreeHeight items since we only care about the path to the subtree root
455
418
  return fullSiblingPath.getSubtreeSiblingPath(subtreeHeight);
456
419
  }
420
+ snapshot(blockNumber) {
421
+ return __classPrivateFieldGet(this, _StandardIndexedTree_snapshotBuilder, "f").snapshot(blockNumber);
422
+ }
423
+ getSnapshot(block) {
424
+ return __classPrivateFieldGet(this, _StandardIndexedTree_snapshotBuilder, "f").getSnapshot(block);
425
+ }
457
426
  /**
458
427
  * Encodes leaves and appends them to a tree.
459
- * @param leaves - Leaves to encode.
428
+ * @param preimages - Leaves to encode.
460
429
  * @param hash0Leaf - Indicates whether 0 value leaf should be hashed. See {@link encodeLeaf}.
461
430
  * @returns Empty promise
462
431
  */
463
- async encodeAndAppendLeaves(leaves, hash0Leaf) {
464
- const startInsertionIndex = Number(this.getNumLeaves(true));
465
- const serializedLeaves = leaves.map((leaf, i) => {
466
- this.cachedLeaves[startInsertionIndex + i] = leaf;
467
- return this.encodeLeaf(leaf, hash0Leaf);
432
+ async encodeAndAppendLeaves(preimages, hash0Leaf) {
433
+ const startInsertionIndex = this.getNumLeaves(true);
434
+ const hashedLeaves = preimages.map((preimage, i) => {
435
+ this.cachedLeafPreimages[(startInsertionIndex + BigInt(i)).toString()] = preimage;
436
+ return this.encodeLeaf(preimage, hash0Leaf);
468
437
  });
469
- await super.appendLeaves(serializedLeaves);
438
+ await super.appendLeaves(hashedLeaves);
470
439
  }
471
440
  /**
472
441
  * Encode a leaf into a buffer.
@@ -478,13 +447,14 @@ export class StandardIndexedTree extends TreeBase {
478
447
  */
479
448
  encodeLeaf(leaf, hash0Leaf) {
480
449
  let encodedLeaf;
481
- if (!hash0Leaf && leaf.value == 0n) {
450
+ if (!hash0Leaf && leaf.getKey() == 0n) {
482
451
  encodedLeaf = toBufferBE(0n, 32);
483
452
  }
484
453
  else {
485
- encodedLeaf = this.hasher.hashInputs([leaf.value, leaf.nextIndex, leaf.nextValue].map(val => toBufferBE(val, 32)));
454
+ encodedLeaf = this.hasher.hashInputs(leaf.toHashInputs());
486
455
  }
487
456
  return encodedLeaf;
488
457
  }
489
458
  }
490
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhbmRhcmRfaW5kZXhlZF90cmVlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0YW5kYXJkX2luZGV4ZWRfdHJlZS9zdGFuZGFyZF9pbmRleGVkX3RyZWUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUN6RSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRzNDLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUUzQyxNQUFNLEdBQUcsR0FBRyxpQkFBaUIsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO0FBRTdELE1BQU0sY0FBYyxHQUFHLENBQUMsSUFBWSxFQUFFLEtBQWEsRUFBRSxFQUFFO0lBQ3JELE9BQU8sR0FBRyxJQUFJLFNBQVMsS0FBSyxFQUFFLENBQUM7QUFDakMsQ0FBQyxDQUFDO0FBRUYsTUFBTSxRQUFRLEdBQWE7SUFDekIsS0FBSyxFQUFFLEVBQUU7SUFDVCxTQUFTLEVBQUUsRUFBRTtJQUNiLFNBQVMsRUFBRSxFQUFFO0NBQ2QsQ0FBQztBQW9CRjs7OztHQUlHO0FBQ0gsU0FBUyxzQkFBc0IsQ0FBbUIsVUFBYTtJQUM3RCxPQUFPO1FBQ0wsUUFBUSxFQUFFLFFBQVE7UUFDbEIsS0FBSyxFQUFFLEVBQUU7UUFDVCxXQUFXLEVBQUUsSUFBSSxXQUFXLENBQUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsNkRBQTZEO0FBQzdELE1BQU0sZUFBZSxHQUFHLENBQUMsUUFBa0IsRUFBRSxFQUFFO0lBQzdDLE1BQU0sYUFBYSxHQUFHLFVBQVUsQ0FB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
459
+ _StandardIndexedTree_snapshotBuilder = new WeakMap();
460
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhbmRhcmRfaW5kZXhlZF90cmVlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0YW5kYXJkX2luZGV4ZWRfdHJlZS9zdGFuZGFyZF9pbmRleGVkX3RyZWUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRTFELE9BQU8sRUFBVSxXQUFXLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFJbkQsT0FBTyxFQUlMLDBCQUEwQixHQUUzQixNQUFNLGFBQWEsQ0FBQztBQUNyQixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFM0MsTUFBTSxHQUFHLEdBQUcsaUJBQWlCLENBQUMsNkJBQTZCLENBQUMsQ0FBQztBQTZDN0QsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxJQUFZLEVBQUUsS0FBYSxFQUFFLEVBQUU7SUFDbkUsT0FBTyxHQUFHLElBQUksa0JBQWtCLFVBQVUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7QUFDMUUsQ0FBQyxDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUcsQ0FBQyxJQUFZLEVBQUUsR0FBVyxFQUFFLEVBQUU7SUFDbEUsT0FBTyxHQUFHLElBQUksMkJBQTJCLFVBQVUsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7QUFDakYsQ0FBQyxDQUFDO0FBRUY7Ozs7R0FJRztBQUNILFNBQVMsc0JBQXNCLENBQzdCLFVBQWEsRUFDYixtQkFBb0M7SUFFcEMsT0FBTztRQUNMLFlBQVksRUFBRSxtQkFBbUIsQ0FBQyxLQUFLLEVBQUU7UUFDekMsS0FBSyxFQUFFLEVBQUU7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