@aztec/merkle-tree 0.16.1 → 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 -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,6 +1,4 @@
1
- import { toBigIntBE } from '@aztec/foundation/bigint-buffer';
2
-
3
- import { LeafData, StandardIndexedTree } from '../../index.js';
1
+ import { StandardIndexedTree } from '../../index.js';
4
2
 
5
3
  /**
6
4
  * A testing utility which is here to store the original implementation of StandardIndexedTree.appendLeaves method
@@ -26,10 +24,10 @@ export class StandardIndexedTreeWithAppend extends StandardIndexedTree {
26
24
  * @returns Empty promise.
27
25
  */
28
26
  private async appendLeaf(leaf: Buffer): Promise<void> {
29
- const newValue = toBigIntBE(leaf);
27
+ const newLeaf = this.leafFactory.fromBuffer(leaf);
30
28
 
31
29
  // Special case when appending zero
32
- if (newValue === 0n) {
30
+ if (newLeaf.getKey() === 0n) {
33
31
  const newSize = (this.cachedSize ?? this.size) + 1n;
34
32
  if (newSize - 1n > this.maxIndex) {
35
33
  throw Error(`Can't append beyond max index. Max index: ${this.maxIndex}`);
@@ -38,27 +36,31 @@ export class StandardIndexedTreeWithAppend extends StandardIndexedTree {
38
36
  return;
39
37
  }
40
38
 
41
- const indexOfPrevious = this.findIndexOfPreviousValue(newValue, true);
42
- const previousLeafCopy = this.getLatestLeafDataCopy(indexOfPrevious.index, true);
43
-
44
- if (previousLeafCopy === undefined) {
39
+ const lowLeafIndex = await this.findIndexOfPreviousKey(newLeaf.getKey(), true);
40
+ if (lowLeafIndex === undefined) {
45
41
  throw new Error(`Previous leaf not found!`);
46
42
  }
47
- const newLeaf = {
48
- value: newValue,
49
- nextIndex: previousLeafCopy.nextIndex,
50
- nextValue: previousLeafCopy.nextValue,
51
- } as LeafData;
52
- if (indexOfPrevious.alreadyPresent) {
43
+ const lowLeafPreimage = (await this.getLatestLeafPreimageCopy(lowLeafIndex.index, true))!;
44
+
45
+ const newLeafPreimage = this.leafPreimageFactory.fromLeaf(
46
+ newLeaf,
47
+ lowLeafPreimage.getNextKey(),
48
+ lowLeafPreimage.getNextIndex(),
49
+ );
50
+
51
+ if (lowLeafIndex.alreadyPresent) {
53
52
  return;
54
53
  }
55
54
  // insert a new leaf at the highest index and update the values of our previous leaf copy
56
55
  const currentSize = this.getNumLeaves(true);
57
- previousLeafCopy.nextIndex = BigInt(currentSize);
58
- previousLeafCopy.nextValue = newLeaf.value;
59
- this.cachedLeaves[Number(currentSize)] = newLeaf;
60
- this.cachedLeaves[Number(indexOfPrevious.index)] = previousLeafCopy;
61
- await this.updateLeaf(previousLeafCopy, BigInt(indexOfPrevious.index));
62
- await this.updateLeaf(newLeaf, this.getNumLeaves(true));
56
+ const newLowLeafPreimage = this.leafPreimageFactory.fromLeaf(
57
+ lowLeafPreimage.asLeaf(),
58
+ newLeaf.getKey(),
59
+ BigInt(currentSize),
60
+ );
61
+ this.cachedLeafPreimages[Number(currentSize)] = newLeafPreimage;
62
+ this.cachedLeafPreimages[Number(lowLeafIndex.index)] = newLowLeafPreimage;
63
+ await this.updateLeaf(newLowLeafPreimage, BigInt(lowLeafIndex.index));
64
+ await this.updateLeaf(newLeafPreimage, this.getNumLeaves(true));
63
65
  }
64
66
  }
@@ -1,3 +1,4 @@
1
+ import { AppendOnlySnapshotBuilder, TreeSnapshot } from '../index.js';
1
2
  import { AppendOnlyTree } from '../interfaces/append_only_tree.js';
2
3
  import { TreeBase } from '../tree_base.js';
3
4
 
@@ -5,6 +6,8 @@ import { TreeBase } from '../tree_base.js';
5
6
  * A Merkle tree implementation that uses a LevelDB database to store the tree.
6
7
  */
7
8
  export class StandardTree extends TreeBase implements AppendOnlyTree {
9
+ #snapshotBuilder = new AppendOnlySnapshotBuilder(this.db, this, this.hasher);
10
+
8
11
  /**
9
12
  * Appends the given leaves to the tree.
10
13
  * @param leaves - The leaves to append.
@@ -13,4 +16,22 @@ export class StandardTree extends TreeBase implements AppendOnlyTree {
13
16
  public async appendLeaves(leaves: Buffer[]): Promise<void> {
14
17
  await super.appendLeaves(leaves);
15
18
  }
19
+
20
+ public snapshot(block: number): Promise<TreeSnapshot> {
21
+ return this.#snapshotBuilder.snapshot(block);
22
+ }
23
+
24
+ public getSnapshot(block: number): Promise<TreeSnapshot> {
25
+ return this.#snapshotBuilder.getSnapshot(block);
26
+ }
27
+
28
+ public async findLeafIndex(value: Buffer, includeUncommitted: boolean): Promise<bigint | undefined> {
29
+ for (let i = 0n; i < this.getNumLeaves(includeUncommitted); i++) {
30
+ const currentValue = await this.getLeafValue(i, includeUncommitted);
31
+ if (currentValue && currentValue.equals(value)) {
32
+ return i;
33
+ }
34
+ }
35
+ return undefined;
36
+ }
16
37
  }
package/src/tree_base.ts CHANGED
@@ -150,6 +150,26 @@ export abstract class TreeBase implements MerkleTree {
150
150
  return this.getLatestValueAtIndex(this.depth, index, includeUncommitted);
151
151
  }
152
152
 
153
+ public getNode(level: number, index: bigint): Promise<Buffer | undefined> {
154
+ if (level < 0 || level > this.depth) {
155
+ throw Error('Invalid level: ' + level);
156
+ }
157
+
158
+ if (index < 0 || index >= 2n ** BigInt(level)) {
159
+ throw Error('Invalid index: ' + index);
160
+ }
161
+
162
+ return this.dbGet(indexToKeyHash(this.name, level, index));
163
+ }
164
+
165
+ public getZeroHash(level: number): Buffer {
166
+ if (level <= 0 || level > this.depth) {
167
+ throw new Error('Invalid level');
168
+ }
169
+
170
+ return this.zeroHashes[level - 1];
171
+ }
172
+
153
173
  /**
154
174
  * Clears the cache.
155
175
  */
@@ -221,13 +241,6 @@ export abstract class TreeBase implements MerkleTree {
221
241
  await this.writeMeta();
222
242
  }
223
243
 
224
- /**
225
- * Initializes the tree from the database.
226
- */
227
- public async initFromDb(): Promise<void> {
228
- // Implemented only by Indexed Tree to populate the leaf cache.
229
- }
230
-
231
244
  /**
232
245
  * Writes meta data to the provided batch.
233
246
  * @param batch - The batch to which to write the meta data.
@@ -287,4 +300,12 @@ export abstract class TreeBase implements MerkleTree {
287
300
  }
288
301
  this.cachedSize = numLeaves + BigInt(leaves.length);
289
302
  }
303
+
304
+ /**
305
+ * Returns the index of a leaf given its value, or undefined if no leaf with that value is found.
306
+ * @param value - The leaf value to look for.
307
+ * @param includeUncommitted - Indicates whether to include uncommitted data.
308
+ * @returns The index of the first leaf found with a given value (undefined if not found).
309
+ */
310
+ abstract findLeafIndex(value: Buffer, includeUncommitted: boolean): Promise<bigint | undefined>;
290
311
  }