@aztec/world-state 0.0.1-commit.b2a5d0dd1 → 0.0.1-commit.b3d3157a

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 (47) hide show
  1. package/dest/instrumentation/instrumentation.d.ts +4 -3
  2. package/dest/instrumentation/instrumentation.d.ts.map +1 -1
  3. package/dest/instrumentation/instrumentation.js +4 -9
  4. package/dest/native/ipc_world_state_instance.d.ts +87 -0
  5. package/dest/native/ipc_world_state_instance.d.ts.map +1 -0
  6. package/dest/native/ipc_world_state_instance.js +660 -0
  7. package/dest/native/merkle_trees_facade.d.ts +6 -3
  8. package/dest/native/merkle_trees_facade.d.ts.map +1 -1
  9. package/dest/native/merkle_trees_facade.js +53 -113
  10. package/dest/native/message.d.ts +14 -229
  11. package/dest/native/message.d.ts.map +1 -1
  12. package/dest/native/message.js +0 -42
  13. package/dest/native/native_world_state.d.ts +15 -5
  14. package/dest/native/native_world_state.d.ts.map +1 -1
  15. package/dest/native/native_world_state.js +97 -51
  16. package/dest/native/native_world_state_instance.d.ts +58 -41
  17. package/dest/native/native_world_state_instance.d.ts.map +1 -1
  18. package/dest/native/native_world_state_instance.js +5 -203
  19. package/dest/native/world_state_operation.d.ts +7 -0
  20. package/dest/native/world_state_operation.d.ts.map +1 -0
  21. package/dest/native/world_state_operation.js +5 -0
  22. package/dest/synchronizer/config.d.ts +1 -1
  23. package/dest/synchronizer/config.d.ts.map +1 -1
  24. package/dest/synchronizer/config.js +9 -10
  25. package/dest/synchronizer/factory.d.ts +3 -3
  26. package/dest/synchronizer/factory.d.ts.map +1 -1
  27. package/dest/synchronizer/factory.js +5 -5
  28. package/dest/synchronizer/server_world_state_synchronizer.d.ts +1 -1
  29. package/dest/synchronizer/server_world_state_synchronizer.d.ts.map +1 -1
  30. package/dest/synchronizer/server_world_state_synchronizer.js +16 -13
  31. package/dest/testing.js +1 -1
  32. package/package.json +14 -10
  33. package/src/instrumentation/instrumentation.ts +6 -18
  34. package/src/native/ipc_world_state_instance.ts +830 -0
  35. package/src/native/merkle_trees_facade.ts +76 -108
  36. package/src/native/message.ts +13 -296
  37. package/src/native/native_world_state.ts +113 -79
  38. package/src/native/native_world_state_instance.ts +96 -284
  39. package/src/native/world_state_operation.ts +33 -0
  40. package/src/synchronizer/config.ts +14 -10
  41. package/src/synchronizer/factory.ts +8 -7
  42. package/src/synchronizer/server_world_state_synchronizer.ts +11 -14
  43. package/src/testing.ts +1 -1
  44. package/dest/native/world_state_ops_queue.d.ts +0 -19
  45. package/dest/native/world_state_ops_queue.d.ts.map +0 -1
  46. package/dest/native/world_state_ops_queue.js +0 -146
  47. package/src/native/world_state_ops_queue.ts +0 -190
@@ -22,14 +22,13 @@ import {
22
22
  PublicDataTreeLeafPreimage,
23
23
  } from '@aztec/stdlib/trees';
24
24
  import { type BlockHeader, PartialStateReference, StateReference } from '@aztec/stdlib/tx';
25
- import { type WorldStateRevision, WorldStateRevisionWithHandle } from '@aztec/stdlib/world-state';
25
+ import type { WorldStateRevision } from '@aztec/stdlib/world-state';
26
26
 
27
27
  import assert from 'assert';
28
28
 
