@aztec/world-state 0.0.1-commit.2f68f620 → 0.0.1-commit.3100065

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 (57) hide show
  1. package/dest/instrumentation/instrumentation.d.ts +3 -4
  2. package/dest/instrumentation/instrumentation.d.ts.map +1 -1
  3. package/dest/instrumentation/instrumentation.js +9 -4
  4. package/dest/native/ipc_world_state_instance.d.ts +22 -59
  5. package/dest/native/ipc_world_state_instance.d.ts.map +1 -1
  6. package/dest/native/ipc_world_state_instance.js +495 -520
  7. package/dest/native/merkle_trees_facade.d.ts +3 -4
  8. package/dest/native/merkle_trees_facade.d.ts.map +1 -1
  9. package/dest/native/merkle_trees_facade.js +109 -37
  10. package/dest/native/message.d.ts +233 -14
  11. package/dest/native/message.d.ts.map +1 -1
  12. package/dest/native/message.js +42 -0
  13. package/dest/native/native_world_state.d.ts +28 -14
  14. package/dest/native/native_world_state.d.ts.map +1 -1
  15. package/dest/native/native_world_state.js +102 -101
  16. package/dest/native/native_world_state_instance.d.ts +42 -58
  17. package/dest/native/native_world_state_instance.d.ts.map +1 -1
  18. package/dest/native/native_world_state_instance.js +222 -5
  19. package/dest/native/world_state_ops_queue.d.ts +19 -0
  20. package/dest/native/world_state_ops_queue.d.ts.map +1 -0
  21. package/dest/native/world_state_ops_queue.js +146 -0
  22. package/dest/synchronizer/errors.d.ts +8 -1
  23. package/dest/synchronizer/errors.d.ts.map +1 -1
  24. package/dest/synchronizer/errors.js +8 -1
  25. package/dest/synchronizer/factory.d.ts +1 -1
  26. package/dest/synchronizer/factory.d.ts.map +1 -1
  27. package/dest/synchronizer/factory.js +1 -1
  28. package/dest/synchronizer/index.d.ts +2 -1
  29. package/dest/synchronizer/index.d.ts.map +1 -1
  30. package/dest/synchronizer/index.js +1 -0
  31. package/dest/synchronizer/server_world_state_synchronizer.d.ts +11 -6
  32. package/dest/synchronizer/server_world_state_synchronizer.d.ts.map +1 -1
  33. package/dest/synchronizer/server_world_state_synchronizer.js +55 -43
  34. package/dest/test/utils.d.ts +1 -1
  35. package/dest/test/utils.d.ts.map +1 -1
  36. package/dest/test/utils.js +6 -1
  37. package/dest/testing.d.ts +2 -2
  38. package/dest/testing.d.ts.map +1 -1
  39. package/dest/testing.js +15 -4
  40. package/package.json +10 -12
  41. package/src/instrumentation/instrumentation.ts +18 -6
  42. package/src/native/ipc_world_state_instance.ts +503 -608
  43. package/src/native/merkle_trees_facade.ts +104 -59
  44. package/src/native/message.ts +300 -13
  45. package/src/native/native_world_state.ts +156 -121
  46. package/src/native/native_world_state_instance.ts +307 -96
  47. package/src/native/world_state_ops_queue.ts +190 -0
  48. package/src/synchronizer/errors.ts +8 -0
  49. package/src/synchronizer/factory.ts +1 -0
  50. package/src/synchronizer/index.ts +1 -0
  51. package/src/synchronizer/server_world_state_synchronizer.ts +63 -30
  52. package/src/test/utils.ts +10 -1
  53. package/src/testing.ts +14 -4
  54. package/dest/native/world_state_operation.d.ts +0 -7
  55. package/dest/native/world_state_operation.d.ts.map +0 -1
  56. package/dest/native/world_state_operation.js +0 -5
  57. package/src/native/world_state_operation.ts +0 -33
