@aztec/world-state 0.0.1-commit.9b94fc1 → 0.0.1-commit.a072138

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 (44) hide show
  1. package/dest/instrumentation/instrumentation.d.ts +1 -1
  2. package/dest/instrumentation/instrumentation.d.ts.map +1 -1
  3. package/dest/instrumentation/instrumentation.js +17 -41
  4. package/dest/native/merkle_trees_facade.d.ts +10 -4
  5. package/dest/native/merkle_trees_facade.d.ts.map +1 -1
  6. package/dest/native/merkle_trees_facade.js +37 -7
  7. package/dest/native/message.d.ts +14 -12
  8. package/dest/native/message.d.ts.map +1 -1
  9. package/dest/native/message.js +14 -13
  10. package/dest/native/native_world_state.d.ts +16 -13
  11. package/dest/native/native_world_state.d.ts.map +1 -1
  12. package/dest/native/native_world_state.js +22 -17
  13. package/dest/native/native_world_state_instance.d.ts +3 -3
  14. package/dest/native/native_world_state_instance.d.ts.map +1 -1
  15. package/dest/native/native_world_state_instance.js +3 -3
  16. package/dest/synchronizer/config.d.ts +1 -3
  17. package/dest/synchronizer/config.d.ts.map +1 -1
  18. package/dest/synchronizer/config.js +1 -6
  19. package/dest/synchronizer/factory.d.ts +4 -3
  20. package/dest/synchronizer/factory.d.ts.map +1 -1
  21. package/dest/synchronizer/factory.js +5 -5
  22. package/dest/synchronizer/server_world_state_synchronizer.d.ts +10 -16
  23. package/dest/synchronizer/server_world_state_synchronizer.d.ts.map +1 -1
  24. package/dest/synchronizer/server_world_state_synchronizer.js +84 -72
  25. package/dest/test/utils.d.ts +12 -5
  26. package/dest/test/utils.d.ts.map +1 -1
  27. package/dest/test/utils.js +54 -50
  28. package/dest/testing.d.ts +2 -2
  29. package/dest/testing.d.ts.map +1 -1
  30. package/dest/testing.js +1 -1
  31. package/dest/world-state-db/merkle_tree_db.d.ts +10 -11
  32. package/dest/world-state-db/merkle_tree_db.d.ts.map +1 -1
  33. package/package.json +13 -13
  34. package/src/instrumentation/instrumentation.ts +17 -41
  35. package/src/native/merkle_trees_facade.ts +39 -5
  36. package/src/native/message.ts +25 -23
  37. package/src/native/native_world_state.ts +52 -28
  38. package/src/native/native_world_state_instance.ts +5 -3
  39. package/src/synchronizer/config.ts +1 -14
  40. package/src/synchronizer/factory.ts +7 -1
  41. package/src/synchronizer/server_world_state_synchronizer.ts +98 -98
  42. package/src/test/utils.ts +86 -91
  43. package/src/testing.ts +1 -1
  44. package/src/world-state-db/merkle_tree_db.ts +13 -14
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/world-state",
3
- "version": "0.0.1-commit.9b94fc1",
3
+ "version": "0.0.1-commit.a072138",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -18,8 +18,8 @@
18
18
  "tsconfig": "./tsconfig.json"
19
19
  },
20
20
  "scripts": {
21
- "build": "yarn clean && tsgo -b",
22
- "build:dev": "tsgo -b --watch",
21
+ "build": "yarn clean && ../scripts/tsc.sh",
22
+ "build:dev": "../scripts/tsc.sh --watch",
23
23
  "clean": "rm -rf ./dest .tsbuildinfo",
24
24
  "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}"
25
25
  },
@@ -64,23 +64,23 @@
64
64
  ]
65
65
  },
66
66
  "dependencies": {
67
- "@aztec/constants": "0.0.1-commit.9b94fc1",
68
- "@aztec/foundation": "0.0.1-commit.9b94fc1",
69
- "@aztec/kv-store": "0.0.1-commit.9b94fc1",
70
- "@aztec/merkle-tree": "0.0.1-commit.9b94fc1",
71
- "@aztec/native": "0.0.1-commit.9b94fc1",
72
- "@aztec/protocol-contracts": "0.0.1-commit.9b94fc1",
73
- "@aztec/stdlib": "0.0.1-commit.9b94fc1",
74
- "@aztec/telemetry-client": "0.0.1-commit.9b94fc1",
67
+ "@aztec/constants": "0.0.1-commit.a072138",
68
+ "@aztec/foundation": "0.0.1-commit.a072138",
69
+ "@aztec/kv-store": "0.0.1-commit.a072138",
70
+ "@aztec/merkle-tree": "0.0.1-commit.a072138",
71
+ "@aztec/native": "0.0.1-commit.a072138",
72
+ "@aztec/protocol-contracts": "0.0.1-commit.a072138",
73
+ "@aztec/stdlib": "0.0.1-commit.a072138",
74
+ "@aztec/telemetry-client": "0.0.1-commit.a072138",
75
75
  "tslib": "^2.4.0",
76
76
  "zod": "^3.23.8"
77
77
  },
