@aztec/world-state 0.0.0-test.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.
Files changed (74) hide show
  1. package/README.md +40 -0
  2. package/dest/index.d.ts +5 -0
  3. package/dest/index.d.ts.map +1 -0
  4. package/dest/index.js +4 -0
  5. package/dest/instrumentation/instrumentation.d.ts +22 -0
  6. package/dest/instrumentation/instrumentation.d.ts.map +1 -0
  7. package/dest/instrumentation/instrumentation.js +117 -0
  8. package/dest/native/fork_checkpoint.d.ts +10 -0
  9. package/dest/native/fork_checkpoint.d.ts.map +1 -0
  10. package/dest/native/fork_checkpoint.js +26 -0
  11. package/dest/native/index.d.ts +3 -0
  12. package/dest/native/index.d.ts.map +1 -0
  13. package/dest/native/index.js +2 -0
  14. package/dest/native/merkle_trees_facade.d.ts +42 -0
  15. package/dest/native/merkle_trees_facade.d.ts.map +1 -0
  16. package/dest/native/merkle_trees_facade.js +240 -0
  17. package/dest/native/message.d.ts +331 -0
  18. package/dest/native/message.d.ts.map +1 -0
  19. package/dest/native/message.js +192 -0
  20. package/dest/native/native_world_state.d.ts +57 -0
  21. package/dest/native/native_world_state.d.ts.map +1 -0
  22. package/dest/native/native_world_state.js +229 -0
  23. package/dest/native/native_world_state_instance.d.ts +33 -0
  24. package/dest/native/native_world_state_instance.d.ts.map +1 -0
  25. package/dest/native/native_world_state_instance.js +164 -0
  26. package/dest/native/world_state_ops_queue.d.ts +19 -0
  27. package/dest/native/world_state_ops_queue.d.ts.map +1 -0
  28. package/dest/native/world_state_ops_queue.js +146 -0
  29. package/dest/synchronizer/config.d.ts +23 -0
  30. package/dest/synchronizer/config.d.ts.map +1 -0
  31. package/dest/synchronizer/config.js +39 -0
  32. package/dest/synchronizer/factory.d.ts +12 -0
  33. package/dest/synchronizer/factory.d.ts.map +1 -0
  34. package/dest/synchronizer/factory.js +24 -0
  35. package/dest/synchronizer/index.d.ts +3 -0
  36. package/dest/synchronizer/index.d.ts.map +1 -0
  37. package/dest/synchronizer/index.js +2 -0
  38. package/dest/synchronizer/server_world_state_synchronizer.d.ts +79 -0
  39. package/dest/synchronizer/server_world_state_synchronizer.d.ts.map +1 -0
  40. package/dest/synchronizer/server_world_state_synchronizer.js +277 -0
  41. package/dest/test/index.d.ts +2 -0
  42. package/dest/test/index.d.ts.map +1 -0
  43. package/dest/test/index.js +1 -0
  44. package/dest/test/utils.d.ts +19 -0
  45. package/dest/test/utils.d.ts.map +1 -0
  46. package/dest/test/utils.js +99 -0
  47. package/dest/testing.d.ts +10 -0
  48. package/dest/testing.d.ts.map +1 -0
  49. package/dest/testing.js +37 -0
  50. package/dest/world-state-db/index.d.ts +3 -0
  51. package/dest/world-state-db/index.d.ts.map +1 -0
  52. package/dest/world-state-db/index.js +1 -0
  53. package/dest/world-state-db/merkle_tree_db.d.ts +68 -0
  54. package/dest/world-state-db/merkle_tree_db.d.ts.map +1 -0
  55. package/dest/world-state-db/merkle_tree_db.js +17 -0
  56. package/package.json +98 -0
  57. package/src/index.ts +4 -0
  58. package/src/instrumentation/instrumentation.ts +174 -0
  59. package/src/native/fork_checkpoint.ts +30 -0
  60. package/src/native/index.ts +2 -0
  61. package/src/native/merkle_trees_facade.ts +331 -0
  62. package/src/native/message.ts +541 -0
  63. package/src/native/native_world_state.ts +317 -0
  64. package/src/native/native_world_state_instance.ts +238 -0
  65. package/src/native/world_state_ops_queue.ts +190 -0
  66. package/src/synchronizer/config.ts +68 -0
  67. package/src/synchronizer/factory.ts +53 -0
  68. package/src/synchronizer/index.ts +2 -0
  69. package/src/synchronizer/server_world_state_synchronizer.ts +344 -0
  70. package/src/test/index.ts +1 -0
  71. package/src/test/utils.ts +153 -0
  72. package/src/testing.ts +60 -0
  73. package/src/world-state-db/index.ts +3 -0
  74. package/src/world-state-db/merkle_tree_db.ts +79 -0
