@aztec/world-state 0.0.0-test.1 → 0.0.1-commit.017a351

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 (69) hide show
  1. package/dest/index.d.ts +1 -1
  2. package/dest/instrumentation/instrumentation.d.ts +6 -4
  3. package/dest/instrumentation/instrumentation.d.ts.map +1 -1
  4. package/dest/instrumentation/instrumentation.js +25 -41
  5. package/dest/native/bench_metrics.d.ts +23 -0
  6. package/dest/native/bench_metrics.d.ts.map +1 -0
  7. package/dest/native/bench_metrics.js +81 -0
  8. package/dest/native/fork_checkpoint.d.ts +7 -1
  9. package/dest/native/fork_checkpoint.d.ts.map +1 -1
  10. package/dest/native/fork_checkpoint.js +15 -3
  11. package/dest/native/index.d.ts +1 -1
  12. package/dest/native/ipc_world_state_instance.d.ts +45 -0
  13. package/dest/native/ipc_world_state_instance.d.ts.map +1 -0
  14. package/dest/native/ipc_world_state_instance.js +750 -0
  15. package/dest/native/merkle_trees_facade.d.ts +25 -9
  16. package/dest/native/merkle_trees_facade.d.ts.map +1 -1
  17. package/dest/native/merkle_trees_facade.js +109 -25
  18. package/dest/native/message.d.ts +87 -58
  19. package/dest/native/message.d.ts.map +1 -1
  20. package/dest/native/message.js +61 -61
  21. package/dest/native/native_world_state.d.ts +41 -21
  22. package/dest/native/native_world_state.d.ts.map +1 -1
  23. package/dest/native/native_world_state.js +177 -50
  24. package/dest/native/native_world_state_instance.d.ts +23 -25
  25. package/dest/native/native_world_state_instance.d.ts.map +1 -1
  26. package/dest/native/native_world_state_instance.js +8 -163
  27. package/dest/native/world_state_ops_queue.d.ts +1 -1
  28. package/dest/native/world_state_ops_queue.d.ts.map +1 -1
  29. package/dest/native/world_state_ops_queue.js +6 -6
  30. package/dest/synchronizer/config.d.ts +14 -6
  31. package/dest/synchronizer/config.d.ts.map +1 -1
  32. package/dest/synchronizer/config.js +36 -14
  33. package/dest/synchronizer/errors.d.ts +4 -0
  34. package/dest/synchronizer/errors.d.ts.map +1 -0
  35. package/dest/synchronizer/errors.js +5 -0
  36. package/dest/synchronizer/factory.d.ts +13 -5
  37. package/dest/synchronizer/factory.d.ts.map +1 -1
  38. package/dest/synchronizer/factory.js +15 -9
  39. package/dest/synchronizer/index.d.ts +1 -1
  40. package/dest/synchronizer/server_world_state_synchronizer.d.ts +21 -31
  41. package/dest/synchronizer/server_world_state_synchronizer.d.ts.map +1 -1
  42. package/dest/synchronizer/server_world_state_synchronizer.js +220 -96
  43. package/dest/test/index.d.ts +1 -1
  44. package/dest/test/utils.d.ts +12 -5
  45. package/dest/test/utils.d.ts.map +1 -1
  46. package/dest/test/utils.js +54 -47
  47. package/dest/testing.d.ts +6 -5
  48. package/dest/testing.d.ts.map +1 -1
  49. package/dest/testing.js +15 -15
  50. package/dest/world-state-db/index.d.ts +1 -1
  51. package/dest/world-state-db/merkle_tree_db.d.ts +12 -18
  52. package/dest/world-state-db/merkle_tree_db.d.ts.map +1 -1
  53. package/package.json +27 -25
  54. package/src/instrumentation/instrumentation.ts +31 -43
  55. package/src/native/bench_metrics.ts +91 -0
  56. package/src/native/fork_checkpoint.ts +19 -3
  57. package/src/native/ipc_world_state_instance.ts +863 -0
  58. package/src/native/merkle_trees_facade.ts +127 -33
  59. package/src/native/message.ts +109 -80
  60. package/src/native/native_world_state.ts +207 -64
  61. package/src/native/native_world_state_instance.ts +28 -223
  62. package/src/native/world_state_ops_queue.ts +6 -6
  63. package/src/synchronizer/config.ts +58 -20
  64. package/src/synchronizer/errors.ts +5 -0
  65. package/src/synchronizer/factory.ts +48 -18
  66. package/src/synchronizer/server_world_state_synchronizer.ts +249 -121
  67. package/src/test/utils.ts +92 -82
  68. package/src/testing.ts +11 -16
  69. package/src/world-state-db/merkle_tree_db.ts +16 -18