78
78
  "devDependencies": {
79
- "@aztec/archiver": "0.0.1-commit.9b94fc1",
79
+ "@aztec/archiver": "0.0.1-commit.a072138",
80
80
  "@jest/globals": "^30.0.0",
81
81
  "@types/jest": "^30.0.0",
82
82
  "@types/node": "^22.15.17",
83
- "@typescript/native-preview": "7.0.0-dev.20251126.1",
83
+ "@typescript/native-preview": "7.0.0-dev.20260113.1",
84
84
  "jest": "^30.0.0",
85
85
  "jest-mock-extended": "^4.0.0",
86
86
  "ts-node": "^10.9.1",
@@ -7,7 +7,7 @@ import {
7
7
  Metrics,
8
8
  type TelemetryClient,
9
9
  type UpDownCounter,
10
- ValueType,
10
+ createUpDownCounterWithDefault,
11
11
  } from '@aztec/telemetry-client';
12
12
 
13
13
  import {
@@ -46,55 +46,31 @@ export class WorldStateInstrumentation {
46
46
  private log: Logger = createLogger('world-state:instrumentation'),
47
47
  ) {
48
48
  const meter = telemetry.getMeter('World State');
49
- this.dbMapSize = meter.createGauge(Metrics.WORLD_STATE_DB_MAP_SIZE, {
50
- description: `The current configured map size for each merkle tree`,
51
- valueType: ValueType.INT,
52
- });
49
+ this.dbMapSize = meter.createGauge(Metrics.WORLD_STATE_DB_MAP_SIZE);
53
50
 
54
- this.dbPhysicalSize = meter.createGauge(Metrics.WORLD_STATE_DB_PHYSICAL_SIZE, {
55
- description: `The current physical disk space used for each database`,
56
- valueType: ValueType.INT,
57
- });
51
+ this.dbPhysicalSize = meter.createGauge(Metrics.WORLD_STATE_DB_PHYSICAL_SIZE);
58
52
 
59
- this.treeSize = meter.createGauge(Metrics.WORLD_STATE_TREE_SIZE, {
60
- description: `The current number of leaves in each merkle tree`,
61
- valueType: ValueType.INT,
62
- });
53
+ this.treeSize = meter.createGauge(Metrics.WORLD_STATE_TREE_SIZE);
63
54
 
64
- this.unfinalizedHeight = meter.createGauge(Metrics.WORLD_STATE_UNFINALIZED_HEIGHT, {
65
- description: `The unfinalized block height of each merkle tree`,
66
- valueType: ValueType.INT,
67
- });
55
+ this.unfinalizedHeight = meter.createGauge(Metrics.WORLD_STATE_UNFINALIZED_HEIGHT);
68
56
 
69
- this.finalizedHeight = meter.createGauge(Metrics.WORLD_STATE_FINALIZED_HEIGHT, {
70
- description: `The finalized block height of each merkle tree`,
71
- valueType: ValueType.INT,
72
- });
57
+ this.finalizedHeight = meter.createGauge(Metrics.WORLD_STATE_FINALIZED_HEIGHT);
73
58
 
74
- this.oldestBlock = meter.createGauge(Metrics.WORLD_STATE_OLDEST_BLOCK, {
75
- description: `The oldest historical block of each merkle tree`,
76
- valueType: ValueType.INT,
77
- });
59
+ this.oldestBlock = meter.createGauge(Metrics.WORLD_STATE_OLDEST_BLOCK);
78
60
 
79
- this.dbUsedSize = meter.createGauge(Metrics.WORLD_STATE_DB_USED_SIZE, {
80
- description: `The current used database size for each db of each merkle tree`,
81
- valueType: ValueType.INT,
82
- });
61
+ this.dbUsedSize = meter.createGauge(Metrics.WORLD_STATE_DB_USED_SIZE);
83
62
 
84
- this.dbNumItems = meter.createGauge(Metrics.WORLD_STATE_DB_NUM_ITEMS, {
85
- description: `The current number of items in each database of each merkle tree`,
86
- valueType: ValueType.INT,
87
- });
63
+ this.dbNumItems = meter.createGauge(Metrics.WORLD_STATE_DB_NUM_ITEMS);
88
64
 
89
- this.requestHistogram = meter.createHistogram(Metrics.WORLD_STATE_REQUEST_TIME, {
90
- description: 'The round trip time of world state requests',
91
- unit: 'us',
92
- valueType: ValueType.INT,
93
- });
65
+ this.requestHistogram = meter.createHistogram(Metrics.WORLD_STATE_REQUEST_TIME);
94
66
 
95
- this.criticalErrors = meter.createUpDownCounter(Metrics.WORLD_STATE_CRITICAL_ERROR_COUNT, {
96
- description: 'The number of critical errors in the world state',
97
- valueType: ValueType.INT,
67
+ this.criticalErrors = createUpDownCounterWithDefault(meter, Metrics.WORLD_STATE_CRITICAL_ERROR_COUNT, {
68
+ [Attributes.ERROR_TYPE]: [
69
+ 'synch_pending_block',
70
+ 'finalize_block',
71
+ 'prune_pending_block',
72
+ 'prune_historical_block',
73
+ ],
98
74
  });
99
75
  }
100
76
 
@@ -1,5 +1,8 @@
1
- import { Fr } from '@aztec/foundation/fields';
1
+ import { BlockNumber } from '@aztec/foundation/branded-types';
2
+ import { Fr } from '@aztec/foundation/curves/bn254';
3
+ import { createLogger } from '@aztec/foundation/log';
2
4
  import { serializeToBuffer } from '@aztec/foundation/serialize';
5
+ import { sleep } from '@aztec/foundation/sleep';
3
6
  import { type IndexedTreeLeafPreimage, SiblingPath } from '@aztec/foundation/trees';
4
7
  import type {
5
8
  BatchInsertionResult,
@@ -191,19 +194,26 @@ export class MerkleTreesFacade implements MerkleTreeReadOperations {
191
194
  async getBlockNumbersForLeafIndices<ID extends MerkleTreeId>(
192
195
  treeId: ID,
193
196
  leafIndices: bigint[],
194
- ): Promise<(bigint | undefined)[]> {
197
+ ): Promise<(BlockNumber | undefined)[]> {
195
198
  const response = await this.instance.call(WorldStateMessageType.GET_BLOCK_NUMBERS_FOR_LEAF_INDICES, {
196
199
  treeId,
197
200
  revision: this.revision,
198
201
  leafIndices,
199
202
  });
200
203
 
201
- return response.blockNumbers.map(x => (x === undefined || x === null ? undefined : BigInt(x)));
204
+ return response.blockNumbers.map(x => (x === undefined || x === null ? undefined : BlockNumber(Number(x))));
202
205
  }
203
206
  }
204
207
 
205
208
  export class MerkleTreesForkFacade extends MerkleTreesFacade implements MerkleTreeWriteOperations {
206
- constructor(instance: NativeWorldStateInstance, initialHeader: BlockHeader, revision: WorldStateRevision) {
209
+ private log = createLogger('world-state:merkle-trees-fork-facade');
210
+
211
+ constructor(
212
+ instance: NativeWorldStateInstance,
213
+ initialHeader: BlockHeader,
214
+ revision: WorldStateRevision,
215
+ private opts: { closeDelayMs?: number },
216
+ ) {
207
217
  assert.notEqual(revision.forkId, 0, 'Fork ID must be set');
208
218
  assert.equal(revision.includeUncommitted, true, 'Fork must include uncommitted data');
209
219
  super(instance, initialHeader, revision);
@@ -282,7 +292,31 @@ export class MerkleTreesForkFacade extends MerkleTreesFacade implements MerkleTr
282
292
 
283
293
  public async close(): Promise<void> {
284
294
  assert.notEqual(this.revision.forkId, 0, 'Fork ID must be set');
285
- await this.instance.call(WorldStateMessageType.DELETE_FORK, { forkId: this.revision.forkId });
295
+ try {
296
+ await this.instance.call(WorldStateMessageType.DELETE_FORK, { forkId: this.revision.forkId });
297
+ } catch (err: any) {
298
+ // Ignore errors due to native instance being closed during shutdown.
299
+ // This can happen when validators are still processing block proposals while the node is stopping.
300
+ if (err?.message === 'Native instance is closed') {
301
+ return;
302
+ }
303
+ throw err;
304
+ }
305
+ }
306
+
307
+ async [Symbol.dispose](): Promise<void> {
308
+ if (this.opts.closeDelayMs) {
309
+ void sleep(this.opts.closeDelayMs)
310
+ .then(() => this.close())
311
+ .catch(err => {
312
+ if (err && 'message' in err && err.message === 'Native instance is closed') {
313
+ return; // Ignore errors due to native instance being closed
314
+ }
315
+ this.log.warn('Error closing MerkleTreesForkFacade after delay', { err });
316
+ });
317
+ } else {
318
+ await this.close();
319
+ }
286
320
  }
287
321
 
288
322
  public async createCheckpoint(): Promise<void> {
@@ -1,5 +1,7 @@
1
- import { Fr } from '@aztec/foundation/fields';
1
+ import { BlockNumber } from '@aztec/foundation/branded-types';
2
+ import { Fr } from '@aztec/foundation/curves/bn254';
2
3
  import type { Tuple } from '@aztec/foundation/serialize';
4
+ import type { BlockHash } from '@aztec/stdlib/block';
3
5
  import { AppendOnlyTreeSnapshot, MerkleTreeId } from '@aztec/stdlib/trees';
4
6
  import type { StateReference } from '@aztec/stdlib/tx';
5
7
  import type { UInt32 } from '@aztec/stdlib/types';
@@ -56,11 +58,11 @@ interface WithTreeId {
56
58
 
57
59
  export interface WorldStateStatusSummary {
58
60
  /** Last block number that can still be unwound. */
59
- unfinalizedBlockNumber: bigint;
61
+ unfinalizedBlockNumber: BlockNumber;
60
62
  /** Last block number that is finalized and cannot be unwound. */
61
- finalizedBlockNumber: bigint;
63
+ finalizedBlockNumber: BlockNumber;
62
64
  /** Oldest block still available for historical queries and forks. */
63
- oldestHistoricalBlock: bigint;
65
+ oldestHistoricalBlock: BlockNumber;
64
66
  /** Whether the trees are in sync with each other */
65
67
  treesAreSynched: boolean;
66
68
  }
@@ -81,11 +83,11 @@ export interface TreeMeta {
81
83
  /** The tree's initial root value */
82
84
  initialRoot: Fr;
83
85
  /** The current oldest historical block number of the tree */
84
- oldestHistoricBlock: bigint;
86
+ oldestHistoricBlock: BlockNumber;
85
87
  /** The current unfinalized block number of the tree */
86
- unfinalizedBlockHeight: bigint;
88
+ unfinalizedBlockHeight: BlockNumber;
87
89
  /** The current finalized block number of the tree */
88
- finalizedBlockHeight: bigint;
90
+ finalizedBlockHeight: BlockNumber;
89
91
  }
90
92
 
91
93
  export interface DBStats {
@@ -173,9 +175,9 @@ export function buildEmptyTreeMeta() {
173
175
  depth: 0,
174
176
  size: 0n,
175
177
  committedSize: 0n,
176
- unfinalizedBlockHeight: 0n,
177
- finalizedBlockHeight: 0n,
178
- oldestHistoricBlock: 0n,
178
+ unfinalizedBlockHeight: BlockNumber.ZERO,
179
+ finalizedBlockHeight: BlockNumber.ZERO,
180
+ oldestHistoricBlock: BlockNumber.ZERO,
179
181
  root: Fr.ZERO,
180
182
  initialRoot: Fr.ZERO,
181
183
  initialSize: 0n,
@@ -204,9 +206,9 @@ export function buildEmptyWorldStateDBStats() {
204
206
 
205
207
  export function buildEmptyWorldStateSummary() {
206
208
  return {
207
- unfinalizedBlockNumber: 0n,
208
- finalizedBlockNumber: 0n,
209
- oldestHistoricalBlock: 0n,
209
+ unfinalizedBlockNumber: BlockNumber.ZERO,
210
+ finalizedBlockNumber: BlockNumber.ZERO,
211
+ oldestHistoricalBlock: BlockNumber.ZERO,
210
212
  treesAreSynched: true,
211
213
  } as WorldStateStatusSummary;
212
214
  }
@@ -220,9 +222,9 @@ export function buildEmptyWorldStateStatusFull() {
220
222
  }
221
223
 
222
224
  export function sanitizeSummary(summary: WorldStateStatusSummary) {
223
- summary.finalizedBlockNumber = BigInt(summary.finalizedBlockNumber);
224
- summary.unfinalizedBlockNumber = BigInt(summary.unfinalizedBlockNumber);
225
- summary.oldestHistoricalBlock = BigInt(summary.oldestHistoricalBlock);
225
+ summary.finalizedBlockNumber = BlockNumber.fromBigInt(BigInt(summary.finalizedBlockNumber));
226
+ summary.unfinalizedBlockNumber = BlockNumber.fromBigInt(BigInt(summary.unfinalizedBlockNumber));
227
+ summary.oldestHistoricalBlock = BlockNumber.fromBigInt(BigInt(summary.oldestHistoricalBlock));
226
228
  return summary;
227
229
  }
228
230
 
@@ -234,11 +236,11 @@ export function sanitizeDBStats(stats: DBStats) {
234
236
 
235
237
  export function sanitizeMeta(meta: TreeMeta) {
236
238
  meta.committedSize = BigInt(meta.committedSize);
237
- meta.finalizedBlockHeight = BigInt(meta.finalizedBlockHeight);
239
+ meta.finalizedBlockHeight = BlockNumber.fromBigInt(BigInt(meta.finalizedBlockHeight));
238
240
  meta.initialSize = BigInt(meta.initialSize);
239
- meta.oldestHistoricBlock = BigInt(meta.oldestHistoricBlock);
241
+ meta.oldestHistoricBlock = BlockNumber.fromBigInt(BigInt(meta.oldestHistoricBlock));
240
242
  meta.size = BigInt(meta.size);
241
- meta.unfinalizedBlockHeight = BigInt(meta.unfinalizedBlockHeight);
243
+ meta.unfinalizedBlockHeight = BlockNumber.fromBigInt(BigInt(meta.unfinalizedBlockHeight));
242
244
  return meta;
243
245
  }
244
246
 
@@ -310,7 +312,7 @@ interface WithLeafValues {
310
312
  }
311
313
 
312
314
  interface BlockShiftRequest extends WithCanonicalForkId {
313
- toBlockNumber: bigint;
315
+ toBlockNumber: BlockNumber;
314
316
  }
315
317
 
316
318
  interface WithLeaves {
@@ -409,9 +411,9 @@ interface UpdateArchiveRequest extends WithForkId {
409
411
  }
410
412
 
411
413
  interface SyncBlockRequest extends WithCanonicalForkId {
412
- blockNumber: number;
414
+ blockNumber: BlockNumber;
413
415
  blockStateRef: BlockStateReference;
414
- blockHeaderHash: Fr;
416
+ blockHeaderHash: BlockHash;
415
417
  paddedNoteHashes: readonly SerializedLeafValue[];
416
418
  paddedL1ToL2Messages: readonly SerializedLeafValue[];
417
419
  paddedNullifiers: readonly SerializedLeafValue[];
@@ -420,7 +422,7 @@ interface SyncBlockRequest extends WithCanonicalForkId {
420
422
 
421
423
  interface CreateForkRequest extends WithCanonicalForkId {
422
424
  latest: boolean;
423
- blockNumber: number;
425
+ blockNumber: BlockNumber;
424
426
  }
425
427
 
426
428
  interface CreateForkResponse {
@@ -1,11 +1,12 @@
1
1
  import { MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
2
+ import { BlockNumber } from '@aztec/foundation/branded-types';
2
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
6
  import { tryRmDir } from '@aztec/foundation/fs';
6
- import { type Logger, createLogger } from '@aztec/foundation/log';
7
- import type { L2Block, L2BlockNew } from '@aztec/stdlib/block';
8
- import { DatabaseVersionManager } from '@aztec/stdlib/database-version';
7
+ import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
8
+ import type { L2Block } from '@aztec/stdlib/block';
9
+ import { DatabaseVersionManager } from '@aztec/stdlib/database-version/manager';
9
10
  import type {
10
11
  IndexedTreeId,
11
12
  MerkleTreeReadOperations,
@@ -51,7 +52,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
51
52
  protected constructor(
52
53
  protected instance: NativeWorldState,
53
54
  protected readonly worldStateInstrumentation: WorldStateInstrumentation,
54
- protected readonly log: Logger = createLogger('world-state:database'),
55
+ protected readonly log: Logger,
55
56
  private readonly cleanup = () => Promise.resolve(),
56
57
  ) {}
57
58
 
@@ -61,9 +62,10 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
61
62
  wsTreeMapSizes: WorldStateTreeMapSizes,
62
63
  prefilledPublicData: PublicDataTreeLeaf[] = [],
63
64
  instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
64
- log = createLogger('world-state:database'),
65
+ bindings?: LoggerBindings,
65
66
  cleanup = () => Promise.resolve(),
66
67
  ): Promise<NativeWorldStateService> {
68
+ const log = createLogger('world-state:database', bindings);
67
69
  const worldStateDirectory = join(dataDir, WORLD_STATE_DIR);
68
70
  // Create a version manager to handle versioning
69
71
  const versionManager = new DatabaseVersionManager({
@@ -71,7 +73,9 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
71
73
  rollupAddress,
72
74
  dataDirectory: worldStateDirectory,
73
75
  onOpen: (dir: string) => {
74
- return Promise.resolve(new NativeWorldState(dir, wsTreeMapSizes, prefilledPublicData, instrumentation));
76
+ return Promise.resolve(
77
+ new NativeWorldState(dir, wsTreeMapSizes, prefilledPublicData, instrumentation, bindings),
78
+ );
75
79
  },
76
80
  });
77
81
 
@@ -92,8 +96,9 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
92
96
  cleanupTmpDir = true,
93
97
  prefilledPublicData: PublicDataTreeLeaf[] = [],
94
98
  instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
99
+ bindings?: LoggerBindings,
95
100
  ): Promise<NativeWorldStateService> {
96
- const log = createLogger('world-state:database');
101
+ const log = createLogger('world-state:database', bindings);
97
102
  const dataDir = await mkdtemp(join(tmpdir(), 'aztec-world-state-'));
98
103
  const dbMapSizeKb = 10 * 1024 * 1024;
99
104
  const worldStateTreeMapSizes: WorldStateTreeMapSizes = {
@@ -115,7 +120,15 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
115
120
  }
116
121
  };
117
122
 
118
- return this.new(rollupAddress, dataDir, worldStateTreeMapSizes, prefilledPublicData, instrumentation, log, cleanup);
123
+ return this.new(
124
+ rollupAddress,
125
+ dataDir,
126
+ worldStateTreeMapSizes,
127
+ prefilledPublicData,
128
+ instrumentation,
129
+ bindings,
130
+ cleanup,
131
+ );
119
132
  }
120
133
 
121
134
  protected async init() {
@@ -134,7 +147,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
134
147
 
135
148
  // the initial header _must_ be the first element in the archive tree
136
149
  // if this assertion fails, check that the hashing done in Header in yarn-project matches the initial header hash done in world_state.cpp
137
- const indices = await committed.findLeafIndices(MerkleTreeId.ARCHIVE, [await this.initialHeader.hash()]);
150
+ const indices = await committed.findLeafIndices(MerkleTreeId.ARCHIVE, [(await this.initialHeader.hash()).toFr()]);
138
151
  const initialHeaderIndex = indices[0];
139
152
  assert.strictEqual(initialHeaderIndex, 0n, 'Invalid initial archive state');
140
153
  }
@@ -150,7 +163,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
150
163
  return new MerkleTreesFacade(this.instance, this.initialHeader!, WorldStateRevision.empty());
151
164
  }
152
165
 
153
- public getSnapshot(blockNumber: number): MerkleTreeReadOperations {
166
+ public getSnapshot(blockNumber: BlockNumber): MerkleTreeReadOperations {
154
167
  return new MerkleTreesFacade(
155
168
  this.instance,
156
169
  this.initialHeader!,
@@ -158,16 +171,24 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
158
171
  );
159
172
  }
160
173
 
161
- public async fork(blockNumber?: number): Promise<MerkleTreeWriteOperations> {
174
+ public async fork(
175
+ blockNumber?: BlockNumber,
176
+ opts: { closeDelayMs?: number } = {},
177
+ ): Promise<MerkleTreeWriteOperations> {
162
178
  const resp = await this.instance.call(WorldStateMessageType.CREATE_FORK, {
163
179
  latest: blockNumber === undefined,
164
- blockNumber: blockNumber ?? 0,
180
+ blockNumber: blockNumber ?? BlockNumber.ZERO,
165
181
  canonical: true,
166
182
  });
167
183
  return new MerkleTreesForkFacade(
168
184
  this.instance,
169
185
  this.initialHeader!,
170
- new WorldStateRevision(/*forkId=*/ resp.forkId, /* blockNumber=*/ 0, /* includeUncommitted=*/ true),
186
+ new WorldStateRevision(
187
+ /*forkId=*/ resp.forkId,
188
+ /* blockNumber=*/ BlockNumber.ZERO,
189
+ /* includeUncommitted=*/ true,
190
+ ),
191
+ opts,
171
192
  );
172
193
  }
173
194
 
@@ -175,21 +196,24 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
175
196
  return this.initialHeader!;
176
197
  }
177
198
 
178
- public async handleL2BlockAndMessages(
179
- l2Block: L2Block | L2BlockNew,
180
- l1ToL2Messages: Fr[],
181
- // TODO(#17027)
182
- // Temporary hack to only insert l1 to l2 messages for the first block in a checkpoint.
183
- isFirstBlock = true,
184
- ): Promise<WorldStateStatusFull> {
185
- // We have to pad both the values within tx effects because that's how the trees are built by circuits.
186
- const paddedNoteHashes = l2Block.body.txEffects.flatMap(txEffect =>
187
- padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
188
- );
199
+ public async handleL2BlockAndMessages(l2Block: L2Block, l1ToL2Messages: Fr[]): Promise<WorldStateStatusFull> {
200
+ const isFirstBlock = l2Block.indexWithinCheckpoint === 0;
201
+ if (!isFirstBlock && l1ToL2Messages.length > 0) {
202
+ throw new Error(
203
+ `L1 to L2 messages must be empty for non-first blocks, but got ${l1ToL2Messages.length} messages for block ${l2Block.number}.`,
204
+ );
205
+ }
206
+
207
+ // We have to pad the given l1 to l2 messages, and the note hashes and nullifiers within tx effects, because that's
208
+ // how the trees are built by circuits.
189
209
  const paddedL1ToL2Messages = isFirstBlock
190
210
  ? padArrayEnd<Fr, number>(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP)
191
211
  : [];
192
212
 
213
+ const paddedNoteHashes = l2Block.body.txEffects.flatMap(txEffect =>
214
+ padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
215
+ );
216
+
193
217
  const paddedNullifiers = l2Block.body.txEffects
194
218
  .flatMap(txEffect => padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX))
195
219
  .map(nullifier => new NullifierLeaf(nullifier));
@@ -256,7 +280,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
256
280
  * @param toBlockNumber The block number that is now the tip of the finalized chain
257
281
  * @returns The new WorldStateStatus
258
282
  */
259
- public async setFinalized(toBlockNumber: bigint) {
283
+ public async setFinalized(toBlockNumber: BlockNumber) {
260
284
  try {
261
285
  await this.instance.call(
262
286
  WorldStateMessageType.FINALIZE_BLOCKS,
@@ -279,7 +303,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
279
303
  * @param toBlockNumber The block number of the new oldest historical block
280
304
  * @returns The new WorldStateStatus
281
305
  */
282
- public async removeHistoricalBlocks(toBlockNumber: bigint) {
306
+ public async removeHistoricalBlocks(toBlockNumber: BlockNumber) {
283
307
  try {
284
308
  return await this.instance.call(
285
309
  WorldStateMessageType.REMOVE_HISTORICAL_BLOCKS,
@@ -301,7 +325,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
301
325
  * @param toBlockNumber The block number of the new tip of the pending chain,
302
326
  * @returns The new WorldStateStatus
303
327
  */
304
- public async unwindBlocks(toBlockNumber: bigint) {
328
+ public async unwindBlocks(toBlockNumber: BlockNumber) {
305
329
  try {
306
330
  return await this.instance.call(
307
331
  WorldStateMessageType.UNWIND_BLOCKS,
@@ -8,7 +8,7 @@ import {
8
8
  NULLIFIER_TREE_HEIGHT,
9
9
  PUBLIC_DATA_TREE_HEIGHT,
10
10
  } from '@aztec/constants';
11
- import { type Logger, createLogger } from '@aztec/foundation/log';
11
+ import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
12
12
  import { NativeWorldState as BaseNativeWorldState, MsgpackChannel } from '@aztec/native';
13
13
  import { MerkleTreeId } from '@aztec/stdlib/trees';
14
14
  import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
@@ -57,7 +57,8 @@ export class NativeWorldState implements NativeWorldStateInstance {
57
57
  private readonly wsTreeMapSizes: WorldStateTreeMapSizes,
58
58
  private readonly prefilledPublicData: PublicDataTreeLeaf[] = [],
59
59
  private readonly instrumentation: WorldStateInstrumentation,
60
- private readonly log: Logger = createLogger('world-state:database'),
60
+ bindings?: LoggerBindings,
61
+ private readonly log: Logger = createLogger('world-state:database', bindings),
61
62
  ) {
62
63
  const threads = Math.min(cpus().length, MAX_WORLD_STATE_THREADS);
63
64
  log.info(
@@ -80,7 +81,7 @@ export class NativeWorldState implements NativeWorldStateInstance {
80
81
  [MerkleTreeId.PUBLIC_DATA_TREE]: 2 * MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
81
82
  },
82
83
  prefilledPublicDataBufferArray,
83
- GeneratorIndex.BLOCK_HASH,
84
+ GeneratorIndex.BLOCK_HEADER_HASH,
84
85
  {
85
86
  [MerkleTreeId.NULLIFIER_TREE]: wsTreeMapSizes.nullifierTreeMapSizeKb,
86
87
  [MerkleTreeId.NOTE_HASH_TREE]: wsTreeMapSizes.noteHashTreeMapSizeKb,
@@ -105,6 +106,7 @@ export class NativeWorldState implements NativeWorldStateInstance {
105
106
  this.wsTreeMapSizes,
106
107
  this.prefilledPublicData,
107
108
  this.instrumentation,
109
+ this.log.getBindings(),
108
110
  this.log,
109
111
  );
110
112
  }
@@ -1,18 +1,10 @@
1
- import {
2
- type ConfigMappingsType,
3
- booleanConfigHelper,
4
- getConfigFromMappings,
5
- numberConfigHelper,
6
- } from '@aztec/foundation/config';
1
+ import { type ConfigMappingsType, getConfigFromMappings, numberConfigHelper } from '@aztec/foundation/config';
7
2
 
8
3
  /** World State synchronizer configuration values. */
9
4
  export interface WorldStateConfig {
10
5
  /** The frequency in which to check. */
11
6
  worldStateBlockCheckIntervalMS: number;
12
7
 
13
- /** Whether to follow only the proven chain. */
14
- worldStateProvenBlocksOnly: boolean;
15
-
16
8
  /** Size of the batch for each get-blocks request from the synchronizer to the archiver. */
17
9
  worldStateBlockRequestBatchSize?: number;
18
10
 
@@ -48,11 +40,6 @@ export const worldStateConfigMappings: ConfigMappingsType<WorldStateConfig> = {
48
40
  defaultValue: 100,
49
41
  description: 'The frequency in which to check.',
50
42
  },
51
- worldStateProvenBlocksOnly: {
52
- env: 'WS_PROVEN_BLOCKS_ONLY',
53
- description: 'Whether to follow only the proven chain.',
54
- ...booleanConfigHelper(),
55
- },
56
43
  worldStateBlockRequestBatchSize: {
57
44
  env: 'WS_BLOCK_REQUEST_BATCH_SIZE',
58
45
  parseEnv: (val: string | undefined) => (val ? +val : undefined),
@@ -1,3 +1,4 @@
1
+ import type { LoggerBindings } from '@aztec/foundation/log';
1
2
  import type { DataStoreConfig } from '@aztec/kv-store/config';
2
3
  import type { L2BlockSource } from '@aztec/stdlib/block';
3
4
  import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
@@ -22,9 +23,10 @@ export async function createWorldStateSynchronizer(
22
23
  l2BlockSource: L2BlockSource & L1ToL2MessageSource,
23
24
  prefilledPublicData: PublicDataTreeLeaf[] = [],
24
25
  client: TelemetryClient = getTelemetryClient(),
26
+ bindings?: LoggerBindings,
25
27
  ) {
26
28
  const instrumentation = new WorldStateInstrumentation(client);
27
- const merkleTrees = await createWorldState(config, prefilledPublicData, instrumentation);
29
+ const merkleTrees = await createWorldState(config, prefilledPublicData, instrumentation, bindings);
28
30
  return new ServerWorldStateSynchronizer(merkleTrees, l2BlockSource, config, instrumentation);
29
31
  }
30
32
 
@@ -42,6 +44,7 @@ export async function createWorldState(
42
44
  Pick<DataStoreConfig, 'dataDirectory' | 'dataStoreMapSizeKb' | 'l1Contracts'>,
43
45
  prefilledPublicData: PublicDataTreeLeaf[] = [],
44
46
  instrumentation: WorldStateInstrumentation = new WorldStateInstrumentation(getTelemetryClient()),
47
+ bindings?: LoggerBindings,
45
48
  ) {
46
49
  const dataDirectory = config.worldStateDataDirectory ?? config.dataDirectory;
47
50
  const dataStoreMapSizeKb = config.worldStateDbMapSizeKb ?? config.dataStoreMapSizeKb;
@@ -65,11 +68,14 @@ export async function createWorldState(
65
68
  wsTreeMapSizes,
66
69
  prefilledPublicData,
67
70
  instrumentation,
71
+ bindings,
68
72
  )
69
73
  : await NativeWorldStateService.tmp(
70
74
  config.l1Contracts.rollupAddress,
71
75
  !['true', '1'].includes(process.env.DEBUG_WORLD_STATE!),
72
76
  prefilledPublicData,
77
+ instrumentation,
78
+ bindings,
73
79
  );
74
80
 
75
81
  return merkleTrees;