@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
@@ -0,0 +1,179 @@
1
+ var _BaseFullTreeSnapshotBuilder_instances, _BaseFullTreeSnapshotBuilder_getSnapshotMeta, _BaseFullTreeSnapshot_instances, _BaseFullTreeSnapshot_getPathFromRoot;
2
+ import { __classPrivateFieldGet } from "tslib";
3
+ import { SiblingPath } from '@aztec/types';
4
+ // key for a node's children
5
+ const snapshotChildKey = (node, child) => Buffer.concat([Buffer.from('snapshot:node:'), node, Buffer.from(':' + child)]);
6
+ // metadata for a snapshot
7
+ const snapshotRootKey = (treeName, block) => `snapshot:root:${treeName}:${block}`;
8
+ const snapshotNumLeavesKey = (treeName, block) => `snapshot:numLeaves:${treeName}:${block}`;
9
+ /**
10
+ * Builds a full snapshot of a tree. This implementation works for any Merkle tree and stores
11
+ * it in a database in a similar way to how a tree is stored in memory, using pointers.
12
+ *
13
+ * Sharing the same database between versions and trees is recommended as the trees would share
14
+ * structure.
15
+ *
16
+ * Implement the protected method `handleLeaf` to store any additional data you need for each leaf.
17
+ *
18
+ * Complexity:
19
+ * N - count of non-zero nodes in tree
20
+ * M - count of snapshots
21
+ * H - tree height
22
+ * Worst case space complexity: O(N * M)
23
+ * Sibling path access: O(H) database reads
24
+ */
25
+ export class BaseFullTreeSnapshotBuilder {
26
+ constructor(db, tree) {
27
+ _BaseFullTreeSnapshotBuilder_instances.add(this);
28
+ this.db = db;
29
+ this.tree = tree;
30
+ }
31
+ async snapshot(block) {
32
+ const snapshotMetadata = await __classPrivateFieldGet(this, _BaseFullTreeSnapshotBuilder_instances, "m", _BaseFullTreeSnapshotBuilder_getSnapshotMeta).call(this, block);
33
+ if (snapshotMetadata) {
34
+ return this.openSnapshot(snapshotMetadata.root, snapshotMetadata.numLeaves);
35
+ }
36
+ const batch = this.db.batch();
37
+ const root = this.tree.getRoot(false);
38
+ const numLeaves = this.tree.getNumLeaves(false);
39
+ const depth = this.tree.getDepth();
40
+ const queue = [[root, 0, 0n]];
41
+ // walk the tree breadth-first and store each of its nodes in the database
42
+ // for each node we save two keys
43
+ // <node hash>:0 -> <left child's hash>
44
+ // <node hash>:1 -> <right child's hash>
45
+ while (queue.length > 0) {
46
+ const [node, level, i] = queue.shift();
47
+ // check if the database already has a child for this tree
48
+ // if it does, then we know we've seen the whole subtree below it before
49
+ // and we don't have to traverse it anymore
50
+ // we use the left child here, but it could be anything that shows we've stored the node before
51
+ const exists = await this.db.get(snapshotChildKey(node, 0)).catch(() => undefined);
52
+ if (exists) {
53
+ continue;
54
+ }
55
+ if (level + 1 > depth) {
56
+ // short circuit if we've reached the leaf level
57
+ // otherwise getNode might throw if we ask for the children of a leaf
58
+ await this.handleLeaf(i, node, batch);
59
+ continue;
60
+ }
61
+ const [lhs, rhs] = await Promise.all([
62
+ this.tree.getNode(level + 1, 2n * i),
63
+ this.tree.getNode(level + 1, 2n * i + 1n),
64
+ ]);
65
+ // we want the zero hash at the children's level, not the node's level
66
+ const zeroHash = this.tree.getZeroHash(level + 1);
67
+ batch.put(snapshotChildKey(node, 0), lhs ?? zeroHash);
68
+ batch.put(snapshotChildKey(node, 1), rhs ?? zeroHash);
69
+ // enqueue the children only if they're not zero hashes
70
+ if (lhs) {
71
+ queue.push([lhs, level + 1, 2n * i]);
72
+ }
73
+ if (rhs) {
74
+ queue.push([rhs, level + 1, 2n * i + 1n]);
75
+ }
76
+ }
77
+ batch.put(snapshotRootKey(this.tree.getName(), block), root);
78
+ batch.put(snapshotNumLeavesKey(this.tree.getName(), block), String(numLeaves));
79
+ await batch.write();
80
+ return this.openSnapshot(root, numLeaves);
81
+ }
82
+ handleLeaf(_index, _node, _batch) {
83
+ return Promise.resolve();
84
+ }
85
+ async getSnapshot(version) {
86
+ const snapshotMetadata = await __classPrivateFieldGet(this, _BaseFullTreeSnapshotBuilder_instances, "m", _BaseFullTreeSnapshotBuilder_getSnapshotMeta).call(this, version);
87
+ if (!snapshotMetadata) {
88
+ throw new Error(`Version ${version} does not exist for tree ${this.tree.getName()}`);
89
+ }
90
+ return this.openSnapshot(snapshotMetadata.root, snapshotMetadata.numLeaves);
91
+ }
92
+ }
93
+ _BaseFullTreeSnapshotBuilder_instances = new WeakSet(), _BaseFullTreeSnapshotBuilder_getSnapshotMeta = async function _BaseFullTreeSnapshotBuilder_getSnapshotMeta(block) {
94
+ try {
95
+ const treeName = this.tree.getName();
96
+ const root = await this.db.get(snapshotRootKey(treeName, block));
97
+ const numLeaves = BigInt(await this.db.get(snapshotNumLeavesKey(treeName, block)));
98
+ return { root, numLeaves };
99
+ }
100
+ catch (err) {
101
+ return undefined;
102
+ }
103
+ };
104
+ /**
105
+ * A source of sibling paths from a snapshot tree
106
+ */
107
+ export class BaseFullTreeSnapshot {
108
+ constructor(db, historicRoot, numLeaves, tree) {
109
+ _BaseFullTreeSnapshot_instances.add(this);
110
+ this.db = db;
111
+ this.historicRoot = historicRoot;
112
+ this.numLeaves = numLeaves;
113
+ this.tree = tree;
114
+ }
115
+ async getSiblingPath(index) {
116
+ const siblings = [];
117
+ for await (const [_node, sibling] of this.pathFromRootToLeaf(index)) {
118
+ siblings.push(sibling);
119
+ }
120
+ // we got the siblings we were looking for, but they are in root-leaf order
121
+ // reverse them here so we have leaf-root (what SiblingPath expects)
122
+ siblings.reverse();
123
+ return new SiblingPath(this.tree.getDepth(), siblings);
124
+ }
125
+ async getLeafValue(index) {
126
+ let leafNode = undefined;
127
+ for await (const [node, _sibling] of this.pathFromRootToLeaf(index)) {
128
+ leafNode = node;
129
+ }
130
+ return leafNode;
131
+ }
132
+ getDepth() {
133
+ return this.tree.getDepth();
134
+ }
135
+ getRoot() {
136
+ return this.historicRoot;
137
+ }
138
+ getNumLeaves() {
139
+ return this.numLeaves;
140
+ }
141
+ async *pathFromRootToLeaf(leafIndex) {
142
+ const root = this.historicRoot;
143
+ const pathFromRoot = __classPrivateFieldGet(this, _BaseFullTreeSnapshot_instances, "m", _BaseFullTreeSnapshot_getPathFromRoot).call(this, leafIndex);
144
+ let node = root;
145
+ for (let i = 0; i < pathFromRoot.length; i++) {
146
+ // get both children. We'll need both anyway (one to keep track of, the other to walk down to)
147
+ const children = await Promise.all([
148
+ this.db.get(snapshotChildKey(node, 0)),
149
+ this.db.get(snapshotChildKey(node, 1)),
150
+ ]).catch(() => [this.tree.getZeroHash(i + 1), this.tree.getZeroHash(i + 1)]);
151
+ const next = children[pathFromRoot[i]];
152
+ const sibling = children[(pathFromRoot[i] + 1) % 2];
153
+ yield [next, sibling];
154
+ node = next;
155
+ }
156
+ }
157
+ async findLeafIndex(value) {
158
+ const numLeaves = this.getNumLeaves();
159
+ for (let i = 0n; i < numLeaves; i++) {
160
+ const currentValue = await this.getLeafValue(i);
161
+ if (currentValue && currentValue.equals(value)) {
162
+ return i;
163
+ }
164
+ }
165
+ return undefined;
166
+ }
167
+ }
168
+ _BaseFullTreeSnapshot_instances = new WeakSet(), _BaseFullTreeSnapshot_getPathFromRoot = function _BaseFullTreeSnapshot_getPathFromRoot(leafIndex) {
169
+ const path = [];
170
+ let level = this.tree.getDepth();
171
+ while (level > 0) {
172
+ path.push(leafIndex & 0x01n ? 1 : 0);
173
+ leafIndex >>= 1n;
174
+ level--;
175
+ }
176
+ path.reverse();
177
+ return path;
178
+ };
179
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZV9mdWxsX3NuYXBzaG90LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NuYXBzaG90cy9iYXNlX2Z1bGxfc25hcHNob3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBTzNDLDRCQUE0QjtBQUM1QixNQUFNLGdCQUFnQixHQUFHLENBQUMsSUFBWSxFQUFFLEtBQVksRUFBRSxFQUFFLENBQ3RELE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUVqRiwwQkFBMEI7QUFDMUIsTUFBTSxlQUFlLEdBQUcsQ0FBQyxRQUFnQixFQUFFLEtBQWEsRUFBRSxFQUFFLENBQUMsaUJBQWlCLFFBQVEsSUFBSSxLQUFLLEVBQUUsQ0FBQztBQUNsRyxNQUFNLG9CQUFvQixHQUFHLENBQUMsUUFBZ0IsRUFBRSxLQUFhLEVBQUUsRUFBRSxDQUFDLHNCQUFzQixRQUFRLElBQUksS0FBSyxFQUFFLENBQUM7QUFFNUc7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBQ0gsTUFBTSxPQUFnQiwyQkFBMkI7SUFHL0MsWUFBc0IsRUFBVyxFQUFZLElBQU87O1FBQTlCLE9BQUUsR0FBRixFQUFFLENBQVM7UUFBWSxTQUFJLEdBQUosSUFBSSxDQUFHO0lBQUcsQ0FBQztJQUV4RCxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQWE7UUFDMUIsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLHVCQUFBLElBQUksNEZBQWlCLE1BQXJCLElBQUksRUFBa0IsS0FBSyxDQUFDLENBQUM7UUFFNUQsSUFBSSxnQkFBZ0IsRUFBRTtZQUNwQixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLGdCQUFn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
@@ -0,0 +1,22 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ import { TreeBase } from '../tree_base.js';
3
+ import { BaseFullTreeSnapshotBuilder } from './base_full_snapshot.js';
4
+ import { TreeSnapshot, TreeSnapshotBuilder } from './snapshot_builder.js';
5
+ /**
6
+ * Builds a full snapshot of a tree. This implementation works for any Merkle tree and stores
7
+ * it in a database in a similar way to how a tree is stored in memory, using pointers.
8
+ *
9
+ * Sharing the same database between versions and trees is recommended as the trees would share
10
+ * structure.
11
+ *
12
+ * Complexity:
13
+ * N - count of non-zero nodes in tree
14
+ * M - count of snapshots
15
+ * H - tree height
16
+ * Worst case space complexity: O(N * M)
17
+ * Sibling path access: O(H) database reads
18
+ */
19
+ export declare class FullTreeSnapshotBuilder extends BaseFullTreeSnapshotBuilder<TreeBase, TreeSnapshot> implements TreeSnapshotBuilder<TreeSnapshot> {
20
+ protected openSnapshot(root: Buffer, numLeaves: bigint): TreeSnapshot;
21
+ }
22
+ //# sourceMappingURL=full_snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"full_snapshot.d.ts","sourceRoot":"","sources":["../../src/snapshots/full_snapshot.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAwB,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAC5F,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE1E;;;;;;;;;;;;;GAaG;AACH,qBAAa,uBACX,SAAQ,2BAA2B,CAAC,QAAQ,EAAE,YAAY,CAC1D,YAAW,mBAAmB,CAAC,YAAY,CAAC;IAE5C,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY;CAGtE"}
@@ -0,0 +1,21 @@
1
+ import { BaseFullTreeSnapshot, BaseFullTreeSnapshotBuilder } from './base_full_snapshot.js';
2
+ /**
3
+ * Builds a full snapshot of a tree. This implementation works for any Merkle tree and stores
4
+ * it in a database in a similar way to how a tree is stored in memory, using pointers.
5
+ *
6
+ * Sharing the same database between versions and trees is recommended as the trees would share
7
+ * structure.
8
+ *
9
+ * Complexity:
10
+ * N - count of non-zero nodes in tree
11
+ * M - count of snapshots
12
+ * H - tree height
13
+ * Worst case space complexity: O(N * M)
14
+ * Sibling path access: O(H) database reads
15
+ */
16
+ export class FullTreeSnapshotBuilder extends BaseFullTreeSnapshotBuilder {
17
+ openSnapshot(root, numLeaves) {
18
+ return new BaseFullTreeSnapshot(this.db, root, numLeaves, this.tree);
19
+ }
20
+ }
21
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnVsbF9zbmFwc2hvdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zbmFwc2hvdHMvZnVsbF9zbmFwc2hvdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUc1Rjs7Ozs7Ozs7Ozs7OztHQWFHO0FBQ0gsTUFBTSxPQUFPLHVCQUNYLFNBQVEsMkJBQW1EO0lBR2pELFlBQVksQ0FBQyxJQUFZLEVBQUUsU0FBaUI7UUFDcEQsT0FBTyxJQUFJLG9CQUFvQixDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdkUsQ0FBQztDQUNGIn0=
@@ -0,0 +1,15 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ import { LevelUp, LevelUpChain } from 'levelup';
3
+ import { IndexedTree } from '../interfaces/indexed_tree.js';
4
+ import { PreimageFactory } from '../standard_indexed_tree/standard_indexed_tree.js';
5
+ import { TreeBase } from '../tree_base.js';
6
+ import { BaseFullTreeSnapshotBuilder } from './base_full_snapshot.js';
7
+ import { IndexedTreeSnapshot, TreeSnapshotBuilder } from './snapshot_builder.js';
8
+ /** a */
9
+ export declare class IndexedTreeSnapshotBuilder extends BaseFullTreeSnapshotBuilder<IndexedTree & TreeBase, IndexedTreeSnapshot> implements TreeSnapshotBuilder<IndexedTreeSnapshot> {
10
+ private leafPreimageBuilder;
11
+ constructor(db: LevelUp, tree: IndexedTree & TreeBase, leafPreimageBuilder: PreimageFactory);
12
+ protected openSnapshot(root: Buffer, numLeaves: bigint): IndexedTreeSnapshot;
13
+ protected handleLeaf(index: bigint, node: Buffer, batch: LevelUpChain): Promise<void>;
14
+ }
15
+ //# sourceMappingURL=indexed_tree_snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexed_tree_snapshot.d.ts","sourceRoot":"","sources":["../../src/snapshots/indexed_tree_snapshot.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEhD,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,mDAAmD,CAAC;AACpF,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAwB,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAC5F,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAKjF,QAAQ;AACR,qBAAa,0BACX,SAAQ,2BAA2B,CAAC,WAAW,GAAG,QAAQ,EAAE,mBAAmB,CAC/E,YAAW,mBAAmB,CAAC,mBAAmB,CAAC;IAEI,OAAO,CAAC,mBAAmB;gBAAtE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,QAAQ,EAAU,mBAAmB,EAAE,eAAe;IAInG,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,mBAAmB;cAI5D,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY;CAM5E"}
@@ -0,0 +1,75 @@
1
+ import { BaseFullTreeSnapshot, BaseFullTreeSnapshotBuilder } from './base_full_snapshot.js';
2
+ const snapshotLeafValue = (node, index) => Buffer.concat([Buffer.from('snapshot:leaf:'), node, Buffer.from(':' + index)]);
3
+ /** a */
4
+ export class IndexedTreeSnapshotBuilder extends BaseFullTreeSnapshotBuilder {
5
+ constructor(db, tree, leafPreimageBuilder) {
6
+ super(db, tree);
7
+ this.leafPreimageBuilder = leafPreimageBuilder;
8
+ }
9
+ openSnapshot(root, numLeaves) {
10
+ return new IndexedTreeSnapshotImpl(this.db, root, numLeaves, this.tree, this.leafPreimageBuilder);
11
+ }
12
+ async handleLeaf(index, node, batch) {
13
+ const leafPreimage = await this.tree.getLatestLeafPreimageCopy(index, false);
14
+ if (leafPreimage) {
15
+ batch.put(snapshotLeafValue(node, index), leafPreimage.toBuffer());
16
+ }
17
+ }
18
+ }
19
+ /** A snapshot of an indexed tree at a particular point in time */
20
+ class IndexedTreeSnapshotImpl extends BaseFullTreeSnapshot {
21
+ constructor(db, historicRoot, numLeaves, tree, leafPreimageBuilder) {
22
+ super(db, historicRoot, numLeaves, tree);
23
+ this.leafPreimageBuilder = leafPreimageBuilder;
24
+ }
25
+ async getLeafValue(index) {
26
+ const leafPreimage = await this.getLatestLeafPreimageCopy(index);
27
+ return leafPreimage?.toBuffer();
28
+ }
29
+ async getLatestLeafPreimageCopy(index) {
30
+ const leafNode = await super.getLeafValue(index);
31
+ const leafValue = await this.db.get(snapshotLeafValue(leafNode, index)).catch(() => undefined);
32
+ if (leafValue) {
33
+ return this.leafPreimageBuilder.fromBuffer(leafValue);
34
+ }
35
+ else {
36
+ return undefined;
37
+ }
38
+ }
39
+ async findIndexOfPreviousKey(newValue) {
40
+ const numLeaves = this.getNumLeaves();
41
+ const diff = [];
42
+ for (let i = 0; i < numLeaves; i++) {
43
+ // this is very inefficient
44
+ const storedLeaf = await this.getLatestLeafPreimageCopy(BigInt(i));
45
+ // The stored leaf can be undefined if it addresses an empty leaf
46
+ // If the leaf is empty we do the same as if the leaf was larger
47
+ if (storedLeaf === undefined) {
48
+ diff.push(newValue);
49
+ }
50
+ else if (storedLeaf.getKey() > newValue) {
51
+ diff.push(newValue);
52
+ }
53
+ else if (storedLeaf.getKey() === newValue) {
54
+ return { index: BigInt(i), alreadyPresent: true };
55
+ }
56
+ else {
57
+ diff.push(newValue - storedLeaf.getKey());
58
+ }
59
+ }
60
+ let minIndex = 0;
61
+ for (let i = 1; i < diff.length; i++) {
62
+ if (diff[i] < diff[minIndex]) {
63
+ minIndex = i;
64
+ }
65
+ }
66
+ return { index: BigInt(minIndex), alreadyPresent: false };
67
+ }
68
+ async findLeafIndex(value) {
69
+ const index = await this.tree.findLeafIndex(value, false);
70
+ if (index !== undefined && index < this.getNumLeaves()) {
71
+ return index;
72
+ }
73
+ }
74
+ }
75
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXhlZF90cmVlX3NuYXBzaG90LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NuYXBzaG90cy9pbmRleGVkX3RyZWVfc25hcHNob3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBT0EsT0FBTyxFQUFFLG9CQUFvQixFQUFFLDJCQUEyQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFHNUYsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLElBQVksRUFBRSxLQUFhLEVBQUUsRUFBRSxDQUN4RCxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFFakYsUUFBUTtBQUNSLE1BQU0sT0FBTywwQkFDWCxTQUFRLDJCQUF3RTtJQUdoRixZQUFZLEVBQVcsRUFBRSxJQUE0QixFQUFVLG1CQUFvQztRQUNqRyxLQUFLLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBRDZDLHdCQUFtQixHQUFuQixtQkFBbUIsQ0FBaUI7SUFFbkcsQ0FBQztJQUVTLFlBQVksQ0FBQyxJQUFZLEVBQUUsU0FBaUI7UUFDcEQsT0FBTyxJQUFJLHVCQUF1QixDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0lBQ3BHLENBQUM7SUFFUyxLQUFLLENBQUMsVUFBVSxDQUFDLEtBQWEsRUFBRSxJQUFZLEVBQUUsS0FBbUI7UUFDekUsTUFBTSxZQUFZLEdBQUcsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLHlCQUF5QixDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztRQUM3RSxJQUFJLFlBQVksRUFBRTtZQUNoQixLQUFLLENBQUMsR0FBRyxDQUFDLGlCQUFpQixD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
@@ -0,0 +1,76 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ import { IndexedTreeLeafPreimage } from '@aztec/foundation/trees';
3
+ import { SiblingPath } from '@aztec/types';
4
+ /**
5
+ * An interface for a tree that can record snapshots of its contents.
6
+ */
7
+ export interface TreeSnapshotBuilder<S extends TreeSnapshot = TreeSnapshot> {
8
+ /**
9
+ * Creates a snapshot of the tree at the given version.
10
+ * @param block - The version to snapshot the tree at.
11
+ */
12
+ snapshot(block: number): Promise<S>;
13
+ /**
14
+ * Returns a snapshot of the tree at the given version.
15
+ * @param block - The version of the snapshot to return.
16
+ */
17
+ getSnapshot(block: number): Promise<S>;
18
+ }
19
+ /**
20
+ * A tree snapshot
21
+ */
22
+ export interface TreeSnapshot {
23
+ /**
24
+ * Returns the current root of the tree.
25
+ */
26
+ getRoot(): Buffer;
27
+ /**
28
+ * Returns the number of leaves in the tree.
29
+ */
30
+ getDepth(): number;
31
+ /**
32
+ * Returns the number of leaves in the tree.
33
+ */
34
+ getNumLeaves(): bigint;
35
+ /**
36
+ * Returns the value of a leaf at the specified index.
37
+ * @param index - The index of the leaf value to be returned.
38
+ */
39
+ getLeafValue(index: bigint): Promise<Buffer | undefined>;
40
+ /**
41
+ * Returns the sibling path for a requested leaf index.
42
+ * @param index - The index of the leaf for which a sibling path is required.
43
+ */
44
+ getSiblingPath<N extends number>(index: bigint): Promise<SiblingPath<N>>;
45
+ /**
46
+ * Returns the index of a leaf given its value, or undefined if no leaf with that value is found.
47
+ * @param treeId - The ID of the tree.
48
+ * @param value - The leaf value to look for.
49
+ * @returns The index of the first leaf found with a given value (undefined if not found).
50
+ */
51
+ findLeafIndex(value: Buffer): Promise<bigint | undefined>;
52
+ }
53
+ /** A snapshot of an indexed tree */
54
+ export interface IndexedTreeSnapshot extends TreeSnapshot {
55
+ /**
56
+ * Gets the historical data for a leaf
57
+ * @param index - The index of the leaf to get the data for
58
+ */
59
+ getLatestLeafPreimageCopy(index: bigint): Promise<IndexedTreeLeafPreimage | undefined>;
60
+ /**
61
+ * Finds the index of the largest leaf whose value is less than or equal to the provided value.
62
+ * @param newValue - The new value to be inserted into the tree.
63
+ * @returns The found leaf index and a flag indicating if the corresponding leaf's value is equal to `newValue`.
64
+ */
65
+ findIndexOfPreviousKey(newValue: bigint): Promise<{
66
+ /**
67
+ * The index of the found leaf.
68
+ */
69
+ index: bigint;
70
+ /**
71
+ * A flag indicating if the corresponding leaf's value is equal to `newValue`.
72
+ */
73
+ alreadyPresent: boolean;
74
+ }>;
75
+ }
76
+ //# sourceMappingURL=snapshot_builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot_builder.d.ts","sourceRoot":"","sources":["../../src/snapshots/snapshot_builder.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C;;GAEG;AACH,MAAM,WAAW,mBAAmB,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY;IACxE;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAEpC;;;OAGG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACxC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,OAAO,IAAI,MAAM,CAAC;IAElB;;OAEG;IACH,QAAQ,IAAI,MAAM,CAAC;IAEnB;;OAEG;IACH,YAAY,IAAI,MAAM,CAAC;IAEvB;;;OAGG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAEzD;;;OAGG;IACH,cAAc,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAEzE;;;;;OAKG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAC3D;AAED,oCAAoC;AACpC,MAAM,WAAW,mBAAoB,SAAQ,YAAY;IACvD;;;OAGG;IACH,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,GAAG,SAAS,CAAC,CAAC;IAEvF;;;;OAIG;IACH,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAChD;;WAEG;QACH,KAAK,EAAE,MAAM,CAAC;QACd;;WAEG;QACH,cAAc,EAAE,OAAO,CAAC;KACzB,CAAC,CAAC;CACJ"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic25hcHNob3RfYnVpbGRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zbmFwc2hvdHMvc25hcHNob3RfYnVpbGRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIn0=
@@ -0,0 +1,5 @@
1
+ import { TreeBase } from '../tree_base.js';
2
+ import { TreeSnapshotBuilder } from './snapshot_builder.js';
3
+ /** Creates a test suit for snapshots */
4
+ export declare function describeSnapshotBuilderTestSuite<T extends TreeBase, S extends TreeSnapshotBuilder>(getTree: () => T, getSnapshotBuilder: () => S, modifyTree: (tree: T) => Promise<void>): void;
5
+ //# sourceMappingURL=snapshot_builder_test_suite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot_builder_test_suite.d.ts","sourceRoot":"","sources":["../../src/snapshots/snapshot_builder_test_suite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,wCAAwC;AACxC,wBAAgB,gCAAgC,CAAC,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,mBAAmB,EAChG,OAAO,EAAE,MAAM,CAAC,EAChB,kBAAkB,EAAE,MAAM,CAAC,EAC3B,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,QAkNvC"}
@@ -0,0 +1,163 @@
1
+ /** Creates a test suit for snapshots */
2
+ export function describeSnapshotBuilderTestSuite(getTree, getSnapshotBuilder, modifyTree) {
3
+ describe('SnapshotBuilder', () => {
4
+ let tree;
5
+ let snapshotBuilder;
6
+ let leaves;
7
+ beforeEach(() => {
8
+ tree = getTree();
9
+ snapshotBuilder = getSnapshotBuilder();
10
+ leaves = Array.from({ length: 4 }).map(() => BigInt(Math.floor(Math.random() * 2 ** tree.getDepth())));
11
+ });
12
+ describe('snapshot', () => {
13
+ it('takes snapshots', async () => {
14
+ await modifyTree(tree);
15
+ await tree.commit();
16
+ await expect(snapshotBuilder.snapshot(1)).resolves.toBeDefined();
17
+ });
18
+ it('is idempotent', async () => {
19
+ await modifyTree(tree);
20
+ await tree.commit();
21
+ const block = 1;
22
+ const snapshot = await snapshotBuilder.snapshot(block);
23
+ await expect(snapshotBuilder.snapshot(block)).resolves.toEqual(snapshot);
24
+ });
25
+ it('returns the same path if tree has not diverged', async () => {
26
+ await modifyTree(tree);
27
+ await tree.commit();
28
+ const snapshot = await snapshotBuilder.snapshot(1);
29
+ const historicPaths = await Promise.all(leaves.map(leaf => snapshot.getSiblingPath(leaf)));
30
+ const expectedPaths = await Promise.all(leaves.map(leaf => tree.getSiblingPath(leaf, false)));
31
+ for (const [index, path] of historicPaths.entries()) {
32
+ expect(path).toEqual(expectedPaths[index]);
33
+ }
34
+ });
35
+ it('returns historic paths if tree has diverged and no new snapshots have been taken', async () => {
36
+ await modifyTree(tree);
37
+ await tree.commit();
38
+ const snapshot = await snapshotBuilder.snapshot(1);
39
+ const expectedPaths = await Promise.all(leaves.map(leaf => tree.getSiblingPath(leaf, false)));
40
+ await modifyTree(tree);
41
+ await tree.commit();
42
+ const historicPaths = await Promise.all(leaves.map(leaf => snapshot.getSiblingPath(leaf)));
43
+ for (const [index, path] of historicPaths.entries()) {
44
+ expect(path).toEqual(expectedPaths[index]);
45
+ }
46
+ });
47
+ it('retains old snapshots even if new one are created', async () => {
48
+ await modifyTree(tree);
49
+ await tree.commit();
50
+ const expectedPaths = await Promise.all(leaves.map(leaf => tree.getSiblingPath(leaf, false)));
51
+ const snapshot = await snapshotBuilder.snapshot(1);
52
+ await modifyTree(tree);
53
+ await tree.commit();
54
+ await snapshotBuilder.snapshot(2);
55
+ // check that snapshot 2 has not influenced snapshot(1) at all
56
+ const historicPaths = await Promise.all(leaves.map(leaf => snapshot.getSiblingPath(leaf)));
57
+ for (const [index, path] of historicPaths.entries()) {
58
+ expect(path).toEqual(expectedPaths[index]);
59
+ }
60
+ });
61
+ it('retains old snapshots even if new one are created and the tree diverges', async () => {
62
+ await modifyTree(tree);
63
+ await tree.commit();
64
+ const expectedPaths = await Promise.all(leaves.map(leaf => tree.getSiblingPath(leaf, false)));
65
+ const snapshot = await snapshotBuilder.snapshot(1);
66
+ await modifyTree(tree);
67
+ await tree.commit();
68
+ await snapshotBuilder.snapshot(2);
69
+ await modifyTree(tree);
70
+ await tree.commit();
71
+ // check that snapshot 2 has not influenced snapshot(1) at all
72
+ // and that the diverging tree does not influence the old snapshot
73
+ const historicPaths = await Promise.all(leaves.map(leaf => snapshot.getSiblingPath(leaf)));
74
+ for (const [index, path] of historicPaths.entries()) {
75
+ expect(path).toEqual(expectedPaths[index]);
76
+ }
77
+ });
78
+ });
79
+ describe('getSnapshot', () => {
80
+ it('returns old snapshots', async () => {
81
+ await modifyTree(tree);
82
+ await tree.commit();
83
+ const expectedPaths = await Promise.all(leaves.map(leaf => tree.getSiblingPath(leaf, false)));
84
+ await snapshotBuilder.snapshot(1);
85
+ for (let i = 2; i < 5; i++) {
86
+ await modifyTree(tree);
87
+ await tree.commit();
88
+ await snapshotBuilder.snapshot(i);
89
+ }
90
+ const firstSnapshot = await snapshotBuilder.getSnapshot(1);
91
+ const historicPaths = await Promise.all(leaves.map(leaf => firstSnapshot.getSiblingPath(leaf)));
92
+ for (const [index, path] of historicPaths.entries()) {
93
+ expect(path).toEqual(expectedPaths[index]);
94
+ }
95
+ });
96
+ it('throws if an unknown snapshot is requested', async () => {
97
+ await modifyTree(tree);
98
+ await tree.commit();
99
+ await snapshotBuilder.snapshot(1);
100
+ await expect(snapshotBuilder.getSnapshot(2)).rejects.toThrow();
101
+ });
102
+ });
103
+ describe('getRoot', () => {
104
+ it('returns the historical root of the tree when the snapshot was taken', async () => {
105
+ await modifyTree(tree);
106
+ await tree.commit();
107
+ const snapshot = await snapshotBuilder.snapshot(1);
108
+ const historicalRoot = tree.getRoot(false);
109
+ await modifyTree(tree);
110
+ await tree.commit();
111
+ expect(snapshot.getRoot()).toEqual(historicalRoot);
112
+ expect(snapshot.getRoot()).not.toEqual(tree.getRoot(false));
113
+ });
114
+ });
115
+ describe('getDepth', () => {
116
+ it('returns the same depth as the tree', async () => {
117
+ await modifyTree(tree);
118
+ await tree.commit();
119
+ const snapshot = await snapshotBuilder.snapshot(1);
120
+ expect(snapshot.getDepth()).toEqual(tree.getDepth());
121
+ });
122
+ });
123
+ describe('getNumLeaves', () => {
124
+ it('returns the historical leaves count when the snapshot was taken', async () => {
125
+ await modifyTree(tree);
126
+ await tree.commit();
127
+ const snapshot = await snapshotBuilder.snapshot(1);
128
+ const historicalNumLeaves = tree.getNumLeaves(false);
129
+ await modifyTree(tree);
130
+ await tree.commit();
131
+ expect(snapshot.getNumLeaves()).toEqual(historicalNumLeaves);
132
+ });
133
+ });
134
+ describe('getLeafValue', () => {
135
+ it('returns the historical leaf value when the snapshot was taken', async () => {
136
+ await modifyTree(tree);
137
+ await tree.commit();
138
+ const snapshot = await snapshotBuilder.snapshot(1);
139
+ const historicalLeafValue = await tree.getLeafValue(0n, false);
140
+ expect(await snapshot.getLeafValue(0n)).toEqual(historicalLeafValue);
141
+ await modifyTree(tree);
142
+ await tree.commit();
143
+ await expect(snapshot.getLeafValue(0n)).resolves.toEqual(historicalLeafValue);
144
+ });
145
+ });
146
+ describe('findLeafIndex', () => {
147
+ it('returns the historical leaf index when the snapshot was taken', async () => {
148
+ await modifyTree(tree);
149
+ await tree.commit();
150
+ const snapshot = await snapshotBuilder.snapshot(1);
151
+ const initialLastLeafIndex = tree.getNumLeaves(false) - 1n;
152
+ let lastLeaf = await tree.getLeafValue(initialLastLeafIndex, false);
153
+ expect(await snapshot.findLeafIndex(lastLeaf)).toBe(initialLastLeafIndex);
154
+ await modifyTree(tree);
155
+ await tree.commit();
156
+ const newLastLeafIndex = tree.getNumLeaves(false) - 1n;
157
+ lastLeaf = await tree.getLeafValue(newLastLeafIndex, false);
158
+ expect(await snapshot.findLeafIndex(lastLeaf)).toBe(undefined);
159
+ });
160
+ });
161
+ });
162
+ }
163
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic25hcHNob3RfYnVpbGRlcl90ZXN0X3N1aXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NuYXBzaG90cy9zbmFwc2hvdF9idWlsZGVyX3Rlc3Rfc3VpdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBR0Esd0NBQXdDO0FBQ3hDLE1BQU0sVUFBVSxnQ0FBZ0MsQ0FDOUMsT0FBZ0IsRUFDaEIsa0JBQTJCLEVBQzNCLFVBQXNDO0lBRXRDLFFBQVEsQ0FBQyxpQkFBaUIsRUFBRSxHQUFHLEVBQUU7UUFDL0IsSUFBSSxJQUFPLENBQUM7UUFDWixJQUFJLGVBQWtCLENBQUM7UUFDdkIsSUFBSSxNQUFnQixDQUFDO1FBRXJCLFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDZCxJQUFJLEdBQUcsT0FBTyxFQUFFLENBQUM7WUFDakIsZUFBZSxHQUFHLGtCQUFrQixFQUFFLENBQUM7WUFFdkMsTUFBTSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDekcsQ0FBQyxDQUFDLENBQUM7UUFFSCxRQUFRLENBQUMsVUFBVSxFQUFFLEdBQUcsRUFBRTtZQUN4QixFQUFFLENBQUMsaUJBQWlCLEVBQUUsS0FBSyxJQUFJLEVBQUU7Z0JBQy9CLE1BQU0sVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUN2QixNQUFNLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDcEIsTUFBTSxNQUFNLENBQUMsZUFBZSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNuRSxDQUFDLENBQUMsQ0FB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
@@ -1,15 +1,20 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
2
  import { UpdateOnlyTree } from '../interfaces/update_only_tree.js';
3
+ import { TreeSnapshot } from '../snapshots/snapshot_builder.js';
3
4
  import { TreeBase } from '../tree_base.js';
4
5
  /**
5
6
  * A Merkle tree implementation that uses a LevelDB database to store the tree.
6
7
  */
7
8
  export declare class SparseTree extends TreeBase implements UpdateOnlyTree {
9
+ #private;
8
10
  /**
9
11
  * Updates a leaf in the tree.
10
12
  * @param leaf - New contents of the leaf.
11
13
  * @param index - Index of the leaf to be updated.
12
14
  */
13
15
  updateLeaf(leaf: Buffer, index: bigint): Promise<void>;
16
+ snapshot(block: number): Promise<TreeSnapshot>;
17
+ getSnapshot(block: number): Promise<TreeSnapshot>;
18
+ findLeafIndex(_value: Buffer, _includeUncommitted: boolean): Promise<bigint | undefined>;
14
19
  }
15
20
  //# sourceMappingURL=sparse_tree.d.ts.map