@@ -3,6 +3,7 @@ import { BlockNumber } from '@aztec/foundation/branded-types';
3
3
  import { fromEntries, padArrayEnd } from '@aztec/foundation/collection';
4
4
  import { Fr } from '@aztec/foundation/curves/bn254';
5
5
  import { EthAddress } from '@aztec/foundation/eth-address';
6
+ import { tryRmDir } from '@aztec/foundation/fs';
6
7
  import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
7
8
  import type { L2Block } from '@aztec/stdlib/block';
8
9
  import { DatabaseVersionManager } from '@aztec/stdlib/database-version/manager';
@@ -18,16 +19,16 @@ import { EMPTY_GENESIS_DATA, type GenesisData, WorldStateRevision } from '@aztec
18
19
  import { getTelemetryClient } from '@aztec/telemetry-client';
19
20
 
20
21
  import assert from 'assert/strict';
21
- import { mkdir, mkdtemp, rm } from 'fs/promises';
22
+ import { mkdtemp, rm } from 'fs/promises';
22
23
  import { tmpdir } from 'os';
23
24
  import { join } from 'path';
24
25
 
25
26
  import { WorldStateInstrumentation } from '../instrumentation/instrumentation.js';
26
27
  import type { WorldStateTreeMapSizes } from '../synchronizer/factory.js';
27
28
  import type { MerkleTreeAdminDatabase as MerkleTreeDatabase } from '../world-state-db/merkle_tree_db.js';
28
- import { IpcWorldState } from './ipc_world_state_instance.js';
29
29
  import { MerkleTreesFacade, MerkleTreesForkFacade, serializeLeaf } from './merkle_trees_facade.js';
