@aztec/merkle-tree 0.6.7 → 0.7.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 (66) hide show
  1. package/Dockerfile +15 -0
  2. package/package.json +4 -4
  3. package/.tsbuildinfo +0 -1
  4. package/dest/index.d.ts +0 -12
  5. package/dest/index.d.ts.map +0 -1
  6. package/dest/index.js +0 -12
  7. package/dest/interfaces/append_only_tree.d.ts +0 -13
  8. package/dest/interfaces/append_only_tree.d.ts.map +0 -1
  9. package/dest/interfaces/append_only_tree.js +0 -2
  10. package/dest/interfaces/indexed_tree.d.ts +0 -57
  11. package/dest/interfaces/indexed_tree.d.ts.map +0 -1
  12. package/dest/interfaces/indexed_tree.js +0 -2
  13. package/dest/interfaces/merkle_tree.d.ts +0 -47
  14. package/dest/interfaces/merkle_tree.d.ts.map +0 -1
  15. package/dest/interfaces/merkle_tree.js +0 -2
  16. package/dest/interfaces/update_only_tree.d.ts +0 -15
  17. package/dest/interfaces/update_only_tree.d.ts.map +0 -1
  18. package/dest/interfaces/update_only_tree.js +0 -2
  19. package/dest/load_tree.d.ts +0 -13
  20. package/dest/load_tree.d.ts.map +0 -1
  21. package/dest/load_tree.js +0 -17
  22. package/dest/new_tree.d.ts +0 -15
  23. package/dest/new_tree.d.ts.map +0 -1
  24. package/dest/new_tree.js +0 -16
  25. package/dest/pedersen.d.ts +0 -15
  26. package/dest/pedersen.d.ts.map +0 -1
  27. package/dest/pedersen.js +0 -22
  28. package/dest/sparse_tree/sparse_tree.d.ts +0 -15
  29. package/dest/sparse_tree/sparse_tree.d.ts.map +0 -1
  30. package/dest/sparse_tree/sparse_tree.js +0 -31
  31. package/dest/sparse_tree/sparse_tree.test.d.ts +0 -2
  32. package/dest/sparse_tree/sparse_tree.test.d.ts.map +0 -1
  33. package/dest/sparse_tree/sparse_tree.test.js +0 -133
  34. package/dest/standard_indexed_tree/standard_indexed_tree.d.ts +0 -245
  35. package/dest/standard_indexed_tree/standard_indexed_tree.d.ts.map +0 -1
  36. package/dest/standard_indexed_tree/standard_indexed_tree.js +0 -488
  37. package/dest/standard_indexed_tree/test/standard_indexed_tree.test.d.ts +0 -2
  38. package/dest/standard_indexed_tree/test/standard_indexed_tree.test.d.ts.map +0 -1
  39. package/dest/standard_indexed_tree/test/standard_indexed_tree.test.js +0 -336
  40. package/dest/standard_indexed_tree/test/standard_indexed_tree_with_append.d.ts +0 -23
  41. package/dest/standard_indexed_tree/test/standard_indexed_tree_with_append.d.ts.map +0 -1
  42. package/dest/standard_indexed_tree/test/standard_indexed_tree_with_append.js +0 -59
  43. package/dest/standard_tree/standard_tree.d.ts +0 -15
  44. package/dest/standard_tree/standard_tree.d.ts.map +0 -1
  45. package/dest/standard_tree/standard_tree.js +0 -15
  46. package/dest/standard_tree/standard_tree.test.d.ts +0 -2
  47. package/dest/standard_tree/standard_tree.test.d.ts.map +0 -1
  48. package/dest/standard_tree/standard_tree.test.js +0 -58
  49. package/dest/test/standard_based_test_suite.d.ts +0 -6
  50. package/dest/test/standard_based_test_suite.d.ts.map +0 -1
  51. package/dest/test/standard_based_test_suite.js +0 -87
  52. package/dest/test/test_suite.d.ts +0 -6
  53. package/dest/test/test_suite.d.ts.map +0 -1
  54. package/dest/test/test_suite.js +0 -119
  55. package/dest/test/utils/append_leaves.d.ts +0 -5
  56. package/dest/test/utils/append_leaves.d.ts.map +0 -1
  57. package/dest/test/utils/append_leaves.js +0 -14
  58. package/dest/test/utils/create_mem_down.d.ts +0 -3
  59. package/dest/test/utils/create_mem_down.d.ts.map +0 -1
  60. package/dest/test/utils/create_mem_down.js +0 -3
  61. package/dest/test/utils/pedersen_with_counter.d.ts +0 -24
  62. package/dest/test/utils/pedersen_with_counter.d.ts.map +0 -1
  63. package/dest/test/utils/pedersen_with_counter.js +0 -31
  64. package/dest/tree_base.d.ts +0 -130
  65. package/dest/tree_base.d.ts.map +0 -1
  66. package/dest/tree_base.js +0 -257
