@aztec/merkle-tree 0.16.1 → 0.16.3

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