@aztec/world-state 0.62.0 → 0.63.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 (37) hide show
  1. package/dest/native/message.d.ts +96 -10
  2. package/dest/native/message.d.ts.map +1 -1
  3. package/dest/native/message.js +116 -1
  4. package/dest/native/native_world_state.d.ts +9 -7
  5. package/dest/native/native_world_state.d.ts.map +1 -1
  6. package/dest/native/native_world_state.js +55 -24
  7. package/dest/native/native_world_state_instance.d.ts +1 -1
  8. package/dest/native/native_world_state_instance.d.ts.map +1 -1
  9. package/dest/native/native_world_state_instance.js +4 -4
  10. package/dest/native/world_state_version.d.ts +15 -0
  11. package/dest/native/world_state_version.d.ts.map +1 -0
  12. package/dest/native/world_state_version.js +38 -0
  13. package/dest/synchronizer/config.d.ts +4 -0
  14. package/dest/synchronizer/config.d.ts.map +1 -1
  15. package/dest/synchronizer/config.js +10 -1
  16. package/dest/synchronizer/factory.d.ts +2 -2
  17. package/dest/synchronizer/factory.d.ts.map +1 -1
  18. package/dest/synchronizer/factory.js +8 -4
  19. package/dest/synchronizer/server_world_state_synchronizer.js +3 -3
  20. package/dest/test/utils.d.ts.map +1 -1
  21. package/dest/test/utils.js +4 -4
  22. package/dest/world-state-db/merkle_tree_db.d.ts +7 -7
  23. package/dest/world-state-db/merkle_tree_db.d.ts.map +1 -1
  24. package/dest/world-state-db/merkle_trees.d.ts +6 -6
  25. package/dest/world-state-db/merkle_trees.d.ts.map +1 -1
  26. package/dest/world-state-db/merkle_trees.js +7 -6
  27. package/package.json +8 -8
  28. package/src/native/message.ts +216 -10
  29. package/src/native/native_world_state.ts +58 -24
  30. package/src/native/native_world_state_instance.ts +3 -2
  31. package/src/native/world_state_version.ts +41 -0
  32. package/src/synchronizer/config.ts +15 -0
  33. package/src/synchronizer/factory.ts +17 -5
  34. package/src/synchronizer/server_world_state_synchronizer.ts +4 -4
  35. package/src/test/utils.ts +2 -3
  36. package/src/world-state-db/merkle_tree_db.ts +7 -7
  37. package/src/world-state-db/merkle_trees.ts +15 -10
@@ -0,0 +1,41 @@
1
+ import { EthAddress } from '@aztec/circuits.js';
2
+
3
+ import { readFile, writeFile } from 'fs/promises';
4
+
5
+ export class WorldStateVersion {
6
+ constructor(readonly version: number, readonly rollupAddress: EthAddress) {}
7
+
8
+ static async readVersion(filename: string) {
9
+ const versionData = await readFile(filename, 'utf-8').catch(() => undefined);
10
+ if (versionData === undefined) {
11
+ return undefined;
12
+ }
13
+ const versionJSON = JSON.parse(versionData);
14
+ if (versionJSON.version === undefined || versionJSON.rollupAddress === undefined) {
15
+ return undefined;
16
+ }
17
+ return WorldStateVersion.fromJSON(versionJSON);
18
+ }
19
+
20
+ public async writeVersionFile(filename: string) {
21
+ const data = JSON.stringify(this.toJSON());
22
+ await writeFile(filename, data, 'utf-8');
23
+ }
24
+
25
+ toJSON() {
26
+ return {
27
+ version: this.version,
28
+ rollupAddress: this.rollupAddress.toChecksumString(),
29
+ };
30
+ }
31
+
32
+ static fromJSON(obj: any): WorldStateVersion {
33
+ const version = obj.version;
34
+ const rollupAddress = EthAddress.fromString(obj.rollupAddress);
35
+ return new WorldStateVersion(version, rollupAddress);
36
+ }
37
+
38
+ static empty() {
39
+ return new WorldStateVersion(0, EthAddress.ZERO);
40
+ }
41
+ }
@@ -10,6 +10,12 @@ export interface WorldStateConfig {
10
10
 
11
11
  /** Size of the batch for each get-blocks request from the synchronizer to the archiver. */
12
12
  worldStateBlockRequestBatchSize?: number;
13
+
14
+ /** The maximum size of the combined world state db in KB, optional, will inherit from the general dataStoreMapSizeKB if not specified*/
15
+ worldStateDbMapSizeKb?: number;
16
+
17
+ /** Optional directory for the world state DB, if unspecified will default to the general data directory */
18
+ worldStateDataDirectory?: string;
13
19
  }