@@ -1,42 +1,48 @@
1
1
  import { MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
2
- import { padArrayEnd } from '@aztec/foundation/collection';
2
+ import { BlockNumber } from '@aztec/foundation/branded-types';
3
+ import { fromEntries, padArrayEnd } from '@aztec/foundation/collection';
4
+ import { Fr } from '@aztec/foundation/curves/bn254';
3
5
  import { EthAddress } from '@aztec/foundation/eth-address';
4
- import { Fr } from '@aztec/foundation/fields';
5
- import { createLogger } from '@aztec/foundation/log';
6
+ import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
6
7
  import type { L2Block } from '@aztec/stdlib/block';
7
- import { DatabaseVersionManager } from '@aztec/stdlib/database-version';
8
+ import { DatabaseVersionManager } from '@aztec/stdlib/database-version/manager';
8
9
  import type {
9
10
  IndexedTreeId,
10
11
  MerkleTreeReadOperations,
11
12
  MerkleTreeWriteOperations,
12
13
  } from '@aztec/stdlib/interfaces/server';
14
+ import type { SnapshotDataKeys } from '@aztec/stdlib/snapshots';
13
15
  import { MerkleTreeId, NullifierLeaf, type NullifierLeafPreimage, PublicDataTreeLeaf } from '@aztec/stdlib/trees';
14
- import { BlockHeader, PartialStateReference, StateReference } from '@aztec/stdlib/tx';
16
+ import { BlockHeader, GlobalVariables, PartialStateReference, StateReference } from '@aztec/stdlib/tx';
17
+ import { EMPTY_GENESIS_DATA, type GenesisData, WorldStateRevision } from '@aztec/stdlib/world-state';
15
18
  import { getTelemetryClient } from '@aztec/telemetry-client';
16
19
 
17
20
  import assert from 'assert/strict';
18
- import { mkdtemp, rm } from 'fs/promises';
21
+ import { mkdir, mkdtemp, rm } from 'fs/promises';
19
22
  import { tmpdir } from 'os';
20
23
  import { join } from 'path';
21
24
 
22
25
  import { WorldStateInstrumentation } from '../instrumentation/instrumentation.js';
26
+ import type { WorldStateTreeMapSizes } from '../synchronizer/factory.js';
23
27
  import type { MerkleTreeAdminDatabase as MerkleTreeDatabase } from '../world-state-db/merkle_tree_db.js';
28
+ import { IpcWorldState } from './ipc_world_state_instance.js';
24
29
  import { MerkleTreesFacade, MerkleTreesForkFacade, serializeLeaf } from './merkle_trees_facade.js';
25
30
  import {
26
31
  WorldStateMessageType,
27
32
  type WorldStateStatusFull,
28
33
  type WorldStateStatusSummary,
29
34
  blockStateReference,
30
- sanitiseFullStatus,
31
- sanitiseSummary,
35
+ sanitizeFullStatus,
36
+ sanitizeSummary,
32
37
  treeStateReferenceToSnapshot,
33
- worldStateRevision,
34
38
  } from './message.js';
35
- import { NativeWorldState } from './native_world_state_instance.js';
39
+ import type { NativeWorldStateInstance } from './native_world_state_instance.js';
36
40
 
37
41
  // The current version of the world state database schema
38
42
  // Increment this when making incompatible changes to the database schema
39
- export const WORLD_STATE_DB_VERSION = 1; // The initial version
43
+ export const WORLD_STATE_DB_VERSION = 2; // The initial version
44
+
45
+ export const WORLD_STATE_DIR = 'world_state';
40
46
 
41
47
  export class NativeWorldStateService implements MerkleTreeDatabase {
42
48
  protected initialHeader: BlockHeader | undefined;
@@ -44,38 +50,53 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
44
50
  private cachedStatusSummary: WorldStateStatusSummary | undefined;
45
51
 
46
52
  protected constructor(
47
- protected readonly instance: NativeWorldState,
53
+ protected instance: NativeWorldStateInstance,
48
54
  protected readonly worldStateInstrumentation: WorldStateInstrumentation,
49
- protected readonly log = createLogger('world-state:database'),
55
+ protected readonly log: Logger,
56
+ private readonly genesis: GenesisData = EMPTY_GENESIS_DATA,
50
57
  private readonly cleanup = () => Promise.resolve(),
58
+ /** Factory to recreate a fresh IpcWorldState after clear(). */
59
+ private readonly recreateInstance?: () => Promise<NativeWorldStateInstance>,
51
60
  ) {}
52
61
 
53
62
  static async new(
54
63
  rollupAddress: EthAddress,
55
64
  dataDir: string,
56
- dbMapSizeKb: number,
57
- prefilledPublicData: PublicDataTreeLeaf[] = [],
65
+ wsTreeMapSizes: WorldStateTreeMapSizes,
66
+ genesis: GenesisData = EMPTY_GENESIS_DATA,
58
67
  instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
59
- log = createLogger('world-state:database'),
68
+ bindings?: LoggerBindings,
60
69
  cleanup = () => Promise.resolve(),
61
70
  ): Promise<NativeWorldStateService> {
62
- const worldStateDirectory = join(dataDir, 'world_state');
63
- // Create a version manager to handle versioning
64
- const versionManager = new DatabaseVersionManager(
65
- WORLD_STATE_DB_VERSION,
71
+ for (const [key, value] of Object.entries(wsTreeMapSizes)) {
72
+ if (value <= 0) {
73
+ throw new Error(`Map size must be a positive number, got ${value} for ${key}`);
74
+ }
75
+ }
76
+
77
+ const log = createLogger('world-state:database', bindings);
78
+ const worldStateDirectory = join(dataDir, WORLD_STATE_DIR);
79
+
80
+ const versionManager = new DatabaseVersionManager({
81
+ schemaVersion: WORLD_STATE_DB_VERSION,
66
82
  rollupAddress,
67
- worldStateDirectory,
68
- (dir: string) => {
69
- return Promise.resolve(new NativeWorldState(dir, dbMapSizeKb, prefilledPublicData, instrumentation));
70
- },
71
- );
83
+ dataDirectory: worldStateDirectory,
84
+ onOpen: dir => IpcWorldState.spawn(dir, wsTreeMapSizes, genesis, instrumentation, bindings),
85
+ });
72
86
 
73
87
  const [instance] = await versionManager.open();
74
- const worldState = new this(instance, instrumentation, log, cleanup);
88
+
89
+ const recreateInstance = async () => {
90
+ await rm(worldStateDirectory, { recursive: true, force: true, maxRetries: 3 });
91
+ await mkdir(worldStateDirectory, { recursive: true });
92
+ return IpcWorldState.spawn(worldStateDirectory, wsTreeMapSizes, genesis, instrumentation, bindings);
93
+ };
94
+
95
+ const worldState = new this(instance, instrumentation, log, genesis, cleanup, recreateInstance);
75
96
  try {
76
97
  await worldState.init();
77
98
  } catch (e) {
78
- log.error(`Error initialising world state: ${e}`);
99
+ log.error(`Error initializing world state: ${e}`);
79
100
  throw e;
80
101
  }
81
102
 
@@ -83,17 +104,25 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
83
104
  }
84
105
 
85
106
  static async tmp(
86
- rollupAddress = EthAddress.ZERO,
87
107
  cleanupTmpDir = true,
88
- prefilledPublicData: PublicDataTreeLeaf[] = [],
108
+ genesis: GenesisData = EMPTY_GENESIS_DATA,
89
109
  instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
110
+ bindings?: LoggerBindings,
90
111
  ): Promise<NativeWorldStateService> {
91
- const log = createLogger('world-state:database');
112
+ const log = createLogger('world-state:database', bindings);
92
113
  const dataDir = await mkdtemp(join(tmpdir(), 'aztec-world-state-'));
93
114
  const dbMapSizeKb = 10 * 1024 * 1024;
94
- log.debug(`Created temporary world state database at: ${dataDir} with size: ${dbMapSizeKb}`);
115
+ const worldStateTreeMapSizes: WorldStateTreeMapSizes = {
116
+ archiveTreeMapSizeKb: dbMapSizeKb,
117
+ nullifierTreeMapSizeKb: dbMapSizeKb,
118
+ noteHashTreeMapSizeKb: dbMapSizeKb,
119
+ messageTreeMapSizeKb: dbMapSizeKb,
120
+ publicDataTreeMapSizeKb: dbMapSizeKb,
121
+ };
122
+ log.debug(`Created temporary world state database at: ${dataDir} with tree map size: ${dbMapSizeKb}`);
123
+
124
+ const instance = await IpcWorldState.spawn(dataDir, worldStateTreeMapSizes, genesis, instrumentation, bindings);
95
125
 
96
- // pass a cleanup callback because process.on('beforeExit', cleanup) does not work under Jest
97
126
  const cleanup = async () => {
98
127
  if (cleanupTmpDir) {
99
128
  await rm(dataDir, { recursive: true, force: true, maxRetries: 3 });
@@ -103,7 +132,43 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
103
132
  }
104
133
  };
105
134
 
106
- return this.new(rollupAddress, dataDir, dbMapSizeKb, prefilledPublicData, instrumentation, log, cleanup);
135
+ const recreateInstance = async () => {
136
+ await rm(dataDir, { recursive: true, force: true, maxRetries: 3 });
137
+ await mkdir(dataDir, { recursive: true });
138
+ return IpcWorldState.spawn(dataDir, worldStateTreeMapSizes, genesis, instrumentation, bindings);
139
+ };
140
+
141
+ const worldState = new this(instance, instrumentation, log, genesis, cleanup, recreateInstance);
142
+ try {
143
+ await worldState.init();
144
+ } catch (e) {
145
+ log.error(`Error initializing tmp world state: ${e}`);
146
+ throw e;
147
+ }
148
+ return worldState;
149
+ }
150
+
151
+ static ephemeral(
152
+ genesis: GenesisData = EMPTY_GENESIS_DATA,
153
+ instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
154
+ bindings?: LoggerBindings,
155
+ ): Promise<NativeWorldStateService> {
156
+ return this.tmp(/*cleanupTmpDir=*/ true, genesis, instrumentation, bindings);
157
+ }
158
+
159
+ static async fromIpc(
160
+ wsdbBackend: ConstructorParameters<typeof IpcWorldState>[0],
161
+ instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
162
+ bindings?: LoggerBindings,
163
+ genesis: GenesisData = EMPTY_GENESIS_DATA,
164
+ cleanup = () => Promise.resolve(),
165
+ recreateInstance?: () => Promise<NativeWorldStateInstance>,
166
+ ): Promise<NativeWorldStateService> {
167
+ const log = createLogger('world-state:database', bindings);
168
+ const instance = new IpcWorldState(wsdbBackend, instrumentation, bindings);
169
+ const worldState = new this(instance, instrumentation, log, genesis, cleanup, recreateInstance);
170
+ await worldState.init();
171
+ return worldState;
107
172
  }
108
173
 
109
174
  protected async init() {
@@ -127,21 +192,57 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
127
192
  assert.strictEqual(initialHeaderIndex, 0n, 'Invalid initial archive state');
128
193
  }
129
194
 
195
+ public async clear(): Promise<void> {
196
+ if (!this.recreateInstance) {
197
+ throw new Error('clear() is not available for externally-managed IPC backends');
198
+ }
199
+ this.log.warn('Clearing world state: shutting down WSDB, deleting data, and recreating');
200
+ await this.instance.close();
201
+ this.cachedStatusSummary = undefined;
202
+ this.instance = await this.recreateInstance();
203
+ await this.init();
204
+ this.log.info('World state cleared and reinitialized from genesis');
205
+ }
206
+
207
+ /** Returns the socket path of the underlying IPC backend, if available. */
208
+ public getSocketPath(): string {
209
+ if (this.instance instanceof IpcWorldState) {
210
+ return this.instance.getSocketPath();
211
+ }
212
+ throw new Error('getSocketPath() is only available with IPC world state');
213
+ }
214
+
130
215
  public getCommitted(): MerkleTreeReadOperations {
131
- return new MerkleTreesFacade(this.instance, this.initialHeader!, worldStateRevision(false, 0, 0));
216
+ return new MerkleTreesFacade(this.instance, this.initialHeader!, WorldStateRevision.empty());
132
217
  }
133
218
 
134
- public getSnapshot(blockNumber: number): MerkleTreeReadOperations {
135
- return new MerkleTreesFacade(this.instance, this.initialHeader!, worldStateRevision(false, 0, blockNumber));
219
+ public getSnapshot(blockNumber: BlockNumber): MerkleTreeReadOperations {
220
+ return new MerkleTreesFacade(
221
+ this.instance,
222
+ this.initialHeader!,
223
+ new WorldStateRevision(/*forkId=*/ 0, /* blockNumber=*/ blockNumber, /* includeUncommitted=*/ false),
224
+ );
136
225
  }
137
226
 
138
- public async fork(blockNumber?: number): Promise<MerkleTreeWriteOperations> {
227
+ public async fork(
228
+ blockNumber?: BlockNumber,
229
+ opts: { closeDelayMs?: number } = {},
230
+ ): Promise<MerkleTreeWriteOperations> {
139
231
  const resp = await this.instance.call(WorldStateMessageType.CREATE_FORK, {
140
232
  latest: blockNumber === undefined,
141
- blockNumber: blockNumber ?? 0,
233
+ blockNumber: blockNumber ?? BlockNumber.ZERO,
142
234
  canonical: true,
143
235
  });
144
- return new MerkleTreesForkFacade(this.instance, this.initialHeader!, worldStateRevision(true, resp.forkId, 0));
236
+ return new MerkleTreesForkFacade(
237
+ this.instance,
238
+ this.initialHeader!,
239
+ new WorldStateRevision(
240
+ /*forkId=*/ resp.forkId,
241
+ /* blockNumber=*/ WorldStateRevision.LATEST,
242
+ /* includeUncommitted=*/ true,
243
+ ),
244
+ opts,
245
+ );
145
246
  }
146
247
 
147
248
  public getInitialHeader(): BlockHeader {
@@ -149,11 +250,22 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
149
250
  }
150
251
 
151
252
  public async handleL2BlockAndMessages(l2Block: L2Block, l1ToL2Messages: Fr[]): Promise<WorldStateStatusFull> {
152
- // We have to pad both the values within tx effects because that's how the trees are built by circuits.
253
+ const isFirstBlock = l2Block.indexWithinCheckpoint === 0;
254
+ if (!isFirstBlock && l1ToL2Messages.length > 0) {
255
+ throw new Error(
256
+ `L1 to L2 messages must be empty for non-first blocks, but got ${l1ToL2Messages.length} messages for block ${l2Block.number}.`,
257
+ );
258
+ }
259
+
260
+ // We have to pad the given l1 to l2 messages, and the note hashes and nullifiers within tx effects, because that's
261
+ // how the trees are built by circuits.
262
+ const paddedL1ToL2Messages = isFirstBlock
263
+ ? padArrayEnd<Fr, number>(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP)
264
+ : [];
265
+
153
266
  const paddedNoteHashes = l2Block.body.txEffects.flatMap(txEffect =>
154
267
  padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
155
268
  );
156
- const paddedL1ToL2Messages = padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
157
269
 
158
270
  const paddedNullifiers = l2Block.body.txEffects
159
271
  .flatMap(txEffect => padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX))
@@ -173,7 +285,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
173
285
  WorldStateMessageType.SYNC_BLOCK,
174
286
  {
175
287
  blockNumber: l2Block.number,
176
- blockHeaderHash: await l2Block.header.hash(),
288
+ blockHeaderHash: (await l2Block.hash()).toBuffer(),
177
289
  paddedL1ToL2Messages: paddedL1ToL2Messages.map(serializeLeaf),
178
290
  paddedNoteHashes: paddedNoteHashes.map(serializeLeaf),
179
291
  paddedNullifiers: paddedNullifiers.map(serializeLeaf),
@@ -181,7 +293,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
181
293
  blockStateRef: blockStateReference(l2Block.header.state),
182
294
  canonical: true,
183
295
  },
184
- this.sanitiseAndCacheSummaryFromFull.bind(this),
296
+ this.sanitizeAndCacheSummaryFromFull.bind(this),
185
297
  this.deleteCachedSummary.bind(this),
186
298
  );
187
299
  } catch (err) {
@@ -191,25 +303,35 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
191
303
  }
192
304
 
193
305
  public async close(): Promise<void> {
194
- await this.instance.close();
195
- await this.cleanup();
306
+ try {
307
+ await this.instance.close();
308
+ } finally {
309
+ await this.cleanup();
310
+ }
311
+ }
312
+
313
+ async [Symbol.asyncDispose](): Promise<void> {
314
+ await this.close();
196
315
  }
197
316
 
198
317
  private async buildInitialHeader(): Promise<BlockHeader> {
199
318
  const state = await this.getInitialStateReference();
200
- return BlockHeader.empty({ state });
319
+ return BlockHeader.empty({
320
+ state,
321
+ globalVariables: GlobalVariables.empty({ timestamp: this.genesis.genesisTimestamp }),
322
+ });
201
323
  }
202
324
 
203
- private sanitiseAndCacheSummaryFromFull(response: WorldStateStatusFull) {
204
- const sanitised = sanitiseFullStatus(response);
205
- this.cachedStatusSummary = { ...sanitised.summary };
206
- return sanitised;
325
+ private sanitizeAndCacheSummaryFromFull(response: WorldStateStatusFull) {
326
+ const sanitized = sanitizeFullStatus(response);
327
+ this.cachedStatusSummary = { ...sanitized.summary };
328
+ return sanitized;
207
329
  }
208
330
 
209
- private sanitiseAndCacheSummary(response: WorldStateStatusSummary) {
210
- const sanitised = sanitiseSummary(response);
211
- this.cachedStatusSummary = { ...sanitised };
212
- return sanitised;
331
+ private sanitizeAndCacheSummary(response: WorldStateStatusSummary) {
332
+ const sanitized = sanitizeSummary(response);
333
+ this.cachedStatusSummary = { ...sanitized };
334
+ return sanitized;
213
335
  }
214
336
 
215
337
  private deleteCachedSummary(_: string) {
@@ -217,19 +339,19 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
217
339
  }
218
340
 
219
341
  /**
220
- * Advances the finalised block number to be the number provided
221
- * @param toBlockNumber The block number that is now the tip of the finalised chain
342
+ * Advances the finalized block number to be the number provided
343
+ * @param toBlockNumber The block number that is now the tip of the finalized chain
222
344
  * @returns The new WorldStateStatus
223
345
  */
224
- public async setFinalised(toBlockNumber: bigint) {
346
+ public async setFinalized(toBlockNumber: BlockNumber) {
225
347
  try {
226
348
  await this.instance.call(
227
- WorldStateMessageType.FINALISE_BLOCKS,
349
+ WorldStateMessageType.FINALIZE_BLOCKS,
228
350
  {
229
351
  toBlockNumber,
230
352
  canonical: true,
231
353
  },
232
- this.sanitiseAndCacheSummary.bind(this),
354
+ this.sanitizeAndCacheSummary.bind(this),
233
355
  this.deleteCachedSummary.bind(this),
234
356
  );
235
357
  } catch (err) {
@@ -244,7 +366,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
244
366
  * @param toBlockNumber The block number of the new oldest historical block
245
367
  * @returns The new WorldStateStatus
246
368
  */
247
- public async removeHistoricalBlocks(toBlockNumber: bigint) {
369
+ public async removeHistoricalBlocks(toBlockNumber: BlockNumber) {
248
370
  try {
249
371
  return await this.instance.call(
250
372
  WorldStateMessageType.REMOVE_HISTORICAL_BLOCKS,
@@ -252,7 +374,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
252
374
  toBlockNumber,
253
375
  canonical: true,
254
376
  },
255
- this.sanitiseAndCacheSummaryFromFull.bind(this),
377
+ this.sanitizeAndCacheSummaryFromFull.bind(this),
256
378
  this.deleteCachedSummary.bind(this),
257
379
  );
258
380
  } catch (err) {
@@ -266,7 +388,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
266
388
  * @param toBlockNumber The block number of the new tip of the pending chain,
267
389
  * @returns The new WorldStateStatus
268
390
  */
269
- public async unwindBlocks(toBlockNumber: bigint) {
391
+ public async unwindBlocks(toBlockNumber: BlockNumber) {
270
392
  try {
271
393
  return await this.instance.call(
272
394
  WorldStateMessageType.UNWIND_BLOCKS,
@@ -274,7 +396,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
274
396
  toBlockNumber,
275
397
  canonical: true,
276
398
  },
277
- this.sanitiseAndCacheSummaryFromFull.bind(this),
399
+ this.sanitizeAndCacheSummaryFromFull.bind(this),
278
400
  this.deleteCachedSummary.bind(this),
279
401
  );
280
402
  } catch (err) {
@@ -290,7 +412,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
290
412
  return await this.instance.call(
291
413
  WorldStateMessageType.GET_STATUS,
292
414
  { canonical: true },
293
- this.sanitiseAndCacheSummary.bind(this),
415
+ this.sanitizeAndCacheSummary.bind(this),
294
416
  );
295
417
  }
296
418
 
@@ -314,4 +436,25 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
314
436
  ),
315
437
  );
316
438
  }
439
+
440
+ public async backupTo(
441
+ dstPath: string,
442
+ compact: boolean = true,
443
+ ): Promise<Record<Exclude<SnapshotDataKeys, 'archiver'>, string>> {
444
+ await this.instance.call(WorldStateMessageType.COPY_STORES, {
445
+ dstPath,
446
+ compact,
447
+ canonical: true,
448
+ });
449
+ return fromEntries(NATIVE_WORLD_STATE_DBS.map(([name, dir]) => [name, join(dstPath, dir, 'data.mdb')] as const));
450
+ }
317
451
  }
452
+
453
+ // The following paths are defined in cpp-land
454
+ export const NATIVE_WORLD_STATE_DBS = [
455
+ ['l1-to-l2-message-tree', 'L1ToL2MessageTree'],
456
+ ['archive-tree', 'ArchiveTree'],
457
+ ['public-data-tree', 'PublicDataTree'],
458
+ ['note-hash-tree', 'NoteHashTree'],
459
+ ['nullifier-tree', 'NullifierTree'],
460
+ ] as const;