30
30
  import {
31
+ WorldStateMessageType,
31
32
  type WorldStateStatusFull,
32
33
  type WorldStateStatusSummary,
33
34
  blockStateReference,
@@ -35,7 +36,7 @@ import {
35
36
  sanitizeSummary,
36
37
  treeStateReferenceToSnapshot,
37
38
  } from './message.js';
38
- import type { NativeWorldStateInstance } from './native_world_state_instance.js';
39
+ import { NativeWorldState } from './native_world_state_instance.js';
39
40
 
40
41
  // The current version of the world state database schema
41
42
  // Increment this when making incompatible changes to the database schema
@@ -43,21 +44,47 @@ export const WORLD_STATE_DB_VERSION = 2; // The initial version
43
44
 
44
45
  export const WORLD_STATE_DIR = 'world_state';
45
46
 
47
+ const DEFAULT_TMP_TREE_MAP_SIZE_KB = 10 * 1024 * 1024;
48
+
49
+ /**
50
+ * Sets up a fresh `mkdtemp` directory + default `WorldStateTreeMapSizes` shared by both
51
+ * the `.tmp` (fsync-on) and `.ephemeral` (fsync-off) factories. Returns the raw tmpdir,
52
+ * the tree map sizes, and the package logger.
53
+ */
54
+ async function createTmpWorldStateDir(
55
+ bindings?: LoggerBindings,
56
+ ): Promise<{ dataDir: string; wsTreeMapSizes: WorldStateTreeMapSizes; log: Logger }> {
57
+ const log = createLogger('world-state:database', bindings);
58
+ const dataDir = await mkdtemp(join(tmpdir(), 'aztec-world-state-'));
59
+ const wsTreeMapSizes: WorldStateTreeMapSizes = {
60
+ archiveTreeMapSizeKb: DEFAULT_TMP_TREE_MAP_SIZE_KB,
61
+ nullifierTreeMapSizeKb: DEFAULT_TMP_TREE_MAP_SIZE_KB,
62
+ noteHashTreeMapSizeKb: DEFAULT_TMP_TREE_MAP_SIZE_KB,
63
+ messageTreeMapSizeKb: DEFAULT_TMP_TREE_MAP_SIZE_KB,
64
+ publicDataTreeMapSizeKb: DEFAULT_TMP_TREE_MAP_SIZE_KB,
65
+ };
66
+ log.debug(`Created temporary world state database at: ${dataDir} (map size ${DEFAULT_TMP_TREE_MAP_SIZE_KB} KB)`);
67
+ return { dataDir, wsTreeMapSizes, log };
68
+ }
69
+
46
70
  export class NativeWorldStateService implements MerkleTreeDatabase {
47
71
  protected initialHeader: BlockHeader | undefined;
48
72
  // This is read heavily and only changes when data is persisted, so we cache it
49
73
  private cachedStatusSummary: WorldStateStatusSummary | undefined;
50
74
 
51
75
  protected constructor(
52
- protected instance: NativeWorldStateInstance,
76
+ protected instance: NativeWorldState,
53
77
  protected readonly worldStateInstrumentation: WorldStateInstrumentation,
54
78
  protected readonly log: Logger,
55
79
  private readonly genesis: GenesisData = EMPTY_GENESIS_DATA,
56
80
  private readonly cleanup = () => Promise.resolve(),
57
- /** Factory to recreate a fresh IpcWorldState after clear(). */
58
- private readonly recreateInstance?: () => Promise<NativeWorldStateInstance>,
59
81
  ) {}
60
82
 
83
+ /**
84
+ * Opens a persistent world state at `dataDir`. Goes through `DatabaseVersionManager` so the
85
+ * caller's rollup address is bound to the on-disk schema and incompatible versions surface
86
+ * loudly. The LMDB envs commit with full fsync.
87
+ */
61
88
  static async new(
62
89
  rollupAddress: EthAddress,
63
90
  dataDir: string,
@@ -67,31 +94,28 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
67
94
  bindings?: LoggerBindings,
68
95
  cleanup = () => Promise.resolve(),
69
96
  ): Promise<NativeWorldStateService> {
70
- for (const [key, value] of Object.entries(wsTreeMapSizes)) {
71
- if (value <= 0) {
72
- throw new Error(`Map size must be a positive number, got ${value} for ${key}`);
73
- }
74
- }
75
-
76
97
  const log = createLogger('world-state:database', bindings);
77
98
  const worldStateDirectory = join(dataDir, WORLD_STATE_DIR);
78
-
79
99
  const versionManager = new DatabaseVersionManager({
80
100
  schemaVersion: WORLD_STATE_DB_VERSION,
81
101
  rollupAddress,
82
102
  dataDirectory: worldStateDirectory,
83
- onOpen: dir => IpcWorldState.spawn(dir, wsTreeMapSizes, genesis, instrumentation, bindings),
103
+ onOpen: (dir: string) =>
104
+ Promise.resolve(
105
+ new NativeWorldState(
106
+ dir,
107
+ wsTreeMapSizes,
108
+ genesis,
109
+ instrumentation,
110
+ bindings,
111
+ undefined,
112
+ /*ephemeral=*/ false,
113
+ ),
114
+ ),
84
115
  });
85
116
 
86
117
  const [instance] = await versionManager.open();
87
-
88
- const recreateInstance = async () => {
89
- await rm(worldStateDirectory, { recursive: true, force: true, maxRetries: 3 });
90
- await mkdir(worldStateDirectory, { recursive: true });
91
- return IpcWorldState.spawn(worldStateDirectory, wsTreeMapSizes, genesis, instrumentation, bindings);
92
- };
93
-
94
- const worldState = new this(instance, instrumentation, log, genesis, cleanup, recreateInstance);
118
+ const worldState = new this(instance, instrumentation, log, genesis, cleanup);
95
119
  try {
96
120
  await worldState.init();
97
121
  } catch (e) {
@@ -102,30 +126,23 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
102
126
  return worldState;
103
127
  }
104
128
 
129
+ /**
130
+ * Opens a world state in a fresh tmpdir with full fsync semantics. Use when you need the
131
+ * on-disk file to remain crash-recoverable (e.g. for snapshot/backup tests) but don't
132
+ * want a persistent dataDir. Pass `cleanupTmpDir=false` to keep the directory after
133
+ * close for inspection.
134
+ *
135
+ * If you don't care about crash-recoverability — i.e. you just want a fast scratch
136
+ * database for tests — use {@link ephemeral} instead.
137
+ */
105
138
  static async tmp(
139
+ rollupAddress = EthAddress.ZERO,
106
140
  cleanupTmpDir = true,
107
141
  genesis: GenesisData = EMPTY_GENESIS_DATA,
108
142
  instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
109
143
  bindings?: LoggerBindings,
110
144
  ): Promise<NativeWorldStateService> {
111
- const log = createLogger('world-state:database', bindings);
112
- const dataDir = await mkdtemp(join(tmpdir(), 'aztec-world-state-'));
113
- // Temporary (test/dev) world states are small and short-lived. Keep the LMDB
114
- // map sizes in the MB range: with the IPC backend each tmp() spawns a separate
115
- // aztec-wsdb that maps these per tree, and oversized maps add real cold-start
116
- // I/O under parallel CI load. 256 MB/tree is ample for tests.
117
- const dbMapSizeKb = 256 * 1024;
118
- const worldStateTreeMapSizes: WorldStateTreeMapSizes = {
119
- archiveTreeMapSizeKb: dbMapSizeKb,
120
- nullifierTreeMapSizeKb: dbMapSizeKb,
121
- noteHashTreeMapSizeKb: dbMapSizeKb,
122
- messageTreeMapSizeKb: dbMapSizeKb,
123
- publicDataTreeMapSizeKb: dbMapSizeKb,
124
- };
125
- log.debug(`Created temporary world state database at: ${dataDir} with tree map size: ${dbMapSizeKb}`);
126
-
127
- const instance = await IpcWorldState.spawn(dataDir, worldStateTreeMapSizes, genesis, instrumentation, bindings);
128
-
145
+ const { dataDir, wsTreeMapSizes, log } = await createTmpWorldStateDir(bindings);
129
146
  const cleanup = async () => {
130
147
  if (cleanupTmpDir) {
131
148
  await rm(dataDir, { recursive: true, force: true, maxRetries: 3 });
@@ -134,46 +151,47 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
134
151
  log.debug(`Leaving temporary world state database: ${dataDir}`);
135
152
  }
136
153
  };
154
+ return this.new(rollupAddress, dataDir, wsTreeMapSizes, genesis, instrumentation, bindings, cleanup);
155
+ }
137
156
 
138
- const recreateInstance = async () => {
157
+ /**
158
+ * Opens a fully-ephemeral world state. The directory is created in `os.tmpdir()`, the LMDB
159
+ * envs open with `MDB_NOSYNC | MDB_NOMETASYNC` so commits never block on fsync, and the
160
+ * directory is removed on dispose. A crash mid-write leaves the env unrecoverable.
161
+ *
162
+ * For unit tests and other isolated runs. Use {@link tmp} when you need fsync semantics in a
163
+ * tmp dir, and {@link new} for a persistent store. Skips {@link DatabaseVersionManager} —
164
+ * there is no on-disk schema to bind to and no rollup address is taken.
165
+ */
166
+ static async ephemeral(
167
+ genesis: GenesisData = EMPTY_GENESIS_DATA,
168
+ instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
169
+ bindings?: LoggerBindings,
170
+ ): Promise<NativeWorldStateService> {
171
+ const { dataDir, wsTreeMapSizes, log } = await createTmpWorldStateDir(bindings);
172
+ const cleanup = async () => {
139
173
  await rm(dataDir, { recursive: true, force: true, maxRetries: 3 });
140
- await mkdir(dataDir, { recursive: true });
141
- return IpcWorldState.spawn(dataDir, worldStateTreeMapSizes, genesis, instrumentation, bindings);
174
+ log.debug(`Deleted ephemeral world state database: ${dataDir}`);
142
175
  };
143
-
144
- const worldState = new this(instance, instrumentation, log, genesis, cleanup, recreateInstance);
176
+ const instance = new NativeWorldState(
177
+ join(dataDir, WORLD_STATE_DIR),
178
+ wsTreeMapSizes,
179
+ genesis,
180
+ instrumentation,
181
+ bindings,
182
+ undefined,
183
+ /*ephemeral=*/ true,
184
+ );
185
+ const worldState = new this(instance, instrumentation, log, genesis, cleanup);
145
186
  try {
146
187
  await worldState.init();
147
188
  } catch (e) {
148
- log.error(`Error initializing tmp world state: ${e}`);
189
+ log.error(`Error initializing ephemeral world state: ${e}`);
149
190
  throw e;
150
191
  }
151
192
  return worldState;
152
193
  }
153
194
 
154
- static ephemeral(
155
- genesis: GenesisData = EMPTY_GENESIS_DATA,
156
- instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
157
- bindings?: LoggerBindings,
158
- ): Promise<NativeWorldStateService> {
159
- return this.tmp(/*cleanupTmpDir=*/ true, genesis, instrumentation, bindings);
160
- }
161
-
162
- static async fromIpc(
163
- wsdbBackend: ConstructorParameters<typeof IpcWorldState>[0],
164
- instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
165
- bindings?: LoggerBindings,
166
- genesis: GenesisData = EMPTY_GENESIS_DATA,
167
- cleanup = () => Promise.resolve(),
168
- recreateInstance?: () => Promise<NativeWorldStateInstance>,
169
- ): Promise<NativeWorldStateService> {
170
- const log = createLogger('world-state:database', bindings);
171
- const instance = new IpcWorldState(wsdbBackend, instrumentation, bindings);
172
- const worldState = new this(instance, instrumentation, log, genesis, cleanup, recreateInstance);
173
- await worldState.init();
174
- return worldState;
175
- }
176
-
177
195
  protected async init() {
178
196
  const status = await this.getStatusSummary();
179
197
  if (!status.treesAreSynched) {
@@ -195,24 +213,11 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
195
213
  assert.strictEqual(initialHeaderIndex, 0n, 'Invalid initial archive state');
196
214
  }
197
215
 
198
- public async clear(): Promise<void> {
199
- if (!this.recreateInstance) {
200
- throw new Error('clear() is not available for externally-managed IPC backends');
201
- }
202
- this.log.warn('Clearing world state: shutting down WSDB, deleting data, and recreating');
216
+ public async clear() {
203
217
  await this.instance.close();
204
218
  this.cachedStatusSummary = undefined;
205
- this.instance = await this.recreateInstance();
206
- await this.init();
207
- this.log.info('World state cleared and reinitialized from genesis');
208
- }
209
-
210
- /** Returns the IPC path of the underlying IPC backend, if available. */
211
- public getIpcPath(): string {
212
- if (this.instance instanceof IpcWorldState) {
213
- return this.instance.getIpcPath();
214
- }
215
- throw new Error('getIpcPath() is only available with IPC world state');
219
+ await tryRmDir(this.instance.getDataDir(), this.log);
220
+ this.instance = this.instance.clone();
216
221
  }
217
222
 
218
223
  public getCommitted(): MerkleTreeReadOperations {
@@ -231,15 +236,16 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
231
236
  blockNumber?: BlockNumber,
232
237
  opts: { closeDelayMs?: number } = {},
233
238
  ): Promise<MerkleTreeWriteOperations> {
234
- const forkId = await this.instance.createFork({
239
+ const resp = await this.instance.call(WorldStateMessageType.CREATE_FORK, {
235
240
  latest: blockNumber === undefined,
236
241
  blockNumber: blockNumber ?? BlockNumber.ZERO,
242
+ canonical: true,
237
243
  });
238
244
  return new MerkleTreesForkFacade(
239
245
  this.instance,
240
246
  this.initialHeader!,
241
247
  new WorldStateRevision(
242
- /*forkId=*/ forkId,
248
+ /*forkId=*/ resp.forkId,
243
249
  /* blockNumber=*/ WorldStateRevision.LATEST,
244
250
  /* includeUncommitted=*/ true,
245
251
  ),
@@ -283,33 +289,33 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
283
289
  });
284
290
 
285
291
  try {
286
- const status = await this.instance.syncBlock({
287
- blockNumber: l2Block.number,
288
- blockHeaderHash: (await l2Block.hash()).toBuffer(),
289
- paddedL1ToL2Messages: paddedL1ToL2Messages.map(serializeLeaf),
290
- paddedNoteHashes: paddedNoteHashes.map(serializeLeaf),
291
- paddedNullifiers: paddedNullifiers.map(serializeLeaf),
292
- publicDataWrites: publicDataWrites.map(serializeLeaf),
293
- blockStateRef: blockStateReference(l2Block.header.state),
294
- });
295
- return this.sanitizeAndCacheSummaryFromFull(status);
292
+ return await this.instance.call(
293
+ WorldStateMessageType.SYNC_BLOCK,
294
+ {
295
+ blockNumber: l2Block.number,
296
+ blockHeaderHash: (await l2Block.hash()).toBuffer(),
297
+ // Forwarded so the native sync verifies the archive root against canonical and rejects a divergent tree.
298
+ expectedArchiveRoot: l2Block.archive.root.toBuffer(),
299
+ expectedPreviousArchiveRoot: l2Block.header.lastArchive.root.toBuffer(),
300
+ paddedL1ToL2Messages: paddedL1ToL2Messages.map(serializeLeaf),
301
+ paddedNoteHashes: paddedNoteHashes.map(serializeLeaf),
302
+ paddedNullifiers: paddedNullifiers.map(serializeLeaf),
303
+ publicDataWrites: publicDataWrites.map(serializeLeaf),
304
+ blockStateRef: blockStateReference(l2Block.header.state),
305
+ canonical: true,
306
+ },
307
+ this.sanitizeAndCacheSummaryFromFull.bind(this),
308
+ this.deleteCachedSummary.bind(this),
309
+ );
296
310
  } catch (err) {
297
- this.deleteCachedSummary();
298
311
  this.worldStateInstrumentation.incCriticalErrors('synch_pending_block');
299
312
  throw err;
300
313
  }
301
314
  }
302
315
 
303
316
  public async close(): Promise<void> {
304
- try {
305
- await this.instance.close();
306
- } finally {
307
- await this.cleanup();
308
- }
309
- }
310
-
311
- async [Symbol.asyncDispose](): Promise<void> {
312
- await this.close();
317
+ await this.instance.close();
318
+ await this.cleanup();
313
319
  }
314
320
 
315
321
  private async buildInitialHeader(): Promise<BlockHeader> {
@@ -332,7 +338,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
332
338
  return sanitized;
333
339
  }
334
340
 
335
- private deleteCachedSummary() {
341
+ private deleteCachedSummary(_: string) {
336
342
  this.cachedStatusSummary = undefined;
337
343
  }
338
344
 
@@ -343,9 +349,16 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
343
349
  */
344
350
  public async setFinalized(toBlockNumber: BlockNumber) {
345
351
  try {
346
- this.sanitizeAndCacheSummary(await this.instance.finalizeBlocks(toBlockNumber));
352
+ await this.instance.call(
353
+ WorldStateMessageType.FINALIZE_BLOCKS,
354
+ {
355
+ toBlockNumber,
356
+ canonical: true,
357
+ },
358
+ this.sanitizeAndCacheSummary.bind(this),
359
+ this.deleteCachedSummary.bind(this),
360
+ );
347
361
  } catch (err) {
348
- this.deleteCachedSummary();
349
362
  this.worldStateInstrumentation.incCriticalErrors('finalize_block');
350
363
  throw err;
351
364
  }
@@ -359,9 +372,16 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
359
372
  */
360
373
  public async removeHistoricalBlocks(toBlockNumber: BlockNumber) {
361
374
  try {
362
- return this.sanitizeAndCacheSummaryFromFull(await this.instance.removeHistoricalBlocks(toBlockNumber));
375
+ return await this.instance.call(
376
+ WorldStateMessageType.REMOVE_HISTORICAL_BLOCKS,
377
+ {
378
+ toBlockNumber,
379
+ canonical: true,
380
+ },
381
+ this.sanitizeAndCacheSummaryFromFull.bind(this),
382
+ this.deleteCachedSummary.bind(this),
383
+ );
363
384
  } catch (err) {
364
- this.deleteCachedSummary();
365
385
  this.worldStateInstrumentation.incCriticalErrors('prune_historical_block');
366
386
  throw err;
367
387
  }
@@ -374,9 +394,16 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
374
394
  */
375
395
  public async unwindBlocks(toBlockNumber: BlockNumber) {
376
396
  try {
377
- return this.sanitizeAndCacheSummaryFromFull(await this.instance.unwindBlocks(toBlockNumber));
397
+ return await this.instance.call(
398
+ WorldStateMessageType.UNWIND_BLOCKS,
399
+ {
400
+ toBlockNumber,
401
+ canonical: true,
402
+ },
403
+ this.sanitizeAndCacheSummaryFromFull.bind(this),
404
+ this.deleteCachedSummary.bind(this),
405
+ );
378
406
  } catch (err) {
379
- this.deleteCachedSummary();
380
407
  this.worldStateInstrumentation.incCriticalErrors('prune_pending_block');
381
408
  throw err;
382
409
  }
@@ -386,7 +413,11 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
386
413
  if (this.cachedStatusSummary !== undefined) {
387
414
  return { ...this.cachedStatusSummary };
388
415
  }
389
- return this.sanitizeAndCacheSummary(await this.instance.getStatus());
416
+ return await this.instance.call(
417
+ WorldStateMessageType.GET_STATUS,
418
+ { canonical: true },
419
+ this.sanitizeAndCacheSummary.bind(this),
420
+ );
390
421
  }
391
422
 
392
423
  updateLeaf<ID extends IndexedTreeId>(
@@ -398,14 +429,14 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
398
429
  }
399
430
 
400
431
  private async getInitialStateReference(): Promise<StateReference> {
401
- const state = await this.instance.getInitialStateReference();
432
+ const resp = await this.instance.call(WorldStateMessageType.GET_INITIAL_STATE_REFERENCE, { canonical: true });
402
433
 
403
434
  return new StateReference(
404
- treeStateReferenceToSnapshot(state[MerkleTreeId.L1_TO_L2_MESSAGE_TREE]),
435
+ treeStateReferenceToSnapshot(resp.state[MerkleTreeId.L1_TO_L2_MESSAGE_TREE]),
405
436
  new PartialStateReference(
406
- treeStateReferenceToSnapshot(state[MerkleTreeId.NOTE_HASH_TREE]),
407
- treeStateReferenceToSnapshot(state[MerkleTreeId.NULLIFIER_TREE]),
408
- treeStateReferenceToSnapshot(state[MerkleTreeId.PUBLIC_DATA_TREE]),
437
+ treeStateReferenceToSnapshot(resp.state[MerkleTreeId.NOTE_HASH_TREE]),
438
+ treeStateReferenceToSnapshot(resp.state[MerkleTreeId.NULLIFIER_TREE]),
439
+ treeStateReferenceToSnapshot(resp.state[MerkleTreeId.PUBLIC_DATA_TREE]),
409
440
  ),
410
441
  );
411
442
  }
@@ -414,7 +445,11 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
414
445
  dstPath: string,
415
446
  compact: boolean = true,
416
447
  ): Promise<Record<Exclude<SnapshotDataKeys, 'archiver'>, string>> {
417
- await this.instance.copyStores(dstPath, compact);
448
+ await this.instance.call(WorldStateMessageType.COPY_STORES, {
449
+ dstPath,
450
+ compact,
451
+ canonical: true,
452
+ });
418
453
  return fromEntries(NATIVE_WORLD_STATE_DBS.map(([name, dir]) => [name, join(dstPath, dir, 'data.mdb')] as const));
419
454
  }
420
455
  }