package/dest/tree_base.js DELETED
@@ -1,257 +0,0 @@
1
- import { toBigIntLE, toBufferLE } from '@aztec/foundation/bigint-buffer';
2
- import { SiblingPath } from '@aztec/types';
3
- const MAX_DEPTH = 254;
4
- const indexToKeyHash = (name, level, index) => `${name}:${level}:${index}`;
5
- const encodeMeta = (root, depth, size) => {
6
- const data = Buffer.alloc(36);
7
- root.copy(data);
8
- data.writeUInt32LE(depth, 32);
9
- return Buffer.concat([data, toBufferLE(size, 32)]);
10
- };
11
- export const decodeMeta = (meta) => {
12
- const root = meta.subarray(0, 32);
13
- const depth = meta.readUInt32LE(32);
14
- const size = toBigIntLE(meta.subarray(36));
15
- return {
16
- root,
17
- depth,
18
- size,
19
- };
20
- };
21
- export const INITIAL_LEAF = Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex');
22
- /**
23
- * A Merkle tree implementation that uses a LevelDB database to store the tree.
24
- */
25
- export class TreeBase {
26
- constructor(db, hasher, name, depth, size = 0n, root) {
27
- this.db = db;
28
- this.hasher = hasher;
29
- this.name = name;
30
- this.depth = depth;
31
- this.size = size;
32
- this.zeroHashes = [];
33
- this.cache = {};
34
- if (!(depth >= 1 && depth <= MAX_DEPTH)) {
35
- throw Error('Invalid depth');
36
- }
37
- // Compute the zero values at each layer.
38
- let current = INITIAL_LEAF;
39
- for (let i = depth - 1; i >= 0; --i) {
40
- this.zeroHashes[i] = current;
41
- current = hasher.compress(current, current);
42
- }
43
- this.root = root ? root : current;
44
- this.maxIndex = 2n ** BigInt(depth) - 1n;
45
- }
46
- /**
47
- * Returns the root of the tree.
48
- * @param includeUncommitted - If true, root incorporating uncommitted changes is returned.
49
- * @returns The root of the tree.
50
- */
51
- getRoot(includeUncommitted) {
52
- return !includeUncommitted ? this.root : this.cache[indexToKeyHash(this.name, 0, 0n)] ?? this.root;
53
- }
54
- /**
55
- * Returns the number of leaves in the tree.
56
- * @param includeUncommitted - If true, the returned number of leaves includes uncommitted changes.
57
- * @returns The number of leaves in the tree.
58
- */
59
- getNumLeaves(includeUncommitted) {
60
- return !includeUncommitted ? this.size : this.cachedSize ?? this.size;
61
- }
62
- /**
63
- * Returns the name of the tree.
64
- * @returns The name of the tree.
65
- */
66
- getName() {
67
- return this.name;
68
- }
69
- /**
70
- * Returns the depth of the tree.
71
- * @returns The depth of the tree.
72
- */
73
- getDepth() {
74
- return this.depth;
75
- }
76
- /**
77
- * Returns a sibling path for the element at the given index.
78
- * @param index - The index of the element.
79
- * @param includeUncommitted - Indicates whether to get a sibling path incorporating uncommitted changes.
80
- * @returns A sibling path for the element at the given index.
81
- * Note: The sibling path is an array of sibling hashes, with the lowest hash (leaf hash) first, and the highest hash last.
82
- */
83
- async getSiblingPath(index, includeUncommitted) {
84
- const path = [];
85
- let level = this.depth;
86
- while (level > 0) {
87
- const isRight = index & 0x01n;
88
- const sibling = await this.getLatestValueAtIndex(level, isRight ? index - 1n : index + 1n, includeUncommitted);
89
- path.push(sibling);
90
- level -= 1;
91
- index >>= 1n;
92
- }
93
- return new SiblingPath(this.depth, path);
94
- }
95
- /**
96
- * Commits the changes to the database.
97
- * @returns Empty promise.
98
- */
99
- async commit() {
100
- const batch = this.db.batch();
101
- const keys = Object.getOwnPropertyNames(this.cache);
102
- for (const key of keys) {
103
- batch.put(key, this.cache[key]);
104
- }
105
- this.size = this.getNumLeaves(true);
106
- this.root = this.getRoot(true);
107
- await this.writeMeta(batch);
108
- await batch.write();
109
- this.clearCache();
110
- }
111
- /**
112
- * Rolls back the not-yet-committed changes.
113
- * @returns Empty promise.
114
- */
115
- rollback() {
116
- this.clearCache();
117
- return Promise.resolve();
118
- }
119
- /**
120
- * Gets the value at the given index.
121
- * @param index - The index of the leaf.
122
- * @param includeUncommitted - Indicates whether to include uncommitted changes.
123
- * @returns Leaf value at the given index or undefined.
124
- */
125
- getLeafValue(index, includeUncommitted) {
126
- return this.getLatestValueAtIndex(this.depth, index, includeUncommitted);
127
- }
128
- /**
129
- * Clears the cache.
130
- */
131
- clearCache() {
132
- this.cache = {};
133
- this.cachedSize = undefined;
134
- }
135
- /**
136
- * Adds a leaf and all the hashes above it to the cache.
137
- * @param leaf - Leaf to add to cache.
138
- * @param index - Index of the leaf (used to derive the cache key).
139
- */
140
- async addLeafToCacheAndHashToRoot(leaf, index) {
141
- const key = indexToKeyHash(this.name, this.depth, index);
142
- let current = leaf;
143
- this.cache[key] = current;
144
- let level = this.depth;
145
- while (level > 0) {
146
- const isRight = index & 0x01n;
147
- const sibling = await this.getLatestValueAtIndex(level, isRight ? index - 1n : index + 1n, true);
148
- const lhs = isRight ? sibling : current;
149
- const rhs = isRight ? current : sibling;
150
- current = this.hasher.compress(lhs, rhs);
151
- level -= 1;
152
- index >>= 1n;
153
- const cacheKey = indexToKeyHash(this.name, level, index);
154
- this.cache[cacheKey] = current;
155
- }
156
- }
157
- /**
158
- * Returns the latest value at the given index.
159
- * @param level - The level of the tree.
160
- * @param index - The index of the element.
161
- * @param includeUncommitted - Indicates, whether to get include uncommitted changes.
162
- * @returns The latest value at the given index.
163
- * Note: If the value is not in the cache, it will be fetched from the database.
164
- */
165
- async getLatestValueAtIndex(level, index, includeUncommitted) {
166
- const key = indexToKeyHash(this.name, level, index);
167
- if (includeUncommitted && this.cache[key] !== undefined) {
168
- return this.cache[key];
169
- }
170
- const committed = await this.dbGet(key);
171
- if (committed !== undefined) {
172
- return committed;
173
- }
174
- return this.zeroHashes[level - 1];
175
- }
176
- /**
177
- * Gets a value from db by key.
178
- * @param key - The key to by which to get the value.
179
- * @returns A value from the db based on the key.
180
- */
181
- async dbGet(key) {
182
- return await this.db.get(key).catch(() => { });
183
- }
184
- /**
185
- * Initializes the tree.
186
- * @param prefilledSize - A number of leaves that are prefilled with values.
187
- * @returns Empty promise.
188
- */
189
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
190
- async init(prefilledSize) {
191
- // prefilledSize is used only by Indexed Tree.
192
- await this.writeMeta();
193
- }
194
- /**
195
- * Initializes the tree from the database.
196
- */
197
- async initFromDb() {
198
- // Implemented only by Indexed Tree to populate the leaf cache.
199
- }
200
- /**
201
- * Writes meta data to the provided batch.
202
- * @param batch - The batch to which to write the meta data.
203
- */
204
- async writeMeta(batch) {
205
- const data = encodeMeta(this.getRoot(true), this.depth, this.getNumLeaves(true));
206
- if (batch) {
207
- batch.put(this.name, data);
208
- }
209
- else {
210
- await this.db.put(this.name, data);
211
- }
212
- }
213
- /**
214
- * Appends the given leaves to the tree.
215
- * @param leaves - The leaves to append.
216
- * @returns Empty promise.
217
- *
218
- * @remarks The batch insertion algorithm works as follows:
219
- * 1. Insert all the leaves,
220
- * 2. start iterating over levels from the bottom up,
221
- * 3. on each level iterate over all the affected nodes (i.e. nodes whose preimages have changed),
222
- * 4. fetch the preimage, hash it and insert the updated value.
223
- * @remarks This algorithm is optimal when it comes to the number of hashing operations. It might not be optimal when
224
- * it comes to the number of database reads, but that should be irrelevant given that most of the time
225
- * `getLatestValueAtIndex` will return a value from cache (because at least one of the 2 children was
226
- * touched in previous iteration).
227
- */
228
- async appendLeaves(leaves) {
229
- const numLeaves = this.getNumLeaves(true);
230
- if (numLeaves + BigInt(leaves.length) - 1n > this.maxIndex) {
231
- throw Error(`Can't append beyond max index. Max index: ${this.maxIndex}`);
232
- }
233
- // 1. Insert all the leaves
234
- let firstIndex = numLeaves;
235
- let level = this.depth;
236
- for (let i = 0; i < leaves.length; i++) {
237
- const cacheKey = indexToKeyHash(this.name, level, firstIndex + BigInt(i));
238
- this.cache[cacheKey] = leaves[i];
239
- }
240
- let lastIndex = firstIndex + BigInt(leaves.length);
241
- // 2. Iterate over all the levels from the bottom up
242
- while (level > 0) {
243
- firstIndex >>= 1n;
244
- lastIndex >>= 1n;
245
- // 3.Iterate over all the affected nodes at this level and update them
246
- for (let index = firstIndex; index <= lastIndex; index++) {
247
- const lhs = await this.getLatestValueAtIndex(level, index * 2n, true);
248
- const rhs = await this.getLatestValueAtIndex(level, index * 2n + 1n, true);
249
- const cacheKey = indexToKeyHash(this.name, level - 1, index);
250
- this.cache[cacheKey] = this.hasher.compress(lhs, rhs);
251
- }
252
- level -= 1;
253
- }
254
- this.cachedSize = numLeaves + BigInt(leaves.length);
255
- }
256
- }
257
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJlZV9iYXNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3RyZWVfYmFzZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3pFLE9BQU8sRUFBVSxXQUFXLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFNbkQsTUFBTSxTQUFTLEdBQUcsR0FBRyxDQUFDO0FBRXRCLE1BQU0sY0FBYyxHQUFHLENBQUMsSUFBWSxFQUFFLEtBQWEsRUFBRSxLQUFhLEVBQUUsRUFBRSxDQUFDLEdBQUcsSUFBSSxJQUFJLEtBQUssSUFBSSxLQUFLLEVBQUUsQ0FBQztBQUNuRyxNQUFNLFVBQVUsR0FBRyxDQUFDLElBQVksRUFBRSxLQUFhLEVBQUUsSUFBWSxFQUFFLEVBQUU7SUFDL0QsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUM5QixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2hCLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzlCLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNyRCxDQUFDLENBQUM7QUFDRixNQUFNLENBQUMsTUFBTSxVQUFVLEdBQUcsQ0FBQyxJQUFZLEVBQUUsRUFBRTtJQUN6QyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNsQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3BDLE1BQU0sSUFBSSxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFD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