@aztec/world-state 0.30.1 → 0.32.0
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.
- package/dest/synchronizer/server_world_state_synchronizer.d.ts +8 -4
- package/dest/synchronizer/server_world_state_synchronizer.d.ts.map +1 -1
- package/dest/synchronizer/server_world_state_synchronizer.js +40 -8
- package/dest/world-state-db/merkle_tree_db.d.ts +11 -2
- package/dest/world-state-db/merkle_tree_db.d.ts.map +1 -1
- package/dest/world-state-db/merkle_tree_db.js +2 -1
- package/dest/world-state-db/merkle_tree_operations.d.ts +36 -12
- package/dest/world-state-db/merkle_tree_operations.d.ts.map +1 -1
- package/dest/world-state-db/merkle_tree_operations.js +2 -1
- package/dest/world-state-db/merkle_tree_operations_facade.d.ts +18 -10
- package/dest/world-state-db/merkle_tree_operations_facade.d.ts.map +1 -1
- package/dest/world-state-db/merkle_tree_operations_facade.js +13 -3
- package/dest/world-state-db/merkle_tree_snapshot_operations_facade.d.ts +7 -7
- package/dest/world-state-db/merkle_tree_snapshot_operations_facade.d.ts.map +1 -1
- package/dest/world-state-db/merkle_tree_snapshot_operations_facade.js +13 -7
- package/dest/world-state-db/merkle_trees.d.ts +18 -9
- package/dest/world-state-db/merkle_trees.d.ts.map +1 -1
- package/dest/world-state-db/merkle_trees.js +60 -24
- package/package.json +7 -7
- package/src/synchronizer/server_world_state_synchronizer.ts +52 -10
- package/src/world-state-db/merkle_tree_db.ts +18 -3
- package/src/world-state-db/merkle_tree_operations.ts +48 -14
- package/src/world-state-db/merkle_tree_operations_facade.ts +40 -14
- package/src/world-state-db/merkle_tree_snapshot_operations_facade.ts +36 -16
- package/src/world-state-db/merkle_trees.ts +108 -33
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { L2Block, MerkleTreeId, SiblingPath } from '@aztec/circuit-types';
|
|
2
|
-
import { Header, NullifierLeafPreimage, StateReference } from '@aztec/circuits.js';
|
|
2
|
+
import { Fr, Header, NullifierLeafPreimage, StateReference } from '@aztec/circuits.js';
|
|
3
3
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
4
4
|
import { IndexedTreeLeafPreimage } from '@aztec/foundation/trees';
|
|
5
|
-
import { BatchInsertionResult } from '@aztec/merkle-tree';
|
|
5
|
+
import { AppendOnlyTree, BatchInsertionResult, IndexedTree } from '@aztec/merkle-tree';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Type alias for the nullifier tree ID.
|
|
@@ -32,6 +32,24 @@ export interface TreeInfo {
|
|
|
32
32
|
depth: number;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
export type MerkleTreeMap = {
|
|
36
|
+
[MerkleTreeId.NULLIFIER_TREE]: IndexedTree;
|
|
37
|
+
[MerkleTreeId.NOTE_HASH_TREE]: AppendOnlyTree<Fr>;
|
|
38
|
+
[MerkleTreeId.PUBLIC_DATA_TREE]: IndexedTree;
|
|
39
|
+
[MerkleTreeId.L1_TO_L2_MESSAGE_TREE]: AppendOnlyTree<Fr>;
|
|
40
|
+
[MerkleTreeId.ARCHIVE]: AppendOnlyTree<Fr>;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
type LeafTypes = {
|
|
44
|
+
[MerkleTreeId.NULLIFIER_TREE]: Buffer;
|
|
45
|
+
[MerkleTreeId.NOTE_HASH_TREE]: Fr;
|
|
46
|
+
[MerkleTreeId.PUBLIC_DATA_TREE]: Buffer;
|
|
47
|
+
[MerkleTreeId.L1_TO_L2_MESSAGE_TREE]: Fr;
|
|
48
|
+
[MerkleTreeId.ARCHIVE]: Fr;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export type MerkleTreeLeafType<ID extends MerkleTreeId> = LeafTypes[ID];
|
|
52
|
+
|
|
35
53
|
/**
|
|
36
54
|
* Defines the interface for operations on a set of Merkle Trees.
|
|
37
55
|
*/
|
|
@@ -41,7 +59,7 @@ export interface MerkleTreeOperations {
|
|
|
41
59
|
* @param treeId - The tree to be updated.
|
|
42
60
|
* @param leaves - The set of leaves to be appended.
|
|
43
61
|
*/
|
|
44
|
-
appendLeaves(treeId:
|
|
62
|
+
appendLeaves<ID extends MerkleTreeId>(treeId: ID, leaves: MerkleTreeLeafType<ID>[]): Promise<void>;
|
|
45
63
|
|
|
46
64
|
/**
|
|
47
65
|
* Returns information about the given tree.
|
|
@@ -71,8 +89,8 @@ export interface MerkleTreeOperations {
|
|
|
71
89
|
* @param treeId - The tree for which the previous value index is required.
|
|
72
90
|
* @param value - The value to be queried.
|
|
73
91
|
*/
|
|
74
|
-
getPreviousValueIndex(
|
|
75
|
-
treeId:
|
|
92
|
+
getPreviousValueIndex<ID extends IndexedTreeId>(
|
|
93
|
+
treeId: ID,
|
|
76
94
|
value: bigint,
|
|
77
95
|
): Promise<
|
|
78
96
|
| {
|
|
@@ -93,7 +111,7 @@ export interface MerkleTreeOperations {
|
|
|
93
111
|
* @param treeId - The tree for which leaf data should be returned.
|
|
94
112
|
* @param index - The index of the leaf required.
|
|
95
113
|
*/
|
|
96
|
-
getLeafPreimage(treeId:
|
|
114
|
+
getLeafPreimage<ID extends IndexedTreeId>(treeId: ID, index: bigint): Promise<IndexedTreeLeafPreimage | undefined>;
|
|
97
115
|
|
|
98
116
|
/**
|
|
99
117
|
* Update the leaf data at the given index.
|
|
@@ -101,21 +119,36 @@ export interface MerkleTreeOperations {
|
|
|
101
119
|
* @param leaf - The updated leaf value.
|
|
102
120
|
* @param index - The index of the leaf to be updated.
|
|
103
121
|
*/
|
|
104
|
-
updateLeaf(treeId:
|
|
122
|
+
updateLeaf<ID extends IndexedTreeId>(treeId: ID, leaf: NullifierLeafPreimage | Buffer, index: bigint): Promise<void>;
|
|
105
123
|
|
|
106
124
|
/**
|
|
107
125
|
* Returns the index containing a leaf value.
|
|
108
126
|
* @param treeId - The tree for which the index should be returned.
|
|
109
127
|
* @param value - The value to search for in the tree.
|
|
110
128
|
*/
|
|
111
|
-
findLeafIndex(treeId:
|
|
129
|
+
findLeafIndex<ID extends MerkleTreeId>(treeId: ID, value: MerkleTreeLeafType<ID>): Promise<bigint | undefined>;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Returns the first index containing a leaf value after `startIndex`.
|
|
133
|
+
* @param treeId - The tree for which the index should be returned.
|
|
134
|
+
* @param value - The value to search for in the tree.
|
|
135
|
+
* @param startIndex - The index to start searching from (used when skipping nullified messages)
|
|
136
|
+
*/
|
|
137
|
+
findLeafIndexAfter<ID extends MerkleTreeId>(
|
|
138
|
+
treeId: ID,
|
|
139
|
+
value: MerkleTreeLeafType<ID>,
|
|
140
|
+
startIndex: bigint,
|
|
141
|
+
): Promise<bigint | undefined>;
|
|
112
142
|
|
|
113
143
|
/**
|
|
114
144
|
* Gets the value for a leaf in the tree.
|
|
115
145
|
* @param treeId - The tree for which the index should be returned.
|
|
116
146
|
* @param index - The index of the leaf.
|
|
117
147
|
*/
|
|
118
|
-
getLeafValue
|
|
148
|
+
getLeafValue<ID extends MerkleTreeId>(
|
|
149
|
+
treeId: ID,
|
|
150
|
+
index: bigint,
|
|
151
|
+
): Promise<MerkleTreeLeafType<typeof treeId> | undefined>;
|
|
119
152
|
|
|
120
153
|
/**
|
|
121
154
|
* Inserts the block hash into the archive.
|
|
@@ -131,8 +164,8 @@ export interface MerkleTreeOperations {
|
|
|
131
164
|
* @param subtreeHeight - Height of the subtree.
|
|
132
165
|
* @returns The witness data for the leaves to be updated when inserting the new ones.
|
|
133
166
|
*/
|
|
134
|
-
batchInsert<TreeHeight extends number, SubtreeSiblingPathHeight extends number>(
|
|
135
|
-
treeId:
|
|
167
|
+
batchInsert<TreeHeight extends number, SubtreeSiblingPathHeight extends number, ID extends IndexedTreeId>(
|
|
168
|
+
treeId: ID,
|
|
136
169
|
leaves: Buffer[],
|
|
137
170
|
subtreeHeight: number,
|
|
138
171
|
): Promise<BatchInsertionResult<TreeHeight, SubtreeSiblingPathHeight>>;
|
|
@@ -140,8 +173,9 @@ export interface MerkleTreeOperations {
|
|
|
140
173
|
/**
|
|
141
174
|
* Handles a single L2 block (i.e. Inserts the new note hashes into the merkle tree).
|
|
142
175
|
* @param block - The L2 block to handle.
|
|
176
|
+
* @param l1ToL2Messages - The L1 to L2 messages for the block.
|
|
143
177
|
*/
|
|
144
|
-
|
|
178
|
+
handleL2BlockAndMessages(block: L2Block, l1ToL2Messages: Fr[]): Promise<HandleL2BlockAndMessagesResult>;
|
|
145
179
|
|
|
146
180
|
/**
|
|
147
181
|
* Commits pending changes to the underlying store.
|
|
@@ -154,8 +188,8 @@ export interface MerkleTreeOperations {
|
|
|
154
188
|
rollback(): Promise<void>;
|
|
155
189
|
}
|
|
156
190
|
|
|
157
|
-
/** Return type for
|
|
158
|
-
export type
|
|
191
|
+
/** Return type for handleL2BlockAndMessages */
|
|
192
|
+
export type HandleL2BlockAndMessagesResult = {
|
|
159
193
|
/** Whether the block processed was emitted by our sequencer */ isBlockOurs: boolean;
|
|
160
194
|
};
|
|
161
195
|
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { L2Block, MerkleTreeId, SiblingPath } from '@aztec/circuit-types';
|
|
2
|
-
import { Header, NullifierLeafPreimage, StateReference } from '@aztec/circuits.js';
|
|
2
|
+
import { Fr, Header, NullifierLeafPreimage, StateReference } from '@aztec/circuits.js';
|
|
3
3
|
import { IndexedTreeLeafPreimage } from '@aztec/foundation/trees';
|
|
4
4
|
import { BatchInsertionResult } from '@aztec/merkle-tree';
|
|
5
5
|
|
|
6
6
|
import { MerkleTreeDb } from './merkle_tree_db.js';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
HandleL2BlockAndMessagesResult,
|
|
9
|
+
IndexedTreeId,
|
|
10
|
+
MerkleTreeLeafType,
|
|
11
|
+
MerkleTreeOperations,
|
|
12
|
+
TreeInfo,
|
|
13
|
+
} from './merkle_tree_operations.js';
|
|
8
14
|
|
|
9
15
|
/**
|
|
10
16
|
* Wraps a MerkleTreeDbOperations to call all functions with a preset includeUncommitted flag.
|
|
@@ -44,7 +50,7 @@ export class MerkleTreeOperationsFacade implements MerkleTreeOperations {
|
|
|
44
50
|
* @param leaves - The set of leaves to be appended.
|
|
45
51
|
* @returns The tree info of the specified tree.
|
|
46
52
|
*/
|
|
47
|
-
appendLeaves(treeId:
|
|
53
|
+
appendLeaves<ID extends MerkleTreeId>(treeId: ID, leaves: MerkleTreeLeafType<ID>[]): Promise<void> {
|
|
48
54
|
return this.trees.appendLeaves(treeId, leaves);
|
|
49
55
|
}
|
|
50
56
|
|
|
@@ -66,8 +72,8 @@ export class MerkleTreeOperationsFacade implements MerkleTreeOperations {
|
|
|
66
72
|
* @param includeUncommitted - If true, the uncommitted changes are included in the search.
|
|
67
73
|
* @returns The found leaf index and a flag indicating if the corresponding leaf's value is equal to `newValue`.
|
|
68
74
|
*/
|
|
69
|
-
getPreviousValueIndex(
|
|
70
|
-
treeId:
|
|
75
|
+
getPreviousValueIndex<ID extends IndexedTreeId>(
|
|
76
|
+
treeId: ID,
|
|
71
77
|
value: bigint,
|
|
72
78
|
): Promise<
|
|
73
79
|
| {
|
|
@@ -92,7 +98,7 @@ export class MerkleTreeOperationsFacade implements MerkleTreeOperations {
|
|
|
92
98
|
* @param index - The index to insert into.
|
|
93
99
|
* @returns Empty promise.
|
|
94
100
|
*/
|
|
95
|
-
updateLeaf(treeId:
|
|
101
|
+
updateLeaf<ID extends IndexedTreeId>(treeId: ID, leaf: NullifierLeafPreimage, index: bigint): Promise<void> {
|
|
96
102
|
return this.trees.updateLeaf(treeId, leaf, index);
|
|
97
103
|
}
|
|
98
104
|
|
|
@@ -102,8 +108,8 @@ export class MerkleTreeOperationsFacade implements MerkleTreeOperations {
|
|
|
102
108
|
* @param index - The index of the leaf to get.
|
|
103
109
|
* @returns Leaf preimage.
|
|
104
110
|
*/
|
|
105
|
-
async getLeafPreimage(
|
|
106
|
-
treeId:
|
|
111
|
+
async getLeafPreimage<ID extends IndexedTreeId>(
|
|
112
|
+
treeId: ID,
|
|
107
113
|
index: bigint,
|
|
108
114
|
): Promise<IndexedTreeLeafPreimage | undefined> {
|
|
109
115
|
const preimage = await this.trees.getLeafPreimage(treeId, index, this.includeUncommitted);
|
|
@@ -116,10 +122,24 @@ export class MerkleTreeOperationsFacade implements MerkleTreeOperations {
|
|
|
116
122
|
* @param value - The leaf value to look for.
|
|
117
123
|
* @returns The index of the first leaf found with a given value (undefined if not found).
|
|
118
124
|
*/
|
|
119
|
-
findLeafIndex(treeId:
|
|
125
|
+
findLeafIndex<ID extends MerkleTreeId>(treeId: ID, value: MerkleTreeLeafType<ID>): Promise<bigint | undefined> {
|
|
120
126
|
return this.trees.findLeafIndex(treeId, value, this.includeUncommitted);
|
|
121
127
|
}
|
|
122
128
|
|
|
129
|
+
/**
|
|
130
|
+
* Returns the first index containing a leaf value after `startIndex`.
|
|
131
|
+
* @param treeId - The tree for which the index should be returned.
|
|
132
|
+
* @param value - The value to search for in the tree.
|
|
133
|
+
* @param startIndex - The index to start searching from (used when skipping nullified messages)
|
|
134
|
+
*/
|
|
135
|
+
findLeafIndexAfter<ID extends MerkleTreeId>(
|
|
136
|
+
treeId: ID,
|
|
137
|
+
value: MerkleTreeLeafType<ID>,
|
|
138
|
+
startIndex: bigint,
|
|
139
|
+
): Promise<bigint | undefined> {
|
|
140
|
+
return this.trees.findLeafIndexAfter(treeId, value, startIndex, this.includeUncommitted);
|
|
141
|
+
}
|
|
142
|
+
|
|
123
143
|
/**
|
|
124
144
|
* Gets the value at the given index.
|
|
125
145
|
* @param treeId - The ID of the tree to get the leaf value from.
|
|
@@ -127,8 +147,13 @@ export class MerkleTreeOperationsFacade implements MerkleTreeOperations {
|
|
|
127
147
|
* @param includeUncommitted - Indicates whether to include uncommitted changes.
|
|
128
148
|
* @returns Leaf value at the given index (undefined if not found).
|
|
129
149
|
*/
|
|
130
|
-
getLeafValue
|
|
131
|
-
|
|
150
|
+
getLeafValue<ID extends MerkleTreeId>(
|
|
151
|
+
treeId: ID,
|
|
152
|
+
index: bigint,
|
|
153
|
+
): Promise<MerkleTreeLeafType<typeof treeId> | undefined> {
|
|
154
|
+
return this.trees.getLeafValue(treeId, index, this.includeUncommitted) as Promise<
|
|
155
|
+
MerkleTreeLeafType<typeof treeId> | undefined
|
|
156
|
+
>;
|
|
132
157
|
}
|
|
133
158
|
|
|
134
159
|
/**
|
|
@@ -143,10 +168,11 @@ export class MerkleTreeOperationsFacade implements MerkleTreeOperations {
|
|
|
143
168
|
/**
|
|
144
169
|
* Handles a single L2 block (i.e. Inserts the new note hashes into the merkle tree).
|
|
145
170
|
* @param block - The L2 block to handle.
|
|
171
|
+
* @param l1ToL2Messages - The L1 to L2 messages for the block.
|
|
146
172
|
* @returns Whether the block handled was produced by this same node.
|
|
147
173
|
*/
|
|
148
|
-
public
|
|
149
|
-
return this.trees.
|
|
174
|
+
public handleL2BlockAndMessages(block: L2Block, l1ToL2Messages: Fr[]): Promise<HandleL2BlockAndMessagesResult> {
|
|
175
|
+
return this.trees.handleL2BlockAndMessages(block, l1ToL2Messages);
|
|
150
176
|
}
|
|
151
177
|
|
|
152
178
|
/**
|
|
@@ -173,7 +199,7 @@ export class MerkleTreeOperationsFacade implements MerkleTreeOperations {
|
|
|
173
199
|
* @returns The data for the leaves to be updated when inserting the new ones.
|
|
174
200
|
*/
|
|
175
201
|
public batchInsert<TreeHeight extends number, SubtreeSiblingPathHeight extends number>(
|
|
176
|
-
treeId:
|
|
202
|
+
treeId: IndexedTreeId,
|
|
177
203
|
leaves: Buffer[],
|
|
178
204
|
subtreeHeight: number,
|
|
179
205
|
): Promise<BatchInsertionResult<TreeHeight, SubtreeSiblingPathHeight>> {
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { MerkleTreeId, SiblingPath } from '@aztec/circuit-types';
|
|
2
2
|
import { AppendOnlyTreeSnapshot, Fr, Header, PartialStateReference, StateReference } from '@aztec/circuits.js';
|
|
3
3
|
import { IndexedTreeLeafPreimage } from '@aztec/foundation/trees';
|
|
4
|
-
import { BatchInsertionResult, IndexedTreeSnapshot
|
|
4
|
+
import { BatchInsertionResult, IndexedTreeSnapshot } from '@aztec/merkle-tree';
|
|
5
5
|
|
|
6
|
-
import { MerkleTreeDb } from './merkle_tree_db.js';
|
|
7
|
-
import {
|
|
6
|
+
import { MerkleTreeDb, TreeSnapshots } from './merkle_tree_db.js';
|
|
7
|
+
import {
|
|
8
|
+
HandleL2BlockAndMessagesResult,
|
|
9
|
+
IndexedTreeId,
|
|
10
|
+
MerkleTreeLeafType,
|
|
11
|
+
MerkleTreeOperations,
|
|
12
|
+
TreeInfo,
|
|
13
|
+
} from './merkle_tree_operations.js';
|
|
8
14
|
|
|
9
15
|
/**
|
|
10
16
|
* Merkle tree operations on readonly tree snapshots.
|
|
@@ -12,42 +18,56 @@ import { HandleL2BlockResult, MerkleTreeOperations, TreeInfo } from './merkle_tr
|
|
|
12
18
|
export class MerkleTreeSnapshotOperationsFacade implements MerkleTreeOperations {
|
|
13
19
|
#treesDb: MerkleTreeDb;
|
|
14
20
|
#blockNumber: number;
|
|
15
|
-
#treeSnapshots:
|
|
21
|
+
#treeSnapshots: TreeSnapshots = {} as any;
|
|
16
22
|
|
|
17
23
|
constructor(trees: MerkleTreeDb, blockNumber: number) {
|
|
18
24
|
this.#treesDb = trees;
|
|
19
25
|
this.#blockNumber = blockNumber;
|
|
20
26
|
}
|
|
21
27
|
|
|
22
|
-
async #getTreeSnapshot(
|
|
23
|
-
if (this.#treeSnapshots[
|
|
24
|
-
return this.#treeSnapshots[
|
|
28
|
+
async #getTreeSnapshot(treeId: MerkleTreeId): Promise<TreeSnapshots[typeof treeId]> {
|
|
29
|
+
if (this.#treeSnapshots[treeId]) {
|
|
30
|
+
return this.#treeSnapshots[treeId];
|
|
25
31
|
}
|
|
26
32
|
|
|
27
33
|
this.#treeSnapshots = await this.#treesDb.getSnapshot(this.#blockNumber);
|
|
28
|
-
return this.#treeSnapshots[
|
|
34
|
+
return this.#treeSnapshots[treeId]!;
|
|
29
35
|
}
|
|
30
36
|
|
|
31
|
-
async findLeafIndex(treeId:
|
|
37
|
+
async findLeafIndex<ID extends MerkleTreeId>(treeId: ID, value: MerkleTreeLeafType<ID>): Promise<bigint | undefined> {
|
|
32
38
|
const tree = await this.#getTreeSnapshot(treeId);
|
|
33
|
-
|
|
39
|
+
// TODO #5448 fix "as any"
|
|
40
|
+
return tree.findLeafIndex(value as any);
|
|
34
41
|
}
|
|
35
42
|
|
|
36
|
-
async
|
|
37
|
-
treeId: MerkleTreeId
|
|
43
|
+
async findLeafIndexAfter<ID extends MerkleTreeId>(
|
|
44
|
+
treeId: MerkleTreeId,
|
|
45
|
+
value: MerkleTreeLeafType<ID>,
|
|
46
|
+
startIndex: bigint,
|
|
47
|
+
): Promise<bigint | undefined> {
|
|
48
|
+
const tree = await this.#getTreeSnapshot(treeId);
|
|
49
|
+
// TODO #5448 fix "as any"
|
|
50
|
+
return tree.findLeafIndexAfter(value as any, startIndex);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async getLeafPreimage<ID extends IndexedTreeId>(
|
|
54
|
+
treeId: ID,
|
|
38
55
|
index: bigint,
|
|
39
56
|
): Promise<IndexedTreeLeafPreimage | undefined> {
|
|
40
57
|
const snapshot = (await this.#getTreeSnapshot(treeId)) as IndexedTreeSnapshot;
|
|
41
58
|
return snapshot.getLatestLeafPreimageCopy(BigInt(index));
|
|
42
59
|
}
|
|
43
60
|
|
|
44
|
-
async getLeafValue
|
|
61
|
+
async getLeafValue<ID extends MerkleTreeId>(
|
|
62
|
+
treeId: ID,
|
|
63
|
+
index: bigint,
|
|
64
|
+
): Promise<MerkleTreeLeafType<typeof treeId> | undefined> {
|
|
45
65
|
const snapshot = await this.#getTreeSnapshot(treeId);
|
|
46
|
-
return snapshot.getLeafValue(BigInt(index));
|
|
66
|
+
return snapshot.getLeafValue(BigInt(index)) as MerkleTreeLeafType<typeof treeId> | undefined;
|
|
47
67
|
}
|
|
48
68
|
|
|
49
69
|
async getPreviousValueIndex(
|
|
50
|
-
treeId:
|
|
70
|
+
treeId: IndexedTreeId,
|
|
51
71
|
value: bigint,
|
|
52
72
|
): Promise<
|
|
53
73
|
| {
|
|
@@ -130,7 +150,7 @@ export class MerkleTreeSnapshotOperationsFacade implements MerkleTreeOperations
|
|
|
130
150
|
return Promise.reject(new Error('Tree snapshot operations are read-only'));
|
|
131
151
|
}
|
|
132
152
|
|
|
133
|
-
|
|
153
|
+
handleL2BlockAndMessages(): Promise<HandleL2BlockAndMessagesResult> {
|
|
134
154
|
return Promise.reject(new Error('Tree snapshot operations are read-only'));
|
|
135
155
|
}
|
|
136
156
|
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
NOTE_HASH_TREE_HEIGHT,
|
|
12
12
|
NULLIFIER_SUBTREE_HEIGHT,
|
|
13
13
|
NULLIFIER_TREE_HEIGHT,
|
|
14
|
+
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
14
15
|
NullifierLeaf,
|
|
15
16
|
NullifierLeafPreimage,
|
|
16
17
|
PUBLIC_DATA_SUBTREE_HEIGHT,
|
|
@@ -20,6 +21,7 @@ import {
|
|
|
20
21
|
PublicDataTreeLeafPreimage,
|
|
21
22
|
StateReference,
|
|
22
23
|
} from '@aztec/circuits.js';
|
|
24
|
+
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
23
25
|
import { SerialQueue } from '@aztec/foundation/fifo';
|
|
24
26
|
import { DebugLogger, createDebugLogger } from '@aztec/foundation/log';
|
|
25
27
|
import { IndexedTreeLeafPreimage } from '@aztec/foundation/trees';
|
|
@@ -38,15 +40,35 @@ import {
|
|
|
38
40
|
} from '@aztec/merkle-tree';
|
|
39
41
|
import { Hasher } from '@aztec/types/interfaces';
|
|
40
42
|
|
|
41
|
-
import {
|
|
42
|
-
|
|
43
|
+
import {
|
|
44
|
+
INITIAL_NULLIFIER_TREE_SIZE,
|
|
45
|
+
INITIAL_PUBLIC_DATA_TREE_SIZE,
|
|
46
|
+
MerkleTreeDb,
|
|
47
|
+
TreeSnapshots,
|
|
48
|
+
} from './merkle_tree_db.js';
|
|
49
|
+
import {
|
|
50
|
+
HandleL2BlockAndMessagesResult,
|
|
51
|
+
IndexedTreeId,
|
|
52
|
+
MerkleTreeLeafType,
|
|
53
|
+
MerkleTreeMap,
|
|
54
|
+
MerkleTreeOperations,
|
|
55
|
+
TreeInfo,
|
|
56
|
+
} from './merkle_tree_operations.js';
|
|
43
57
|
import { MerkleTreeOperationsFacade } from './merkle_tree_operations_facade.js';
|
|
44
58
|
|
|
45
59
|
/**
|
|
46
60
|
* The nullifier tree is an indexed tree.
|
|
47
61
|
*/
|
|
48
62
|
class NullifierTree extends StandardIndexedTree {
|
|
49
|
-
constructor(
|
|
63
|
+
constructor(
|
|
64
|
+
store: AztecKVStore,
|
|
65
|
+
hasher: Hasher,
|
|
66
|
+
name: string,
|
|
67
|
+
depth: number,
|
|
68
|
+
size: bigint = 0n,
|
|
69
|
+
_noop: any,
|
|
70
|
+
root?: Buffer,
|
|
71
|
+
) {
|
|
50
72
|
super(store, hasher, name, depth, size, NullifierLeafPreimage, NullifierLeaf, root);
|
|
51
73
|
}
|
|
52
74
|
}
|
|
@@ -55,7 +77,15 @@ class NullifierTree extends StandardIndexedTree {
|
|
|
55
77
|
* The public data tree is an indexed tree.
|
|
56
78
|
*/
|
|
57
79
|
class PublicDataTree extends StandardIndexedTree {
|
|
58
|
-
constructor(
|
|
80
|
+
constructor(
|
|
81
|
+
store: AztecKVStore,
|
|
82
|
+
hasher: Hasher,
|
|
83
|
+
name: string,
|
|
84
|
+
depth: number,
|
|
85
|
+
size: bigint = 0n,
|
|
86
|
+
_noop: any,
|
|
87
|
+
root?: Buffer,
|
|
88
|
+
) {
|
|
59
89
|
super(store, hasher, name, depth, size, PublicDataTreeLeafPreimage, PublicDataTreeLeaf, root);
|
|
60
90
|
}
|
|
61
91
|
}
|
|
@@ -64,7 +94,8 @@ class PublicDataTree extends StandardIndexedTree {
|
|
|
64
94
|
* A convenience class for managing multiple merkle trees.
|
|
65
95
|
*/
|
|
66
96
|
export class MerkleTrees implements MerkleTreeDb {
|
|
67
|
-
|
|
97
|
+
// gets initialized in #init
|
|
98
|
+
private trees: MerkleTreeMap = null as any;
|
|
68
99
|
private jobQueue = new SerialQueue();
|
|
69
100
|
|
|
70
101
|
private constructor(private store: AztecKVStore, private log: DebugLogger) {}
|
|
@@ -94,14 +125,16 @@ export class MerkleTrees implements MerkleTreeDb {
|
|
|
94
125
|
this.store,
|
|
95
126
|
hasher,
|
|
96
127
|
`${MerkleTreeId[MerkleTreeId.NULLIFIER_TREE]}`,
|
|
128
|
+
{},
|
|
97
129
|
NULLIFIER_TREE_HEIGHT,
|
|
98
130
|
INITIAL_NULLIFIER_TREE_SIZE,
|
|
99
131
|
);
|
|
100
|
-
const noteHashTree: AppendOnlyTree = await initializeTree(
|
|
132
|
+
const noteHashTree: AppendOnlyTree<Fr> = await initializeTree(
|
|
101
133
|
StandardTree,
|
|
102
134
|
this.store,
|
|
103
135
|
hasher,
|
|
104
136
|
`${MerkleTreeId[MerkleTreeId.NOTE_HASH_TREE]}`,
|
|
137
|
+
Fr,
|
|
105
138
|
NOTE_HASH_TREE_HEIGHT,
|
|
106
139
|
);
|
|
107
140
|
const publicDataTree = await initializeTree(
|
|
@@ -109,21 +142,24 @@ export class MerkleTrees implements MerkleTreeDb {
|
|
|
109
142
|
this.store,
|
|
110
143
|
hasher,
|
|
111
144
|
`${MerkleTreeId[MerkleTreeId.PUBLIC_DATA_TREE]}`,
|
|
145
|
+
{},
|
|
112
146
|
PUBLIC_DATA_TREE_HEIGHT,
|
|
113
147
|
INITIAL_PUBLIC_DATA_TREE_SIZE,
|
|
114
148
|
);
|
|
115
|
-
const l1Tol2MessageTree: AppendOnlyTree = await initializeTree(
|
|
149
|
+
const l1Tol2MessageTree: AppendOnlyTree<Fr> = await initializeTree(
|
|
116
150
|
StandardTree,
|
|
117
151
|
this.store,
|
|
118
152
|
hasher,
|
|
119
153
|
`${MerkleTreeId[MerkleTreeId.L1_TO_L2_MESSAGE_TREE]}`,
|
|
154
|
+
Fr,
|
|
120
155
|
L1_TO_L2_MSG_TREE_HEIGHT,
|
|
121
156
|
);
|
|
122
|
-
const archive: AppendOnlyTree = await initializeTree(
|
|
157
|
+
const archive: AppendOnlyTree<Fr> = await initializeTree(
|
|
123
158
|
StandardTree,
|
|
124
159
|
this.store,
|
|
125
160
|
hasher,
|
|
126
161
|
`${MerkleTreeId[MerkleTreeId.ARCHIVE]}`,
|
|
162
|
+
Fr,
|
|
127
163
|
ARCHIVE_HEIGHT,
|
|
128
164
|
);
|
|
129
165
|
this.trees = [nullifierTree, noteHashTree, publicDataTree, l1Tol2MessageTree, archive];
|
|
@@ -223,7 +259,7 @@ export class MerkleTrees implements MerkleTreeDb {
|
|
|
223
259
|
treeId: MerkleTreeId,
|
|
224
260
|
index: bigint,
|
|
225
261
|
includeUncommitted: boolean,
|
|
226
|
-
): Promise<
|
|
262
|
+
): Promise<MerkleTreeLeafType<typeof treeId> | undefined> {
|
|
227
263
|
return await this.synchronize(() => Promise.resolve(this.trees[treeId].getLeafValue(index, includeUncommitted)));
|
|
228
264
|
}
|
|
229
265
|
|
|
@@ -248,7 +284,7 @@ export class MerkleTrees implements MerkleTreeDb {
|
|
|
248
284
|
* @param leaves - The leaves to append.
|
|
249
285
|
* @returns Empty promise.
|
|
250
286
|
*/
|
|
251
|
-
public async appendLeaves(treeId:
|
|
287
|
+
public async appendLeaves<ID extends MerkleTreeId>(treeId: ID, leaves: MerkleTreeLeafType<ID>[]): Promise<void> {
|
|
252
288
|
return await this.synchronize(() => this.#appendLeaves(treeId, leaves));
|
|
253
289
|
}
|
|
254
290
|
|
|
@@ -321,14 +357,35 @@ export class MerkleTrees implements MerkleTreeDb {
|
|
|
321
357
|
* @param includeUncommitted - Indicates whether to include uncommitted data.
|
|
322
358
|
* @returns The index of the first leaf found with a given value (undefined if not found).
|
|
323
359
|
*/
|
|
324
|
-
public async findLeafIndex(
|
|
325
|
-
treeId:
|
|
326
|
-
value:
|
|
360
|
+
public async findLeafIndex<ID extends MerkleTreeId>(
|
|
361
|
+
treeId: ID,
|
|
362
|
+
value: MerkleTreeLeafType<ID>,
|
|
363
|
+
includeUncommitted: boolean,
|
|
364
|
+
): Promise<bigint | undefined> {
|
|
365
|
+
return await this.synchronize(() => {
|
|
366
|
+
const tree = this.trees[treeId];
|
|
367
|
+
// TODO #5448 fix "as any"
|
|
368
|
+
return Promise.resolve(tree.findLeafIndex(value as any, includeUncommitted));
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Returns the first index containing a leaf value after `startIndex`.
|
|
374
|
+
* @param treeId - The tree for which the index should be returned.
|
|
375
|
+
* @param value - The value to search for in the tree.
|
|
376
|
+
* @param startIndex - The index to start searching from (used when skipping nullified messages)
|
|
377
|
+
* @param includeUncommitted - Indicates whether to include uncommitted data.
|
|
378
|
+
*/
|
|
379
|
+
public async findLeafIndexAfter<ID extends MerkleTreeId>(
|
|
380
|
+
treeId: ID,
|
|
381
|
+
value: MerkleTreeLeafType<ID>,
|
|
382
|
+
startIndex: bigint,
|
|
327
383
|
includeUncommitted: boolean,
|
|
328
384
|
): Promise<bigint | undefined> {
|
|
329
385
|
return await this.synchronize(() => {
|
|
330
386
|
const tree = this.trees[treeId];
|
|
331
|
-
|
|
387
|
+
// TODO #5448 fix "as any"
|
|
388
|
+
return Promise.resolve(tree.findLeafIndexAfter(value as any, startIndex, includeUncommitted));
|
|
332
389
|
});
|
|
333
390
|
}
|
|
334
391
|
|
|
@@ -346,10 +403,11 @@ export class MerkleTrees implements MerkleTreeDb {
|
|
|
346
403
|
/**
|
|
347
404
|
* Handles a single L2 block (i.e. Inserts the new note hashes into the merkle tree).
|
|
348
405
|
* @param block - The L2 block to handle.
|
|
406
|
+
* @param l1ToL2Messages - The L1 to L2 messages for the block.
|
|
349
407
|
* @returns Whether the block handled was produced by this same node.
|
|
350
408
|
*/
|
|
351
|
-
public async
|
|
352
|
-
return await this.synchronize(() => this.#
|
|
409
|
+
public async handleL2BlockAndMessages(block: L2Block, l1ToL2Messages: Fr[]): Promise<HandleL2BlockAndMessagesResult> {
|
|
410
|
+
return await this.synchronize(() => this.#handleL2BlockAndMessages(block, l1ToL2Messages));
|
|
353
411
|
}
|
|
354
412
|
|
|
355
413
|
/**
|
|
@@ -364,7 +422,7 @@ export class MerkleTrees implements MerkleTreeDb {
|
|
|
364
422
|
SubtreeHeight extends number,
|
|
365
423
|
SubtreeSiblingPathHeight extends number,
|
|
366
424
|
>(
|
|
367
|
-
treeId:
|
|
425
|
+
treeId: IndexedTreeId,
|
|
368
426
|
leaves: Buffer[],
|
|
369
427
|
subtreeHeight: SubtreeHeight,
|
|
370
428
|
): Promise<BatchInsertionResult<TreeHeight, SubtreeSiblingPathHeight>> {
|
|
@@ -394,7 +452,7 @@ export class MerkleTrees implements MerkleTreeDb {
|
|
|
394
452
|
}
|
|
395
453
|
|
|
396
454
|
const blockHash = header.hash();
|
|
397
|
-
await this.#appendLeaves(MerkleTreeId.ARCHIVE, [blockHash
|
|
455
|
+
await this.#appendLeaves(MerkleTreeId.ARCHIVE, [blockHash]);
|
|
398
456
|
}
|
|
399
457
|
|
|
400
458
|
/**
|
|
@@ -428,20 +486,21 @@ export class MerkleTrees implements MerkleTreeDb {
|
|
|
428
486
|
* @param leaves - Leaves to append.
|
|
429
487
|
* @returns Empty promise.
|
|
430
488
|
*/
|
|
431
|
-
async #appendLeaves(treeId:
|
|
489
|
+
async #appendLeaves<ID extends MerkleTreeId>(treeId: ID, leaves: MerkleTreeLeafType<typeof treeId>[]): Promise<void> {
|
|
432
490
|
const tree = this.trees[treeId];
|
|
433
491
|
if (!('appendLeaves' in tree)) {
|
|
434
492
|
throw new Error('Tree does not support `appendLeaves` method');
|
|
435
493
|
}
|
|
436
|
-
|
|
494
|
+
// TODO #5448 fix "as any"
|
|
495
|
+
return await tree.appendLeaves(leaves as any[]);
|
|
437
496
|
}
|
|
438
497
|
|
|
439
|
-
async #updateLeaf(treeId: IndexedTreeId, leaf:
|
|
498
|
+
async #updateLeaf(treeId: IndexedTreeId, leaf: MerkleTreeLeafType<typeof treeId>, index: bigint): Promise<void> {
|
|
440
499
|
const tree = this.trees[treeId];
|
|
441
500
|
if (!('updateLeaf' in tree)) {
|
|
442
501
|
throw new Error('Tree does not support `updateLeaf` method');
|
|
443
502
|
}
|
|
444
|
-
return await tree.updateLeaf(leaf, index);
|
|
503
|
+
return await (tree as UpdateOnlyTree<typeof leaf>).updateLeaf(leaf, index);
|
|
445
504
|
}
|
|
446
505
|
|
|
447
506
|
/**
|
|
@@ -449,7 +508,7 @@ export class MerkleTrees implements MerkleTreeDb {
|
|
|
449
508
|
* @returns Empty promise.
|
|
450
509
|
*/
|
|
451
510
|
async #commit(): Promise<void> {
|
|
452
|
-
for (const tree of this.trees) {
|
|
511
|
+
for (const tree of Object.values(this.trees)) {
|
|
453
512
|
await tree.commit();
|
|
454
513
|
}
|
|
455
514
|
}
|
|
@@ -459,17 +518,31 @@ export class MerkleTrees implements MerkleTreeDb {
|
|
|
459
518
|
* @returns Empty promise.
|
|
460
519
|
*/
|
|
461
520
|
async #rollback(): Promise<void> {
|
|
462
|
-
for (const tree of this.trees) {
|
|
521
|
+
for (const tree of Object.values(this.trees)) {
|
|
463
522
|
await tree.rollback();
|
|
464
523
|
}
|
|
465
524
|
}
|
|
466
525
|
|
|
467
|
-
public getSnapshot(blockNumber: number) {
|
|
468
|
-
|
|
526
|
+
public async getSnapshot(blockNumber: number): Promise<TreeSnapshots> {
|
|
527
|
+
const snapshots = await Promise.all([
|
|
528
|
+
this.trees[MerkleTreeId.NULLIFIER_TREE].getSnapshot(blockNumber),
|
|
529
|
+
this.trees[MerkleTreeId.NOTE_HASH_TREE].getSnapshot(blockNumber),
|
|
530
|
+
this.trees[MerkleTreeId.PUBLIC_DATA_TREE].getSnapshot(blockNumber),
|
|
531
|
+
this.trees[MerkleTreeId.L1_TO_L2_MESSAGE_TREE].getSnapshot(blockNumber),
|
|
532
|
+
this.trees[MerkleTreeId.ARCHIVE].getSnapshot(blockNumber),
|
|
533
|
+
]);
|
|
534
|
+
|
|
535
|
+
return {
|
|
536
|
+
[MerkleTreeId.NULLIFIER_TREE]: snapshots[0],
|
|
537
|
+
[MerkleTreeId.NOTE_HASH_TREE]: snapshots[1],
|
|
538
|
+
[MerkleTreeId.PUBLIC_DATA_TREE]: snapshots[2],
|
|
539
|
+
[MerkleTreeId.L1_TO_L2_MESSAGE_TREE]: snapshots[3],
|
|
540
|
+
[MerkleTreeId.ARCHIVE]: snapshots[4],
|
|
541
|
+
};
|
|
469
542
|
}
|
|
470
543
|
|
|
471
544
|
async #snapshot(blockNumber: number): Promise<void> {
|
|
472
|
-
for (const tree of this.trees) {
|
|
545
|
+
for (const tree of Object.values(this.trees)) {
|
|
473
546
|
await tree.snapshot(blockNumber);
|
|
474
547
|
}
|
|
475
548
|
}
|
|
@@ -477,8 +550,9 @@ export class MerkleTrees implements MerkleTreeDb {
|
|
|
477
550
|
/**
|
|
478
551
|
* Handles a single L2 block (i.e. Inserts the new note hashes into the merkle tree).
|
|
479
552
|
* @param l2Block - The L2 block to handle.
|
|
553
|
+
* @param l1ToL2Messages - The L1 to L2 messages for the block.
|
|
480
554
|
*/
|
|
481
|
-
async #
|
|
555
|
+
async #handleL2BlockAndMessages(l2Block: L2Block, l1ToL2Messages: Fr[]): Promise<HandleL2BlockAndMessagesResult> {
|
|
482
556
|
const treeRootWithIdPairs = [
|
|
483
557
|
[l2Block.header.state.partial.nullifierTree.root, MerkleTreeId.NULLIFIER_TREE],
|
|
484
558
|
[l2Block.header.state.partial.noteHashTree.root, MerkleTreeId.NOTE_HASH_TREE],
|
|
@@ -498,15 +572,16 @@ export class MerkleTrees implements MerkleTreeDb {
|
|
|
498
572
|
this.log(`Block ${l2Block.number} is not ours, rolling back world state and committing state from chain`);
|
|
499
573
|
await this.#rollback();
|
|
500
574
|
|
|
575
|
+
// We pad the messages because always a fixed number of messages is inserted and we need
|
|
576
|
+
// the `nextAvailableLeafIndex` to correctly progress.
|
|
577
|
+
const l1ToL2MessagesPadded = padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
|
|
578
|
+
|
|
501
579
|
// Sync the append only trees
|
|
502
580
|
for (const [tree, leaves] of [
|
|
503
581
|
[MerkleTreeId.NOTE_HASH_TREE, l2Block.body.txEffects.flatMap(txEffect => txEffect.noteHashes)],
|
|
504
|
-
[MerkleTreeId.L1_TO_L2_MESSAGE_TREE,
|
|
582
|
+
[MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded],
|
|
505
583
|
] as const) {
|
|
506
|
-
await this.#appendLeaves(
|
|
507
|
-
tree,
|
|
508
|
-
leaves.map(fr => fr.toBuffer()),
|
|
509
|
-
);
|
|
584
|
+
await this.#appendLeaves(tree, leaves);
|
|
510
585
|
}
|
|
511
586
|
|
|
512
587
|
// Sync the indexed trees
|