29
29
  import {
30
30
  type SerializedIndexedLeaf,
31
31
  type SerializedLeafValue,
32
- WorldStateMessageType,
33
32
  blockStateReference,
34
33
  treeStateReferenceToSnapshot,
35
34
  } from './message.js';
@@ -46,8 +45,12 @@ export class MerkleTreesFacade implements MerkleTreeReadOperations {
46
45
  return this.initialHeader;
47
46
  }
48
47
 
49
- getRevision(): WorldStateRevisionWithHandle {
50
- return WorldStateRevisionWithHandle.fromWorldStateRevision(this.revision, this.instance.getHandle());
48
+ getRevision(): WorldStateRevision {
49
+ return this.revision;
50
+ }
51
+
52
+ getIpcPath(): string {
53
+ return this.instance.getIpcPath();
51
54
  }
52
55
 
53
56
  findLeafIndices(treeId: MerkleTreeId, values: MerkleTreeLeafType<MerkleTreeId>[]): Promise<(bigint | undefined)[]> {
@@ -58,13 +61,13 @@ export class MerkleTreesFacade implements MerkleTreeReadOperations {
58
61
  treeId: MerkleTreeId,
59
62
  values: MerkleTreeLeafType<MerkleTreeId>[],
60
63
  ): Promise<({ path: SiblingPath<N>; index: bigint } | undefined)[]> {
61
- const response = await this.instance.call(WorldStateMessageType.FIND_SIBLING_PATHS, {
62
- leaves: values.map(leaf => serializeLeaf(hydrateLeaf(treeId, leaf))),
63
- revision: this.revision,
64
+ const paths = await this.instance.findSiblingPaths(
64
65
  treeId,
65
- });
66
+ this.revision,
67
+ values.map(leaf => serializeLeaf(hydrateLeaf(treeId, leaf))),
68
+ );
66
69
 
67
- return response.paths.map(path => {
70
+ return paths.map(path => {
68
71
  if (!path) {
69
72
  return undefined;
70
73
  }
@@ -77,14 +80,14 @@ export class MerkleTreesFacade implements MerkleTreeReadOperations {
77
80
  leaves: MerkleTreeLeafType<MerkleTreeId>[],
78
81
  startIndex: bigint,
79
82
  ): Promise<(bigint | undefined)[]> {
80
- const response = await this.instance.call(WorldStateMessageType.FIND_LEAF_INDICES, {
81
- leaves: leaves.map(leaf => serializeLeaf(hydrateLeaf(treeId, leaf))),
82
- revision: this.revision,
83
+ const indices = await this.instance.findLeafIndices(
83
84
  treeId,
85
+ this.revision,
86
+ leaves.map(leaf => serializeLeaf(hydrateLeaf(treeId, leaf))),
84
87
  startIndex,
85
- });
88
+ );
86
89
 
87
- return response.indices.map(index => {
90
+ return indices.map(index => {
88
91
  if (typeof index === 'number' || typeof index === 'bigint') {
89
92
  return BigInt(index);
90
93
  } else {
@@ -94,11 +97,7 @@ export class MerkleTreesFacade implements MerkleTreeReadOperations {
94
97
  }
95
98
 
96
99
  async getLeafPreimage(treeId: IndexedTreeId, leafIndex: bigint): Promise<IndexedTreeLeafPreimage | undefined> {
97
- const resp = await this.instance.call(WorldStateMessageType.GET_LEAF_PREIMAGE, {
98
- leafIndex,
99
- revision: this.revision,
100
- treeId,
101
- });
100
+ const resp = await this.instance.getLeafPreimage(treeId, this.revision, leafIndex);
102
101
 
103
102
  return resp ? deserializeIndexedLeaf(resp) : undefined;
104
103
  }
@@ -107,11 +106,7 @@ export class MerkleTreesFacade implements MerkleTreeReadOperations {
107
106
  treeId: ID,
108
107
  leafIndex: bigint,
109
108
  ): Promise<MerkleTreeLeafType<ID> | undefined> {
110
- const resp = await this.instance.call(WorldStateMessageType.GET_LEAF_VALUE, {
111
- leafIndex,
112
- revision: this.revision,
113
- treeId,
114
- });
109
+ const resp = await this.instance.getLeafValue(treeId, this.revision, leafIndex);
115
110
 
116
111
  if (!resp) {
117
112
  return undefined;
@@ -129,11 +124,7 @@ export class MerkleTreesFacade implements MerkleTreeReadOperations {
129
124
  treeId: IndexedTreeId,
130
125
  value: bigint,
131
126
  ): Promise<{ index: bigint; alreadyPresent: boolean } | undefined> {
132
- const resp = await this.instance.call(WorldStateMessageType.FIND_LOW_LEAF, {
133
- key: new Fr(value),
134
- revision: this.revision,
135
- treeId,
136
- });
127
+ const resp = await this.instance.findLowLeaf(treeId, this.revision, new Fr(value));
137
128
  return {
138
129
  alreadyPresent: resp.alreadyPresent,
139
130
  index: BigInt(resp.index),
@@ -141,73 +132,54 @@ export class MerkleTreesFacade implements MerkleTreeReadOperations {
141
132
  }
142
133
 
143
134
  async getSiblingPath<N extends number>(treeId: MerkleTreeId, leafIndex: bigint): Promise<SiblingPath<N>> {
144
- const siblingPath = await this.instance.call(WorldStateMessageType.GET_SIBLING_PATH, {
145
- leafIndex,
146
- revision: this.revision,
147
- treeId,
148
- });
135
+ const siblingPath = await this.instance.getSiblingPath(treeId, this.revision, leafIndex);
149
136
 
150
137
  return new SiblingPath(siblingPath.length, siblingPath) as any;
151
138
  }
152
139
 
153
140
  async getStateReference(): Promise<StateReference> {
154
- const resp = await this.instance.call(WorldStateMessageType.GET_STATE_REFERENCE, {
155
- revision: this.revision,
156
- });
141
+ const state = await this.instance.getStateReference(this.revision);
157
142
 
158
143
  return new StateReference(
159
- treeStateReferenceToSnapshot(resp.state[MerkleTreeId.L1_TO_L2_MESSAGE_TREE]),
144
+ treeStateReferenceToSnapshot(state[MerkleTreeId.L1_TO_L2_MESSAGE_TREE]),
160
145
  new PartialStateReference(
161
- treeStateReferenceToSnapshot(resp.state[MerkleTreeId.NOTE_HASH_TREE]),
162
- treeStateReferenceToSnapshot(resp.state[MerkleTreeId.NULLIFIER_TREE]),
163
- treeStateReferenceToSnapshot(resp.state[MerkleTreeId.PUBLIC_DATA_TREE]),
146
+ treeStateReferenceToSnapshot(state[MerkleTreeId.NOTE_HASH_TREE]),
147
+ treeStateReferenceToSnapshot(state[MerkleTreeId.NULLIFIER_TREE]),
148
+ treeStateReferenceToSnapshot(state[MerkleTreeId.PUBLIC_DATA_TREE]),
164
149
  ),
165
150
  );
166
151
  }
167
152
 
168
153
  async getInitialStateReference(): Promise<StateReference> {
169
- const resp = await this.instance.call(WorldStateMessageType.GET_INITIAL_STATE_REFERENCE, { canonical: true });
154
+ const state = await this.instance.getInitialStateReference();
170
155
 
171
156
  return new StateReference(
172
- treeStateReferenceToSnapshot(resp.state[MerkleTreeId.L1_TO_L2_MESSAGE_TREE]),
157
+ treeStateReferenceToSnapshot(state[MerkleTreeId.L1_TO_L2_MESSAGE_TREE]),
173
158
  new PartialStateReference(
174
- treeStateReferenceToSnapshot(resp.state[MerkleTreeId.NOTE_HASH_TREE]),
175
- treeStateReferenceToSnapshot(resp.state[MerkleTreeId.NULLIFIER_TREE]),
176
- treeStateReferenceToSnapshot(resp.state[MerkleTreeId.PUBLIC_DATA_TREE]),
159
+ treeStateReferenceToSnapshot(state[MerkleTreeId.NOTE_HASH_TREE]),
160
+ treeStateReferenceToSnapshot(state[MerkleTreeId.NULLIFIER_TREE]),
161
+ treeStateReferenceToSnapshot(state[MerkleTreeId.PUBLIC_DATA_TREE]),
177
162
  ),
178
163
  );
179
164
  }
180
165
 
181
166
  async getTreeInfo(treeId: MerkleTreeId): Promise<TreeInfo> {
182
- const resp = await this.instance.call(WorldStateMessageType.GET_TREE_INFO, {
183
- treeId: treeId,
184
- revision: this.revision,
185
- });
186
-
187
- return {
188
- depth: resp.depth,
189
- root: resp.root,
190
- size: BigInt(resp.size),
191
- treeId,
192
- };
167
+ return await this.instance.getTreeInfo(treeId, this.revision);
193
168
  }
194
169
 
195
170
  async getBlockNumbersForLeafIndices<ID extends MerkleTreeId>(
196
171
  treeId: ID,
197
172
  leafIndices: bigint[],
198
173
  ): Promise<(BlockNumber | undefined)[]> {
199
- const response = await this.instance.call(WorldStateMessageType.GET_BLOCK_NUMBERS_FOR_LEAF_INDICES, {
200
- treeId,
201
- revision: this.revision,
202
- leafIndices,
203
- });
174
+ const blockNumbers = await this.instance.getBlockNumbersForLeafIndices(treeId, this.revision, leafIndices);
204
175
 
205
- return response.blockNumbers.map(x => (x === undefined || x === null ? undefined : BlockNumber(Number(x))));
176
+ return blockNumbers.map(x => (x === undefined || x === null ? undefined : BlockNumber(Number(x))));
206
177
  }
207
178
  }
208
179
 
209
180
  export class MerkleTreesForkFacade extends MerkleTreesFacade implements MerkleTreeWriteOperations {
210
181
  private log = createLogger('world-state:merkle-trees-fork-facade');
182
+ private closePromise: Promise<void> | undefined;
211
183
 
212
184
  constructor(
213
185
  instance: NativeWorldStateInstance,
@@ -220,19 +192,19 @@ export class MerkleTreesForkFacade extends MerkleTreesFacade implements MerkleTr
220
192
  super(instance, initialHeader, revision);
221
193
  }
222
194
  async updateArchive(header: BlockHeader): Promise<void> {
223
- await this.instance.call(WorldStateMessageType.UPDATE_ARCHIVE, {
224
- forkId: this.revision.forkId,
225
- blockHeaderHash: (await header.hash()).toBuffer(),
226
- blockStateRef: blockStateReference(header.state),
227
- });
195
+ await this.instance.updateArchive(
196
+ this.revision.forkId,
197
+ blockStateReference(header.state),
198
+ (await header.hash()).toBuffer(),
199
+ );
228
200
  }
229
201
 
230
202
  async appendLeaves<ID extends MerkleTreeId>(treeId: ID, leaves: MerkleTreeLeafType<ID>[]): Promise<void> {
231
- await this.instance.call(WorldStateMessageType.APPEND_LEAVES, {
232
- leaves: leaves.map(leaf => serializeLeaf(hydrateLeaf(treeId, leaf as any))),
233
- forkId: this.revision.forkId,
203
+ await this.instance.appendLeaves(
234
204
  treeId,
235
- });
205
+ this.revision.forkId,
206
+ leaves.map(leaf => serializeLeaf(hydrateLeaf(treeId, leaf as any))),
207
+ );
236
208
  }
237
209
 
238
210
  async batchInsert<TreeHeight extends number, SubtreeSiblingPathHeight extends number, ID extends IndexedTreeId>(
@@ -241,24 +213,19 @@ export class MerkleTreesForkFacade extends MerkleTreesFacade implements MerkleTr
241
213
  subtreeHeight: number,
242
214
  ): Promise<BatchInsertionResult<TreeHeight, SubtreeSiblingPathHeight>> {
243
215
  const leaves = rawLeaves.map((leaf: Buffer) => hydrateLeaf(treeId, leaf)).map(serializeLeaf);
244
- const resp = await this.instance.call(WorldStateMessageType.BATCH_INSERT, {
245
- leaves,
246
- treeId,
247
- forkId: this.revision.forkId,
248
- subtreeDepth: subtreeHeight,
249
- });
216
+ const resp = await this.instance.batchInsert(treeId, this.revision.forkId, leaves, subtreeHeight);
250
217
 
251
218
  return {
252
219
  newSubtreeSiblingPath: new SiblingPath<SubtreeSiblingPathHeight>(
253
- resp.subtree_path.length as any,
254
- resp.subtree_path,
220
+ resp.subtreePath.length as any,
221
+ resp.subtreePath,
255
222
  ),
256
- sortedNewLeaves: resp.sorted_leaves
223
+ sortedNewLeaves: resp.sortedLeaves
257
224
  .map(([leaf]) => leaf)
258
225
  .map(deserializeLeafValue)
259
226
  .map(serializeToBuffer),
260
- sortedNewLeavesIndexes: resp.sorted_leaves.map(([, index]) => index),
261
- lowLeavesWitnessData: resp.low_leaf_witness_data.map(data => ({
227
+ sortedNewLeavesIndexes: resp.sortedLeaves.map(([, index]) => index),
228
+ lowLeavesWitnessData: resp.lowLeafWitnessData.map(data => ({
262
229
  index: BigInt(data.index),
263
230
  leafPreimage: deserializeIndexedLeaf(data.leaf),
264
231
  siblingPath: new SiblingPath<TreeHeight>(data.path.length as any, data.path),
@@ -271,19 +238,15 @@ export class MerkleTreesForkFacade extends MerkleTreesFacade implements MerkleTr
271
238
  rawLeaves: Buffer[],
272
239
  ): Promise<SequentialInsertionResult<TreeHeight>> {
273
240
  const leaves = rawLeaves.map((leaf: Buffer) => hydrateLeaf(treeId, leaf)).map(serializeLeaf);
274
- const resp = await this.instance.call(WorldStateMessageType.SEQUENTIAL_INSERT, {
275
- leaves,
276
- treeId,
277
- forkId: this.revision.forkId,
278
- });
241
+ const resp = await this.instance.sequentialInsert(treeId, this.revision.forkId, leaves);
279
242
 
280
243
  return {
281
- lowLeavesWitnessData: resp.low_leaf_witness_data.map(data => ({
244
+ lowLeavesWitnessData: resp.lowLeafWitnessData.map(data => ({
282
245
  index: BigInt(data.index),
283
246
  leafPreimage: deserializeIndexedLeaf(data.leaf),
284
247
  siblingPath: new SiblingPath<TreeHeight>(data.path.length as any, data.path),
285
248
  })),
286
- insertionWitnessData: resp.insertion_witness_data.map(data => ({
249
+ insertionWitnessData: resp.insertionWitnessData.map(data => ({
287
250
  index: BigInt(data.index),
288
251
  leafPreimage: deserializeIndexedLeaf(data.leaf),
289
252
  siblingPath: new SiblingPath<TreeHeight>(data.path.length as any, data.path),
@@ -291,14 +254,29 @@ export class MerkleTreesForkFacade extends MerkleTreesFacade implements MerkleTr
291
254
  };
292
255
  }
293
256
 
294
- public async close(): Promise<void> {
257
+ public close(): Promise<void> {
295
258
  assert.notEqual(this.revision.forkId, 0, 'Fork ID must be set');
259
+ // Share the in-flight close promise across duplicate dispose calls so DELETE_FORK is sent at most once.
260
+ if (this.closePromise) {
261
+ return this.closePromise;
262
+ }
263
+ this.closePromise = this.doClose();
264
+ return this.closePromise;
265
+ }
266
+
267
+ private async doClose(): Promise<void> {
296
268
  try {
297
- await this.instance.call(WorldStateMessageType.DELETE_FORK, { forkId: this.revision.forkId });
269
+ await this.instance.deleteFork(this.revision.forkId);
298
270
  } catch (err: any) {
299
271
  // Ignore errors due to native instance being closed during shutdown.
300
272
  // This can happen when validators are still processing block proposals while the node is stopping.
301
- if (err?.message === 'Native instance is closed') {
273
+ if (err?.message === 'Native instance is closed' || err?.message === 'IPC instance is closed') {
274
+ return;
275
+ }
276
+ // Ignore "Fork not found": the native fork was already destroyed by a pending-chain unwind or a
277
+ // historical prune (both call C++ remove_forks_for_block). Fork IDs are monotonic and never reused,
278
+ // so swallowing this on close cannot mask a deletion of a different fork.
279
+ if (err?.message === 'Fork not found') {
302
280
  return;
303
281
  }
304
282
  throw err;
@@ -310,9 +288,6 @@ export class MerkleTreesForkFacade extends MerkleTreesFacade implements MerkleTr
310
288
  void sleep(this.opts.closeDelayMs)
311
289
  .then(() => this.close())
312
290
  .catch(err => {
313
- if (err && 'message' in err && err.message === 'Native instance is closed') {
314
- return; // Ignore errors due to native instance being closed
315
- }
316
291
  this.log.warn('Error closing MerkleTreesForkFacade after delay', { err });
317
292
  });
318
293
  } else {
@@ -322,34 +297,27 @@ export class MerkleTreesForkFacade extends MerkleTreesFacade implements MerkleTr
322
297
 
323
298
  public async createCheckpoint(): Promise<number> {
324
299
  assert.notEqual(this.revision.forkId, 0, 'Fork ID must be set');
325
- const resp = await this.instance.call(WorldStateMessageType.CREATE_CHECKPOINT, { forkId: this.revision.forkId });
326
- return resp.depth;
300
+ return await this.instance.createCheckpoint(this.revision.forkId);
327
301
  }
328
302
 
329
303
  public async commitCheckpoint(): Promise<void> {
330
304
  assert.notEqual(this.revision.forkId, 0, 'Fork ID must be set');
331
- await this.instance.call(WorldStateMessageType.COMMIT_CHECKPOINT, { forkId: this.revision.forkId });
305
+ await this.instance.commitCheckpoint(this.revision.forkId);
332
306
  }
333
307
 
334
308
  public async revertCheckpoint(): Promise<void> {
335
309
  assert.notEqual(this.revision.forkId, 0, 'Fork ID must be set');
336
- await this.instance.call(WorldStateMessageType.REVERT_CHECKPOINT, { forkId: this.revision.forkId });
310
+ await this.instance.revertCheckpoint(this.revision.forkId);
337
311
  }
338
312
 
339
313
  public async commitAllCheckpointsTo(depth: number): Promise<void> {
340
314
  assert.notEqual(this.revision.forkId, 0, 'Fork ID must be set');
341
- await this.instance.call(WorldStateMessageType.COMMIT_ALL_CHECKPOINTS, {
342
- forkId: this.revision.forkId,
343
- depth,
344
- });
315
+ await this.instance.commitAllCheckpoints(this.revision.forkId, depth);
345
316
  }
346
317
 
347
318
  public async revertAllCheckpointsTo(depth: number): Promise<void> {
348
319
  assert.notEqual(this.revision.forkId, 0, 'Fork ID must be set');
349
- await this.instance.call(WorldStateMessageType.REVERT_ALL_CHECKPOINTS, {
350
- forkId: this.revision.forkId,
351
- depth,
352
- });
320
+ await this.instance.revertAllCheckpoints(this.revision.forkId, depth);
353
321
  }
354
322
  }
355
323