@@ -0,0 +1,331 @@
1
+ import { Fr } from '@aztec/foundation/fields';
2
+ import { serializeToBuffer } from '@aztec/foundation/serialize';
3
+ import { type IndexedTreeLeafPreimage, SiblingPath } from '@aztec/foundation/trees';
4
+ import type {
5
+ BatchInsertionResult,
6
+ IndexedTreeId,
7
+ MerkleTreeLeafType,
8
+ MerkleTreeReadOperations,
9
+ MerkleTreeWriteOperations,
10
+ SequentialInsertionResult,
11
+ TreeInfo,
12
+ } from '@aztec/stdlib/interfaces/server';
13
+ import {
14
+ MerkleTreeId,
15
+ NullifierLeaf,
16
+ NullifierLeafPreimage,
17
+ PublicDataTreeLeaf,
18
+ PublicDataTreeLeafPreimage,
19
+ } from '@aztec/stdlib/trees';
20
+ import { type BlockHeader, PartialStateReference, StateReference } from '@aztec/stdlib/tx';
21
+
22
+ import assert from 'assert';
23
+
24
+ import {
25
+ type SerializedIndexedLeaf,
26
+ type SerializedLeafValue,
27
+ WorldStateMessageType,
28
+ type WorldStateRevision,
29
+ blockStateReference,
30
+ treeStateReferenceToSnapshot,
31
+ } from './message.js';
32
+ import type { NativeWorldStateInstance } from './native_world_state_instance.js';
33
+
34
+ export class MerkleTreesFacade implements MerkleTreeReadOperations {
35
+ constructor(
36
+ protected readonly instance: NativeWorldStateInstance,
37
+ protected readonly initialHeader: BlockHeader,
38
+ protected readonly revision: WorldStateRevision,
39
+ ) {}
40
+
41
+ getInitialHeader(): BlockHeader {
42
+ return this.initialHeader;
43
+ }
44
+
45
+ findLeafIndices(treeId: MerkleTreeId, values: MerkleTreeLeafType<MerkleTreeId>[]): Promise<(bigint | undefined)[]> {
46
+ return this.findLeafIndicesAfter(treeId, values, 0n);
47
+ }
48
+
49
+ async findLeafIndicesAfter(
50
+ treeId: MerkleTreeId,
51
+ leaves: MerkleTreeLeafType<MerkleTreeId>[],
52
+ startIndex: bigint,
53
+ ): Promise<(bigint | undefined)[]> {
54
+ const response = await this.instance.call(WorldStateMessageType.FIND_LEAF_INDICES, {
55
+ leaves: leaves.map(leaf => serializeLeaf(hydrateLeaf(treeId, leaf))),
56
+ revision: this.revision,
57
+ treeId,
58
+ startIndex,
59
+ });
60
+
61
+ return response.indices.map(index => {
62
+ if (typeof index === 'number' || typeof index === 'bigint') {
63
+ return BigInt(index);
64
+ } else {
65
+ return undefined;
66
+ }
67
+ });
68
+ }
69
+
70
+ async getLeafPreimage(treeId: IndexedTreeId, leafIndex: bigint): Promise<IndexedTreeLeafPreimage | undefined> {
71
+ const resp = await this.instance.call(WorldStateMessageType.GET_LEAF_PREIMAGE, {
72
+ leafIndex,
73
+ revision: this.revision,
74
+ treeId,
75
+ });
76
+
77
+ return resp ? deserializeIndexedLeaf(resp) : undefined;
78
+ }
79
+
80
+ async getLeafValue<ID extends MerkleTreeId>(
81
+ treeId: ID,
82
+ leafIndex: bigint,
83
+ ): Promise<MerkleTreeLeafType<ID> | undefined> {
84
+ const resp = await this.instance.call(WorldStateMessageType.GET_LEAF_VALUE, {
85
+ leafIndex,
86
+ revision: this.revision,
87
+ treeId,
88
+ });
89
+
90
+ if (!resp) {
91
+ return undefined;
92
+ }
93
+
94
+ const leaf = deserializeLeafValue(resp);
95
+ if (leaf instanceof Fr) {
96
+ return leaf as any;
97
+ } else {
98
+ return leaf.toBuffer() as any;
99
+ }
100
+ }
101
+
102
+ async getPreviousValueIndex(
103
+ treeId: IndexedTreeId,
104
+ value: bigint,
105
+ ): Promise<{ index: bigint; alreadyPresent: boolean } | undefined> {
106
+ const resp = await this.instance.call(WorldStateMessageType.FIND_LOW_LEAF, {
107
+ key: new Fr(value),
108
+ revision: this.revision,
109
+ treeId,
110
+ });
111
+ return {
112
+ alreadyPresent: resp.alreadyPresent,
113
+ index: BigInt(resp.index),
114
+ };
115
+ }
116
+
117
+ async getSiblingPath<N extends number>(treeId: MerkleTreeId, leafIndex: bigint): Promise<SiblingPath<N>> {
118
+ const siblingPath = await this.instance.call(WorldStateMessageType.GET_SIBLING_PATH, {
119
+ leafIndex,
120
+ revision: this.revision,
121
+ treeId,
122
+ });
123
+
124
+ return new SiblingPath(siblingPath.length, siblingPath) as any;
125
+ }
126
+
127
+ async getStateReference(): Promise<StateReference> {
128
+ const resp = await this.instance.call(WorldStateMessageType.GET_STATE_REFERENCE, {
129
+ revision: this.revision,
130
+ });
131
+
132
+ return new StateReference(
133
+ treeStateReferenceToSnapshot(resp.state[MerkleTreeId.L1_TO_L2_MESSAGE_TREE]),
134
+ new PartialStateReference(
135
+ treeStateReferenceToSnapshot(resp.state[MerkleTreeId.NOTE_HASH_TREE]),
136
+ treeStateReferenceToSnapshot(resp.state[MerkleTreeId.NULLIFIER_TREE]),
137
+ treeStateReferenceToSnapshot(resp.state[MerkleTreeId.PUBLIC_DATA_TREE]),
138
+ ),
139
+ );
140
+ }
141
+
142
+ async getInitialStateReference(): Promise<StateReference> {
143
+ const resp = await this.instance.call(WorldStateMessageType.GET_INITIAL_STATE_REFERENCE, { canonical: true });
144
+
145
+ return new StateReference(
146
+ treeStateReferenceToSnapshot(resp.state[MerkleTreeId.L1_TO_L2_MESSAGE_TREE]),
147
+ new PartialStateReference(
148
+ treeStateReferenceToSnapshot(resp.state[MerkleTreeId.NOTE_HASH_TREE]),
149
+ treeStateReferenceToSnapshot(resp.state[MerkleTreeId.NULLIFIER_TREE]),
150
+ treeStateReferenceToSnapshot(resp.state[MerkleTreeId.PUBLIC_DATA_TREE]),
151
+ ),
152
+ );
153
+ }
154
+
155
+ async getTreeInfo(treeId: MerkleTreeId): Promise<TreeInfo> {
156
+ const resp = await this.instance.call(WorldStateMessageType.GET_TREE_INFO, {
157
+ treeId: treeId,
158
+ revision: this.revision,
159
+ });
160
+
161
+ return {
162
+ depth: resp.depth,
163
+ root: resp.root,
164
+ size: BigInt(resp.size),
165
+ treeId,
166
+ };
167
+ }
168
+
169
+ async getBlockNumbersForLeafIndices<ID extends MerkleTreeId>(
170
+ treeId: ID,
171
+ leafIndices: bigint[],
172
+ ): Promise<(bigint | undefined)[]> {
173
+ const response = await this.instance.call(WorldStateMessageType.GET_BLOCK_NUMBERS_FOR_LEAF_INDICES, {
174
+ treeId,
175
+ revision: this.revision,
176
+ leafIndices,
177
+ });
178
+
179
+ return response.blockNumbers.map(x => (x === undefined || x === null ? undefined : BigInt(x)));
180
+ }
181
+ }
182
+
183
+ export class MerkleTreesForkFacade extends MerkleTreesFacade implements MerkleTreeWriteOperations {
184
+ constructor(instance: NativeWorldStateInstance, initialHeader: BlockHeader, revision: WorldStateRevision) {
185
+ assert.notEqual(revision.forkId, 0, 'Fork ID must be set');
186
+ assert.equal(revision.includeUncommitted, true, 'Fork must include uncommitted data');
187
+ super(instance, initialHeader, revision);
188
+ }
189
+ async updateArchive(header: BlockHeader): Promise<void> {
190
+ await this.instance.call(WorldStateMessageType.UPDATE_ARCHIVE, {
191
+ forkId: this.revision.forkId,
192
+ blockHeaderHash: (await header.hash()).toBuffer(),
193
+ blockStateRef: blockStateReference(header.state),
194
+ });
195
+ }
196
+
197
+ async appendLeaves<ID extends MerkleTreeId>(treeId: ID, leaves: MerkleTreeLeafType<ID>[]): Promise<void> {
198
+ await this.instance.call(WorldStateMessageType.APPEND_LEAVES, {
199
+ leaves: leaves.map(leaf => leaf as any),
200
+ forkId: this.revision.forkId,
201
+ treeId,
202
+ });
203
+ }
204
+
205
+ async batchInsert<TreeHeight extends number, SubtreeSiblingPathHeight extends number, ID extends IndexedTreeId>(
206
+ treeId: ID,
207
+ rawLeaves: Buffer[],
208
+ subtreeHeight: number,
209
+ ): Promise<BatchInsertionResult<TreeHeight, SubtreeSiblingPathHeight>> {
210
+ const leaves = rawLeaves.map((leaf: Buffer) => hydrateLeaf(treeId, leaf)).map(serializeLeaf);
211
+ const resp = await this.instance.call(WorldStateMessageType.BATCH_INSERT, {
212
+ leaves,
213
+ treeId,
214
+ forkId: this.revision.forkId,
215
+ subtreeDepth: subtreeHeight,
216
+ });
217
+
218
+ return {
219
+ newSubtreeSiblingPath: new SiblingPath<SubtreeSiblingPathHeight>(
220
+ resp.subtree_path.length as any,
221
+ resp.subtree_path,
222
+ ),
223
+ sortedNewLeaves: resp.sorted_leaves
224
+ .map(([leaf]) => leaf)
225
+ .map(deserializeLeafValue)
226
+ .map(serializeToBuffer),
227
+ sortedNewLeavesIndexes: resp.sorted_leaves.map(([, index]) => index),
228
+ lowLeavesWitnessData: resp.low_leaf_witness_data.map(data => ({
229
+ index: BigInt(data.index),
230
+ leafPreimage: deserializeIndexedLeaf(data.leaf),
231
+ siblingPath: new SiblingPath<TreeHeight>(data.path.length as any, data.path),
232
+ })),
233
+ };
234
+ }
235
+
236
+ async sequentialInsert<TreeHeight extends number, ID extends IndexedTreeId>(
237
+ treeId: ID,
238
+ rawLeaves: Buffer[],
239
+ ): Promise<SequentialInsertionResult<TreeHeight>> {
240
+ const leaves = rawLeaves.map((leaf: Buffer) => hydrateLeaf(treeId, leaf)).map(serializeLeaf);
241
+ const resp = await this.instance.call(WorldStateMessageType.SEQUENTIAL_INSERT, {
242
+ leaves,
243
+ treeId,
244
+ forkId: this.revision.forkId,
245
+ });
246
+
247
+ return {
248
+ lowLeavesWitnessData: resp.low_leaf_witness_data.map(data => ({
249
+ index: BigInt(data.index),
250
+ leafPreimage: deserializeIndexedLeaf(data.leaf),
251
+ siblingPath: new SiblingPath<TreeHeight>(data.path.length as any, data.path),
252
+ })),
253
+ insertionWitnessData: resp.insertion_witness_data.map(data => ({
254
+ index: BigInt(data.index),
255
+ leafPreimage: deserializeIndexedLeaf(data.leaf),
256
+ siblingPath: new SiblingPath<TreeHeight>(data.path.length as any, data.path),
257
+ })),
258
+ };
259
+ }
260
+
261
+ public async close(): Promise<void> {
262
+ assert.notEqual(this.revision.forkId, 0, 'Fork ID must be set');
263
+ await this.instance.call(WorldStateMessageType.DELETE_FORK, { forkId: this.revision.forkId });
264
+ }
265
+
266
+ public async createCheckpoint(): Promise<void> {
267
+ assert.notEqual(this.revision.forkId, 0, 'Fork ID must be set');
268
+ await this.instance.call(WorldStateMessageType.CREATE_CHECKPOINT, { forkId: this.revision.forkId });
269
+ }
270
+
271
+ public async commitCheckpoint(): Promise<void> {
272
+ assert.notEqual(this.revision.forkId, 0, 'Fork ID must be set');
273
+ await this.instance.call(WorldStateMessageType.COMMIT_CHECKPOINT, { forkId: this.revision.forkId });
274
+ }
275
+
276
+ public async revertCheckpoint(): Promise<void> {
277
+ assert.notEqual(this.revision.forkId, 0, 'Fork ID must be set');
278
+ await this.instance.call(WorldStateMessageType.REVERT_CHECKPOINT, { forkId: this.revision.forkId });
279
+ }
280
+ }
281
+
282
+ function hydrateLeaf<ID extends MerkleTreeId>(treeId: ID, leaf: Fr | Buffer) {
283
+ if (leaf instanceof Fr) {
284
+ return leaf;
285
+ } else if (treeId === MerkleTreeId.NULLIFIER_TREE) {
286
+ return NullifierLeaf.fromBuffer(leaf);
287
+ } else if (treeId === MerkleTreeId.PUBLIC_DATA_TREE) {
288
+ return PublicDataTreeLeaf.fromBuffer(leaf);
289
+ } else {
290
+ return Fr.fromBuffer(leaf);
291
+ }
292
+ }
293
+
294
+ export function serializeLeaf(leaf: Fr | NullifierLeaf | PublicDataTreeLeaf): SerializedLeafValue {
295
+ if (leaf instanceof Fr) {
296
+ return leaf.toBuffer();
297
+ } else if (leaf instanceof NullifierLeaf) {
298
+ return { value: leaf.nullifier.toBuffer() };
299
+ } else {
300
+ return { value: leaf.value.toBuffer(), slot: leaf.slot.toBuffer() };
301
+ }
302
+ }
303
+
304
+ function deserializeLeafValue(leaf: SerializedLeafValue): Fr | NullifierLeaf | PublicDataTreeLeaf {
305
+ if (Buffer.isBuffer(leaf)) {
306
+ return Fr.fromBuffer(leaf);
307
+ } else if ('slot' in leaf) {
308
+ return new PublicDataTreeLeaf(Fr.fromBuffer(leaf.slot), Fr.fromBuffer(leaf.value));
309
+ } else {
310
+ return new NullifierLeaf(Fr.fromBuffer(leaf.value));
311
+ }
312
+ }
313
+
314
+ function deserializeIndexedLeaf(leaf: SerializedIndexedLeaf): IndexedTreeLeafPreimage {
315
+ if ('slot' in leaf.value) {
316
+ return new PublicDataTreeLeafPreimage(
317
+ Fr.fromBuffer(leaf.value.slot),
318
+ Fr.fromBuffer(leaf.value.value),
319
+ Fr.fromBuffer(leaf.nextValue),
320
+ BigInt(leaf.nextIndex),
321
+ );
322
+ } else if ('value' in leaf.value) {
323
+ return new NullifierLeafPreimage(
324
+ Fr.fromBuffer(leaf.value.value),
325
+ Fr.fromBuffer(leaf.nextValue),
326
+ BigInt(leaf.nextIndex),
327
+ );
328
+ } else {
329
+ throw new Error('Invalid leaf type');
330
+ }
331
+ }