14
20
 
15
21
  export const worldStateConfigMappings: ConfigMappingsType<WorldStateConfig> = {
@@ -29,6 +35,15 @@ export const worldStateConfigMappings: ConfigMappingsType<WorldStateConfig> = {
29
35
  parseEnv: (val: string | undefined) => (val ? +val : undefined),
30
36
  description: 'Size of the batch for each get-blocks request from the synchronizer to the archiver.',
31
37
  },
38
+ worldStateDbMapSizeKb: {
39
+ env: 'WS_DB_MAP_SIZE_KB',
40
+ parseEnv: (val: string | undefined) => (val ? +val : undefined),
41
+ description: 'The maximum possible size of the world state DB',
42
+ },
43
+ worldStateDataDirectory: {
44
+ env: 'WS_DATA_DIRECTORY',
45
+ description: 'Optional directory for the world state database',
46
+ },
32
47
  };
33
48
 
34
49
  /**
@@ -1,6 +1,7 @@
1
1
  import { type L1ToL2MessageSource, type L2BlockSource } from '@aztec/circuit-types';
2
2
  import { createDebugLogger } from '@aztec/foundation/log';
3
- import { type DataStoreConfig, createStore } from '@aztec/kv-store/utils';
3
+ import { type DataStoreConfig } from '@aztec/kv-store/config';
4
+ import { createStore } from '@aztec/kv-store/utils';
4
5
  import { type TelemetryClient } from '@aztec/telemetry-client';
5
6
  import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
6
7
 
@@ -18,14 +19,25 @@ export async function createWorldStateSynchronizer(
18
19
  return new ServerWorldStateSynchronizer(merkleTrees, l2BlockSource, config);
19
20
  }
20
21
 
21
- export async function createWorldState(config: DataStoreConfig, client: TelemetryClient = new NoopTelemetryClient()) {
22
+ export async function createWorldState(
23
+ config: WorldStateConfig & DataStoreConfig,
24
+ client: TelemetryClient = new NoopTelemetryClient(),
25
+ ) {
26
+ const newConfig = {
27
+ dataDirectory: config.worldStateDataDirectory ?? config.dataDirectory,
28
+ dataStoreMapSizeKB: config.worldStateDbMapSizeKb ?? config.dataStoreMapSizeKB,
29
+ } as DataStoreConfig;
22
30
  const merkleTrees = ['true', '1'].includes(process.env.USE_LEGACY_WORLD_STATE ?? '')
23
31
  ? await MerkleTrees.new(
24
- await createStore('world-state', config, createDebugLogger('aztec:world-state:lmdb')),
32
+ await createStore('world-state', newConfig, createDebugLogger('aztec:world-state:lmdb')),
25
33
  client,
26
34
  )
27
- : config.dataDirectory
28
- ? await NativeWorldStateService.new(config.l1Contracts.rollupAddress, config.dataDirectory)
35
+ : newConfig.dataDirectory
36
+ ? await NativeWorldStateService.new(
37
+ config.l1Contracts.rollupAddress,
38
+ newConfig.dataDirectory,
39
+ newConfig.dataStoreMapSizeKB,
40
+ )
29
41
  : await NativeWorldStateService.tmp(
30
42
  config.l1Contracts.rollupAddress,
31
43
  !['true', '1'].includes(process.env.DEBUG_WORLD_STATE!),
@@ -24,7 +24,7 @@ import { promiseWithResolvers } from '@aztec/foundation/promise';
24
24
  import { elapsed } from '@aztec/foundation/timer';
25
25
  import { SHA256Trunc } from '@aztec/merkle-tree';
26
26
 
27
- import { type WorldStateStatus } from '../native/message.js';
27
+ import { type WorldStateStatusSummary } from '../native/message.js';
28
28
  import { type MerkleTreeAdminDatabase } from '../world-state-db/merkle_tree_db.js';
29
29
  import { type WorldStateConfig } from './config.js';
30
30
 
@@ -163,7 +163,7 @@ export class ServerWorldStateSynchronizer
163
163
 
164
164
  /** Returns the latest L2 block number for each tip of the chain (latest, proven, finalized). */
165
165
  public async getL2Tips(): Promise<L2Tips> {
166
- const status = await this.merkleTreeDb.getStatus();
166
+ const status = await this.merkleTreeDb.getStatusSummary();
167
167
  const unfinalisedBlockHash = await this.getL2BlockHash(Number(status.unfinalisedBlockNumber));
168
168
  const latestBlockId: L2BlockId = { number: Number(status.unfinalisedBlockNumber), hash: unfinalisedBlockHash! };
169
169
 
@@ -225,7 +225,7 @@ export class ServerWorldStateSynchronizer
225
225
  * @param l1ToL2Messages - The L1 to L2 messages for the block.
226
226
  * @returns Whether the block handled was produced by this same node.
227
227
  */
228
- private async handleL2Block(l2Block: L2Block, l1ToL2Messages: Fr[]): Promise<WorldStateStatus> {
228
+ private async handleL2Block(l2Block: L2Block, l1ToL2Messages: Fr[]): Promise<WorldStateStatusSummary> {
229
229
  // First we check that the L1 to L2 messages hash to the block inHash.
230
230
  // Note that we cannot optimize this check by checking the root of the subtree after inserting the messages
231
231
  // to the real L1_TO_L2_MESSAGE_TREE (like we do in merkleTreeDb.handleL2BlockAndMessages(...)) because that
@@ -240,7 +240,7 @@ export class ServerWorldStateSynchronizer
240
240
  this.syncPromise.resolve();
241
241
  }
242
242
 
243
- return result;
243
+ return result.summary;
244
244
  }
245
245
 
246
246
  private async handleChainFinalized(blockNumber: number) {
package/src/test/utils.ts CHANGED
@@ -3,7 +3,6 @@ import {
3
3
  MerkleTreeId,
4
4
  type MerkleTreeReadOperations,
5
5
  type MerkleTreeWriteOperations,
6
- PublicDataWrite,
7
6
  TxEffect,
8
7
  } from '@aztec/circuit-types';
9
8
  import {
@@ -15,7 +14,7 @@ import {
15
14
  NULLIFIER_SUBTREE_HEIGHT,
16
15
  NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
17
16
  PUBLIC_DATA_SUBTREE_HEIGHT,
18
- PublicDataTreeLeaf,
17
+ PublicDataWrite,
19
18
  } from '@aztec/circuits.js';
20
19
  import { padArrayEnd } from '@aztec/foundation/collection';
21
20
 
@@ -54,7 +53,7 @@ export async function mockBlock(blockNum: number, size: number, fork: MerkleTree
54
53
 
55
54
  await fork.batchInsert(
56
55
  MerkleTreeId.PUBLIC_DATA_TREE,
57
- publicDataWrites.map(write => new PublicDataTreeLeaf(write.leafIndex, write.newValue).toBuffer()),
56
+ publicDataWrites.map(write => write.toBuffer()),
58
57
  PUBLIC_DATA_SUBTREE_HEIGHT,
59
58
  );
60
59
 
@@ -3,7 +3,7 @@ import { type MerkleTreeReadOperations, type MerkleTreeWriteOperations } from '@
3
3
  import { type Fr, MAX_NULLIFIERS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX } from '@aztec/circuits.js';
4
4
  import { type IndexedTreeSnapshot, type TreeSnapshot } from '@aztec/merkle-tree';
5
5
 
6
- import { type WorldStateStatus } from '../native/message.js';
6
+ import { type WorldStateStatusFull, type WorldStateStatusSummary } from '../native/message.js';
7
7
 
8
8
  /**
9
9
  *
@@ -38,7 +38,7 @@ export interface MerkleTreeAdminDatabase {
38
38
  * @param block - The L2 block to handle.
39
39
  * @param l1ToL2Messages - The L1 to L2 messages for the block.
40
40
  */
41
- handleL2BlockAndMessages(block: L2Block, l1ToL2Messages: Fr[]): Promise<WorldStateStatus>;
41
+ handleL2BlockAndMessages(block: L2Block, l1ToL2Messages: Fr[]): Promise<WorldStateStatusFull>;
42
42
 
43
43
  /**
44
44
  * Gets a handle that allows reading the latest committed state
@@ -62,27 +62,27 @@ export interface MerkleTreeAdminDatabase {
62
62
  * @param toBlockNumber The block number of the new oldest historical block
63
63
  * @returns The new WorldStateStatus
64
64
  */
65
- removeHistoricalBlocks(toBlockNumber: bigint): Promise<WorldStateStatus>;
65
+ removeHistoricalBlocks(toBlockNumber: bigint): Promise<WorldStateStatusFull>;
66
66
 
67
67
  /**
68
68
  * Removes all pending blocks down to but not including the given block number
69
69
  * @param toBlockNumber The block number of the new tip of the pending chain,
70
70
  * @returns The new WorldStateStatus
71
71
  */
72
- unwindBlocks(toBlockNumber: bigint): Promise<WorldStateStatus>;
72
+ unwindBlocks(toBlockNumber: bigint): Promise<WorldStateStatusFull>;
73
73
 
74
74
  /**
75
75
  * Advances the finalised block number to be the number provided
76
76
  * @param toBlockNumber The block number that is now the tip of the finalised chain
77
77
  * @returns The new WorldStateStatus
78
78
  */
79
- setFinalised(toBlockNumber: bigint): Promise<WorldStateStatus>;
79
+ setFinalised(toBlockNumber: bigint): Promise<WorldStateStatusSummary>;
80
80
 
81
81
  /**
82
- * Gets the current status of the database.
82
+ * Gets the current status summary of the database.
83
83
  * @returns The current WorldStateStatus.
84
84
  */
85
- getStatus(): Promise<WorldStateStatus>;
85
+ getStatusSummary(): Promise<WorldStateStatusSummary>;
86
86
 
87
87
  /** Stops the database */
88
88
  close(): Promise<void>;
@@ -1,4 +1,4 @@
1
- import { type L2Block, MerkleTreeId, PublicDataWrite, type SiblingPath, TxEffect } from '@aztec/circuit-types';
1
+ import { type L2Block, MerkleTreeId, type SiblingPath, TxEffect } from '@aztec/circuit-types';
2
2
  import {
3
3
  type BatchInsertionResult,
4
4
  type IndexedTreeId,
@@ -27,6 +27,7 @@ import {
27
27
  PartialStateReference,
28
28
  PublicDataTreeLeaf,
29
29
  PublicDataTreeLeafPreimage,
30
+ PublicDataWrite,
30
31
  StateReference,
31
32
  } from '@aztec/circuits.js';
32
33
  import { padArrayEnd } from '@aztec/foundation/collection';
@@ -50,7 +51,11 @@ import { type TelemetryClient } from '@aztec/telemetry-client';
50
51
  import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
51
52
  import { type Hasher } from '@aztec/types/interfaces';
52
53
 
53
- import { type WorldStateStatus } from '../native/message.js';
54
+ import {
55
+ type WorldStateStatusFull,
56
+ type WorldStateStatusSummary,
57
+ buildEmptyWorldStateStatusFull,
58
+ } from '../native/message.js';
54
59
  import {
55
60
  INITIAL_NULLIFIER_TREE_SIZE,
56
61
  INITIAL_PUBLIC_DATA_TREE_SIZE,
@@ -197,19 +202,19 @@ export class MerkleTrees implements MerkleTreeAdminDatabase {
197
202
  }
198
203
  }
199
204
 
200
- public removeHistoricalBlocks(_toBlockNumber: bigint): Promise<WorldStateStatus> {
205
+ public removeHistoricalBlocks(_toBlockNumber: bigint): Promise<WorldStateStatusFull> {
201
206
  throw new Error('Method not implemented.');
202
207
  }
203
208
 
204
- public unwindBlocks(_toBlockNumber: bigint): Promise<WorldStateStatus> {
209
+ public unwindBlocks(_toBlockNumber: bigint): Promise<WorldStateStatusFull> {
205
210
  throw new Error('Method not implemented.');
206
211
  }
207
212
 
208
- public setFinalised(_toBlockNumber: bigint): Promise<WorldStateStatus> {
213
+ public setFinalised(_toBlockNumber: bigint): Promise<WorldStateStatusSummary> {
209
214
  throw new Error('Method not implemented.');
210
215
  }
211
216
 
212
- public getStatus(): Promise<WorldStateStatus> {
217
+ public getStatusSummary(): Promise<WorldStateStatusSummary> {
213
218
  throw new Error('Method not implemented.');
214
219
  }
215
220
 
@@ -466,7 +471,7 @@ export class MerkleTrees implements MerkleTreeAdminDatabase {
466
471
  * @param l1ToL2Messages - The L1 to L2 messages for the block.
467
472
  * @returns Whether the block handled was produced by this same node.
468
473
  */
469
- public async handleL2BlockAndMessages(block: L2Block, l1ToL2Messages: Fr[]): Promise<WorldStateStatus> {
474
+ public async handleL2BlockAndMessages(block: L2Block, l1ToL2Messages: Fr[]): Promise<WorldStateStatusFull> {
470
475
  return await this.synchronize(() => this.#handleL2BlockAndMessages(block, l1ToL2Messages));
471
476
  }
472
477
 
@@ -616,7 +621,7 @@ export class MerkleTrees implements MerkleTreeAdminDatabase {
616
621
  * @param l2Block - The L2 block to handle.
617
622
  * @param l1ToL2Messages - The L1 to L2 messages for the block.
618
623
  */
619
- async #handleL2BlockAndMessages(l2Block: L2Block, l1ToL2Messages: Fr[]): Promise<WorldStateStatus> {
624
+ async #handleL2BlockAndMessages(l2Block: L2Block, l1ToL2Messages: Fr[]): Promise<WorldStateStatusFull> {
620
625
  const timer = new Timer();
621
626
 
622
627
  const treeRootWithIdPairs = [
@@ -678,7 +683,7 @@ export class MerkleTrees implements MerkleTreeAdminDatabase {
678
683
  );
679
684
 
680
685
  await publicDataTree.batchInsert(
681
- publicDataWrites.map(write => new PublicDataTreeLeaf(write.leafIndex, write.newValue).toBuffer()),
686
+ publicDataWrites.map(write => write.toBuffer()),
682
687
  PUBLIC_DATA_SUBTREE_HEIGHT,
683
688
  );
684
689
  }
@@ -709,7 +714,7 @@ export class MerkleTrees implements MerkleTreeAdminDatabase {
709
714
 
710
715
  this.metrics.recordDbSize(this.store.estimateSize().bytes);
711
716
  this.metrics.recordSyncDuration('commit', timer);
712
- return { unfinalisedBlockNumber: 0n, finalisedBlockNumber: 0n, oldestHistoricalBlock: 0n } as WorldStateStatus;
717
+ return buildEmptyWorldStateStatusFull();
713
718
  }
714
719
 
715
720
  #isDbPopulated(): boolean {