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

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 (50) 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/fork_checkpoint.d.ts +7 -1
  5. package/dest/native/fork_checkpoint.d.ts.map +1 -1
  6. package/dest/native/fork_checkpoint.js +15 -3
  7. package/dest/native/merkle_trees_facade.d.ts +15 -8
  8. package/dest/native/merkle_trees_facade.d.ts.map +1 -1
  9. package/dest/native/merkle_trees_facade.js +53 -15
  10. package/dest/native/message.d.ts +24 -15
  11. package/dest/native/message.d.ts.map +1 -1
  12. package/dest/native/message.js +14 -13
  13. package/dest/native/native_world_state.d.ts +19 -14
  14. package/dest/native/native_world_state.d.ts.map +1 -1
  15. package/dest/native/native_world_state.js +31 -21
  16. package/dest/native/native_world_state_instance.d.ts +5 -5
  17. package/dest/native/native_world_state_instance.d.ts.map +1 -1
  18. package/dest/native/native_world_state_instance.js +8 -7
  19. package/dest/native/world_state_ops_queue.js +5 -5
  20. package/dest/synchronizer/config.d.ts +3 -5
  21. package/dest/synchronizer/config.d.ts.map +1 -1
  22. package/dest/synchronizer/config.js +14 -16
  23. package/dest/synchronizer/factory.d.ts +6 -5
  24. package/dest/synchronizer/factory.d.ts.map +1 -1
  25. package/dest/synchronizer/factory.js +6 -5
  26. package/dest/synchronizer/server_world_state_synchronizer.d.ts +11 -17
  27. package/dest/synchronizer/server_world_state_synchronizer.d.ts.map +1 -1
  28. package/dest/synchronizer/server_world_state_synchronizer.js +162 -81
  29. package/dest/test/utils.d.ts +12 -5
  30. package/dest/test/utils.d.ts.map +1 -1
  31. package/dest/test/utils.js +54 -50
  32. package/dest/testing.d.ts +5 -4
  33. package/dest/testing.d.ts.map +1 -1
  34. package/dest/testing.js +11 -7
  35. package/dest/world-state-db/merkle_tree_db.d.ts +10 -20
  36. package/dest/world-state-db/merkle_tree_db.d.ts.map +1 -1
  37. package/package.json +12 -13
  38. package/src/instrumentation/instrumentation.ts +17 -41
  39. package/src/native/fork_checkpoint.ts +19 -3
  40. package/src/native/merkle_trees_facade.ts +62 -16
  41. package/src/native/message.ts +37 -26
  42. package/src/native/native_world_state.ts +52 -34
  43. package/src/native/native_world_state_instance.ts +14 -8
  44. package/src/native/world_state_ops_queue.ts +5 -5
  45. package/src/synchronizer/config.ts +15 -26
  46. package/src/synchronizer/factory.ts +13 -7
  47. package/src/synchronizer/server_world_state_synchronizer.ts +184 -106
  48. package/src/test/utils.ts +86 -91
  49. package/src/testing.ts +9 -10
  50. package/src/world-state-db/merkle_tree_db.ts +13 -24
@@ -1,4 +1,5 @@
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';
3
4
  import { AppendOnlyTreeSnapshot, MerkleTreeId } from '@aztec/stdlib/trees';
4
5
  import type { StateReference } from '@aztec/stdlib/tx';
@@ -56,11 +57,11 @@ interface WithTreeId {
56
57
 
57
58
  export interface WorldStateStatusSummary {
58
59
  /** Last block number that can still be unwound. */
59
- unfinalizedBlockNumber: bigint;
60
+ unfinalizedBlockNumber: BlockNumber;
60
61
  /** Last block number that is finalized and cannot be unwound. */
61
- finalizedBlockNumber: bigint;
62
+ finalizedBlockNumber: BlockNumber;
62
63
  /** Oldest block still available for historical queries and forks. */
63
- oldestHistoricalBlock: bigint;
64
+ oldestHistoricalBlock: BlockNumber;
64
65
  /** Whether the trees are in sync with each other */
65
66
  treesAreSynched: boolean;
66
67
  }
@@ -81,11 +82,11 @@ export interface TreeMeta {
81
82
  /** The tree's initial root value */
82
83
  initialRoot: Fr;
83
84
  /** The current oldest historical block number of the tree */
84
- oldestHistoricBlock: bigint;
85
+ oldestHistoricBlock: BlockNumber;
85
86
  /** The current unfinalized block number of the tree */
86
- unfinalizedBlockHeight: bigint;
87
+ unfinalizedBlockHeight: BlockNumber;
87
88
  /** The current finalized block number of the tree */
88
- finalizedBlockHeight: bigint;
89
+ finalizedBlockHeight: BlockNumber;
89
90
  }
90
91
 
91
92
  export interface DBStats {
@@ -173,9 +174,9 @@ export function buildEmptyTreeMeta() {
173
174
  depth: 0,
174
175
  size: 0n,
175
176
  committedSize: 0n,
176
- unfinalizedBlockHeight: 0n,
177
- finalizedBlockHeight: 0n,
178
- oldestHistoricBlock: 0n,
177
+ unfinalizedBlockHeight: BlockNumber.ZERO,
178
+ finalizedBlockHeight: BlockNumber.ZERO,
179
+ oldestHistoricBlock: BlockNumber.ZERO,
179
180
  root: Fr.ZERO,
180
181
  initialRoot: Fr.ZERO,
181
182
  initialSize: 0n,
@@ -204,9 +205,9 @@ export function buildEmptyWorldStateDBStats() {
204
205
 
205
206
  export function buildEmptyWorldStateSummary() {
206
207
  return {
207
- unfinalizedBlockNumber: 0n,
208
- finalizedBlockNumber: 0n,
209
- oldestHistoricalBlock: 0n,
208
+ unfinalizedBlockNumber: BlockNumber.ZERO,
209
+ finalizedBlockNumber: BlockNumber.ZERO,
210
+ oldestHistoricalBlock: BlockNumber.ZERO,
210
211
  treesAreSynched: true,
211
212
  } as WorldStateStatusSummary;
212
213
  }
@@ -220,9 +221,9 @@ export function buildEmptyWorldStateStatusFull() {
220
221
  }
221
222
 
222
223
  export function sanitizeSummary(summary: WorldStateStatusSummary) {
223
- summary.finalizedBlockNumber = BigInt(summary.finalizedBlockNumber);
224
- summary.unfinalizedBlockNumber = BigInt(summary.unfinalizedBlockNumber);
225
- summary.oldestHistoricalBlock = BigInt(summary.oldestHistoricalBlock);
224
+ summary.finalizedBlockNumber = BlockNumber.fromBigInt(BigInt(summary.finalizedBlockNumber));
225
+ summary.unfinalizedBlockNumber = BlockNumber.fromBigInt(BigInt(summary.unfinalizedBlockNumber));
226
+ summary.oldestHistoricalBlock = BlockNumber.fromBigInt(BigInt(summary.oldestHistoricalBlock));
226
227
  return summary;
227
228
  }
228
229
 
@@ -234,11 +235,11 @@ export function sanitizeDBStats(stats: DBStats) {
234
235
 
235
236
  export function sanitizeMeta(meta: TreeMeta) {
236
237
  meta.committedSize = BigInt(meta.committedSize);
237
- meta.finalizedBlockHeight = BigInt(meta.finalizedBlockHeight);
238
+ meta.finalizedBlockHeight = BlockNumber.fromBigInt(BigInt(meta.finalizedBlockHeight));
238
239
  meta.initialSize = BigInt(meta.initialSize);
239
- meta.oldestHistoricBlock = BigInt(meta.oldestHistoricBlock);
240
+ meta.oldestHistoricBlock = BlockNumber.fromBigInt(BigInt(meta.oldestHistoricBlock));
240
241
  meta.size = BigInt(meta.size);
241
- meta.unfinalizedBlockHeight = BigInt(meta.unfinalizedBlockHeight);
242
+ meta.unfinalizedBlockHeight = BlockNumber.fromBigInt(BigInt(meta.unfinalizedBlockHeight));
242
243
  return meta;
243
244
  }
244
245
 
@@ -282,6 +283,16 @@ interface WithForkId {
282
283
  forkId: number;
283
284
  }
284
285
 
286
+ interface CreateCheckpointResponse {
287
+ depth: number;
288
+ }
289
+
290
+ /** Request to commit/revert all checkpoints down to a target depth. The resulting depth after the operation equals the given depth. */
291
+ interface CheckpointDepthRequest extends WithForkId {
292
+ /** The target depth after the operation. All checkpoints above this depth are committed/reverted. */
293
+ depth: number;
294
+ }
295
+
285
296
  interface WithWorldStateRevision {
286
297
  revision: WorldStateRevision;
287
298
  }
@@ -310,7 +321,7 @@ interface WithLeafValues {
310
321
  }
311
322
 
312
323
  interface BlockShiftRequest extends WithCanonicalForkId {
313
- toBlockNumber: bigint;
324
+ toBlockNumber: BlockNumber;
314
325
  }
315
326
 
316
327
  interface WithLeaves {
@@ -409,9 +420,9 @@ interface UpdateArchiveRequest extends WithForkId {
409
420
  }
410
421
 
411
422
  interface SyncBlockRequest extends WithCanonicalForkId {
412
- blockNumber: number;
423
+ blockNumber: BlockNumber;
413
424
  blockStateRef: BlockStateReference;
414
- blockHeaderHash: Fr;
425
+ blockHeaderHash: Buffer;
415
426
  paddedNoteHashes: readonly SerializedLeafValue[];
416
427
  paddedL1ToL2Messages: readonly SerializedLeafValue[];
417
428
  paddedNullifiers: readonly SerializedLeafValue[];
@@ -420,7 +431,7 @@ interface SyncBlockRequest extends WithCanonicalForkId {
420
431
 
421
432
  interface CreateForkRequest extends WithCanonicalForkId {
422
433
  latest: boolean;
423
- blockNumber: number;
434
+ blockNumber: BlockNumber;
424
435
  }
425
436
 
426
437
  interface CreateForkResponse {
@@ -485,8 +496,8 @@ export type WorldStateRequest = {
485
496
  [WorldStateMessageType.CREATE_CHECKPOINT]: WithForkId;
486
497
  [WorldStateMessageType.COMMIT_CHECKPOINT]: WithForkId;
487
498
  [WorldStateMessageType.REVERT_CHECKPOINT]: WithForkId;
488
- [WorldStateMessageType.COMMIT_ALL_CHECKPOINTS]: WithForkId;
489
- [WorldStateMessageType.REVERT_ALL_CHECKPOINTS]: WithForkId;
499
+ [WorldStateMessageType.COMMIT_ALL_CHECKPOINTS]: CheckpointDepthRequest;
500
+ [WorldStateMessageType.REVERT_ALL_CHECKPOINTS]: CheckpointDepthRequest;
490
501
 
491
502
  [WorldStateMessageType.COPY_STORES]: CopyStoresRequest;
492
503
 
@@ -527,7 +538,7 @@ export type WorldStateResponse = {
527
538
 
528
539
  [WorldStateMessageType.GET_STATUS]: WorldStateStatusSummary;
529
540
 
530
- [WorldStateMessageType.CREATE_CHECKPOINT]: void;
541
+ [WorldStateMessageType.CREATE_CHECKPOINT]: CreateCheckpointResponse;
531
542
  [WorldStateMessageType.COMMIT_CHECKPOINT]: void;
532
543
  [WorldStateMessageType.REVERT_CHECKPOINT]: void;
533
544
  [WorldStateMessageType.COMMIT_ALL_CHECKPOINTS]: void;
@@ -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,
@@ -13,8 +14,8 @@ import type {
13
14
  } from '@aztec/stdlib/interfaces/server';
14
15
  import type { SnapshotDataKeys } from '@aztec/stdlib/snapshots';
15
16
  import { MerkleTreeId, NullifierLeaf, type NullifierLeafPreimage, PublicDataTreeLeaf } from '@aztec/stdlib/trees';
16
- import { BlockHeader, PartialStateReference, StateReference } from '@aztec/stdlib/tx';
17
- import { WorldStateRevision } from '@aztec/stdlib/world-state';
17
+ import { BlockHeader, GlobalVariables, PartialStateReference, StateReference } from '@aztec/stdlib/tx';
18
+ import { EMPTY_GENESIS_DATA, type GenesisData, WorldStateRevision } from '@aztec/stdlib/world-state';
18
19
  import { getTelemetryClient } from '@aztec/telemetry-client';
19
20
 
20
21
  import assert from 'assert/strict';
@@ -51,7 +52,8 @@ 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,
56
+ private readonly genesis: GenesisData = EMPTY_GENESIS_DATA,
55
57
  private readonly cleanup = () => Promise.resolve(),
56
58
  ) {}
57
59
 
@@ -59,11 +61,12 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
59
61
  rollupAddress: EthAddress,
60
62
  dataDir: string,
61
63
  wsTreeMapSizes: WorldStateTreeMapSizes,
62
- prefilledPublicData: PublicDataTreeLeaf[] = [],
64
+ genesis: GenesisData = EMPTY_GENESIS_DATA,
63
65
  instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
64
- log = createLogger('world-state:database'),
66
+ bindings?: LoggerBindings,
65
67
  cleanup = () => Promise.resolve(),
66
68
  ): Promise<NativeWorldStateService> {
69
+ const log = createLogger('world-state:database', bindings);
67
70
  const worldStateDirectory = join(dataDir, WORLD_STATE_DIR);
68
71
  // Create a version manager to handle versioning
69
72
  const versionManager = new DatabaseVersionManager({
@@ -71,12 +74,12 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
71
74
  rollupAddress,
72
75
  dataDirectory: worldStateDirectory,
73
76
  onOpen: (dir: string) => {
74
- return Promise.resolve(new NativeWorldState(dir, wsTreeMapSizes, prefilledPublicData, instrumentation));
77
+ return Promise.resolve(new NativeWorldState(dir, wsTreeMapSizes, genesis, instrumentation, bindings));
75
78
  },
76
79
  });
77
80
 
78
81
  const [instance] = await versionManager.open();
79
- const worldState = new this(instance, instrumentation, log, cleanup);
82
+ const worldState = new this(instance, instrumentation, log, genesis, cleanup);
80
83
  try {
81
84
  await worldState.init();
82
85
  } catch (e) {
@@ -90,10 +93,11 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
90
93
  static async tmp(
91
94
  rollupAddress = EthAddress.ZERO,
92
95
  cleanupTmpDir = true,
93
- prefilledPublicData: PublicDataTreeLeaf[] = [],
96
+ genesis: GenesisData = EMPTY_GENESIS_DATA,
94
97
  instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
98
+ bindings?: LoggerBindings,
95
99
  ): Promise<NativeWorldStateService> {
96
- const log = createLogger('world-state:database');
100
+ const log = createLogger('world-state:database', bindings);
97
101
  const dataDir = await mkdtemp(join(tmpdir(), 'aztec-world-state-'));
98
102
  const dbMapSizeKb = 10 * 1024 * 1024;
99
103
  const worldStateTreeMapSizes: WorldStateTreeMapSizes = {
@@ -115,7 +119,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
115
119
  }
116
120
  };
117
121
 
118
- return this.new(rollupAddress, dataDir, worldStateTreeMapSizes, prefilledPublicData, instrumentation, log, cleanup);
122
+ return this.new(rollupAddress, dataDir, worldStateTreeMapSizes, genesis, instrumentation, bindings, cleanup);
119
123
  }
120
124
 
121
125
  protected async init() {
@@ -150,7 +154,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
150
154
  return new MerkleTreesFacade(this.instance, this.initialHeader!, WorldStateRevision.empty());
151
155
  }
152
156
 
153
- public getSnapshot(blockNumber: number): MerkleTreeReadOperations {
157
+ public getSnapshot(blockNumber: BlockNumber): MerkleTreeReadOperations {
154
158
  return new MerkleTreesFacade(
155
159
  this.instance,
156
160
  this.initialHeader!,
@@ -158,16 +162,24 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
158
162
  );
159
163
  }
160
164
 
161
- public async fork(blockNumber?: number): Promise<MerkleTreeWriteOperations> {
165
+ public async fork(
166
+ blockNumber?: BlockNumber,
167
+ opts: { closeDelayMs?: number } = {},
168
+ ): Promise<MerkleTreeWriteOperations> {
162
169
  const resp = await this.instance.call(WorldStateMessageType.CREATE_FORK, {
163
170
  latest: blockNumber === undefined,
164
- blockNumber: blockNumber ?? 0,
171
+ blockNumber: blockNumber ?? BlockNumber.ZERO,
165
172
  canonical: true,
166
173
  });
167
174
  return new MerkleTreesForkFacade(
168
175
  this.instance,
169
176
  this.initialHeader!,
170
- new WorldStateRevision(/*forkId=*/ resp.forkId, /* blockNumber=*/ 0, /* includeUncommitted=*/ true),
177
+ new WorldStateRevision(
178
+ /*forkId=*/ resp.forkId,
179
+ /* blockNumber=*/ BlockNumber.ZERO,
180
+ /* includeUncommitted=*/ true,
181
+ ),
182
+ opts,
171
183
  );
172
184
  }
173
185
 
@@ -175,21 +187,24 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
175
187
  return this.initialHeader!;
176
188
  }
177
189
 
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
- );
190
+ public async handleL2BlockAndMessages(l2Block: L2Block, l1ToL2Messages: Fr[]): Promise<WorldStateStatusFull> {
191
+ const isFirstBlock = l2Block.indexWithinCheckpoint === 0;
192
+ if (!isFirstBlock && l1ToL2Messages.length > 0) {
193
+ throw new Error(
194
+ `L1 to L2 messages must be empty for non-first blocks, but got ${l1ToL2Messages.length} messages for block ${l2Block.number}.`,
195
+ );
196
+ }
197
+
198
+ // We have to pad the given l1 to l2 messages, and the note hashes and nullifiers within tx effects, because that's
199
+ // how the trees are built by circuits.
189
200
  const paddedL1ToL2Messages = isFirstBlock
190
201
  ? padArrayEnd<Fr, number>(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP)
191
202
  : [];
192
203
 
204
+ const paddedNoteHashes = l2Block.body.txEffects.flatMap(txEffect =>
205
+ padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
206
+ );
207
+
193
208
  const paddedNullifiers = l2Block.body.txEffects
194
209
  .flatMap(txEffect => padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX))
195
210
  .map(nullifier => new NullifierLeaf(nullifier));
@@ -208,7 +223,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
208
223
  WorldStateMessageType.SYNC_BLOCK,
209
224
  {
210
225
  blockNumber: l2Block.number,
211
- blockHeaderHash: await l2Block.hash(),
226
+ blockHeaderHash: (await l2Block.hash()).toBuffer(),
212
227
  paddedL1ToL2Messages: paddedL1ToL2Messages.map(serializeLeaf),
213
228
  paddedNoteHashes: paddedNoteHashes.map(serializeLeaf),
214
229
  paddedNullifiers: paddedNullifiers.map(serializeLeaf),
@@ -232,7 +247,10 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
232
247
 
233
248
  private async buildInitialHeader(): Promise<BlockHeader> {
234
249
  const state = await this.getInitialStateReference();
235
- return BlockHeader.empty({ state });
250
+ return BlockHeader.empty({
251
+ state,
252
+ globalVariables: GlobalVariables.empty({ timestamp: this.genesis.genesisTimestamp }),
253
+ });
236
254
  }
237
255
 
238
256
  private sanitizeAndCacheSummaryFromFull(response: WorldStateStatusFull) {
@@ -256,7 +274,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
256
274
  * @param toBlockNumber The block number that is now the tip of the finalized chain
257
275
  * @returns The new WorldStateStatus
258
276
  */
259
- public async setFinalized(toBlockNumber: bigint) {
277
+ public async setFinalized(toBlockNumber: BlockNumber) {
260
278
  try {
261
279
  await this.instance.call(
262
280
  WorldStateMessageType.FINALIZE_BLOCKS,
@@ -279,7 +297,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
279
297
  * @param toBlockNumber The block number of the new oldest historical block
280
298
  * @returns The new WorldStateStatus
281
299
  */
282
- public async removeHistoricalBlocks(toBlockNumber: bigint) {
300
+ public async removeHistoricalBlocks(toBlockNumber: BlockNumber) {
283
301
  try {
284
302
  return await this.instance.call(
285
303
  WorldStateMessageType.REMOVE_HISTORICAL_BLOCKS,
@@ -301,7 +319,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
301
319
  * @param toBlockNumber The block number of the new tip of the pending chain,
302
320
  * @returns The new WorldStateStatus
303
321
  */
304
- public async unwindBlocks(toBlockNumber: bigint) {
322
+ public async unwindBlocks(toBlockNumber: BlockNumber) {
305
323
  try {
306
324
  return await this.instance.call(
307
325
  WorldStateMessageType.UNWIND_BLOCKS,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ARCHIVE_HEIGHT,
3
- GeneratorIndex,
3
+ DomainSeparator,
4
4
  L1_TO_L2_MSG_TREE_HEIGHT,
5
5
  MAX_NULLIFIERS_PER_TX,
6
6
  MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
@@ -8,10 +8,10 @@ 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
- import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
14
+ import { EMPTY_GENESIS_DATA, type GenesisData } from '@aztec/stdlib/world-state';
15
15
 
16
16
  import assert from 'assert';
17
17
  import { cpus } from 'os';
@@ -55,9 +55,10 @@ export class NativeWorldState implements NativeWorldStateInstance {
55
55
  constructor(
56
56
  private readonly dataDir: string,
57
57
  private readonly wsTreeMapSizes: WorldStateTreeMapSizes,
58
- private readonly prefilledPublicData: PublicDataTreeLeaf[] = [],
58
+ private readonly genesis: GenesisData = EMPTY_GENESIS_DATA,
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(
@@ -65,7 +66,10 @@ export class NativeWorldState implements NativeWorldStateInstance {
65
66
  wsTreeMapSizes,
66
67
  )} and ${threads} threads.`,
67
68
  );
68
- const prefilledPublicDataBufferArray = prefilledPublicData.map(d => [d.slot.toBuffer(), d.value.toBuffer()]);
69
+ const prefilledPublicDataBufferArray = genesis.prefilledPublicData.map(d => [
70
+ d.slot.toBuffer(),
71
+ d.value.toBuffer(),
72
+ ]);
69
73
  const ws = new BaseNativeWorldState(
70
74
  dataDir,
71
75
  {
@@ -80,7 +84,8 @@ export class NativeWorldState implements NativeWorldStateInstance {
80
84
  [MerkleTreeId.PUBLIC_DATA_TREE]: 2 * MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
81
85
  },
82
86
  prefilledPublicDataBufferArray,
83
- GeneratorIndex.BLOCK_HASH,
87
+ DomainSeparator.BLOCK_HEADER_HASH,
88
+ Number(genesis.genesisTimestamp),
84
89
  {
85
90
  [MerkleTreeId.NULLIFIER_TREE]: wsTreeMapSizes.nullifierTreeMapSizeKb,
86
91
  [MerkleTreeId.NOTE_HASH_TREE]: wsTreeMapSizes.noteHashTreeMapSizeKb,
@@ -103,8 +108,9 @@ export class NativeWorldState implements NativeWorldStateInstance {
103
108
  return new NativeWorldState(
104
109
  this.dataDir,
105
110
  this.wsTreeMapSizes,
106
- this.prefilledPublicData,
111
+ this.genesis,
107
112
  this.instrumentation,
113
+ this.log.getBindings(),
108
114
  this.log,
109
115
  );
110
116
  }
@@ -96,7 +96,7 @@ export class WorldStateOpsQueue {
96
96
  // then send the request immediately
97
97
  // If a mutating request is in flight then we must wait
98
98
  // If a mutating request is not in flight but something is queued then it must be a mutating request
99
- if (this.inFlightMutatingCount == 0 && this.requests.length == 0) {
99
+ if (this.inFlightMutatingCount === 0 && this.requests.length === 0) {
100
100
  this.sendEnqueuedRequest(op);
101
101
  } else {
102
102
  this.requests.push(op);
@@ -122,7 +122,7 @@ export class WorldStateOpsQueue {
122
122
  --this.inFlightCount;
123
123
 
124
124
  // If there are still requests in flight then do nothing further
125
- if (this.inFlightCount != 0) {
125
+ if (this.inFlightCount !== 0) {
126
126
  return;
127
127
  }
128
128
 
@@ -134,7 +134,7 @@ export class WorldStateOpsQueue {
134
134
  while (this.requests.length > 0) {
135
135
  const next = this.requests[0];
136
136
  if (next.mutating) {
137
- if (this.inFlightCount == 0) {
137
+ if (this.inFlightCount === 0) {
138
138
  // send the mutating request
139
139
  this.requests.shift();
140
140
  this.sendEnqueuedRequest(next);
@@ -149,7 +149,7 @@ export class WorldStateOpsQueue {
149
149
  }
150
150
 
151
151
  // If the queue is empty, there is nothing in flight and we have been told to stop, then resolve the stop promise
152
- if (this.inFlightCount == 0 && this.stopResolve !== undefined) {
152
+ if (this.inFlightCount === 0 && this.stopResolve !== undefined) {
153
153
  this.stopResolve();
154
154
  }
155
155
  }
@@ -182,7 +182,7 @@ export class WorldStateOpsQueue {
182
182
  });
183
183
 
184
184
  // If no outstanding requests then immediately resolve the promise
185
- if (this.requests.length == 0 && this.inFlightCount == 0 && this.stopResolve !== undefined) {
185
+ if (this.requests.length === 0 && this.inFlightCount === 0 && this.stopResolve !== undefined) {
186
186
  this.stopResolve();
187
187
  }
188
188
  return this.stopPromise;
@@ -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
 
@@ -37,8 +29,8 @@ export interface WorldStateConfig {
37
29
  /** Optional directory for the world state DB, if unspecified will default to the general data directory */
38
30
  worldStateDataDirectory?: string;
39
31
 
40
- /** The number of historic blocks to maintain */
41
- worldStateBlockHistory: number;
32
+ /** The number of historic checkpoints worth of blocks to maintain */
33
+ worldStateCheckpointHistory: number;
42
34
  }
43
35
 
44
36
  export const worldStateConfigMappings: ConfigMappingsType<WorldStateConfig> = {
@@ -48,48 +40,43 @@ 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
- parseEnv: (val: string | undefined) => (val ? +val : undefined),
45
+ parseEnv: (val: string) => +val,
59
46
  description: 'Size of the batch for each get-blocks request from the synchronizer to the archiver.',
60
47
  },
61
48
  worldStateDbMapSizeKb: {
62
49
  env: 'WS_DB_MAP_SIZE_KB',
63
- parseEnv: (val: string | undefined) => (val ? +val : undefined),
50
+ parseEnv: (val: string) => +val,
64
51
  description: 'The maximum possible size of the world state DB in KB. Overwrites the general dataStoreMapSizeKb.',
65
52
  },
66
53
  archiveTreeMapSizeKb: {
67
54
  env: 'ARCHIVE_TREE_MAP_SIZE_KB',
68
- parseEnv: (val: string | undefined) => (val ? +val : undefined),
55
+ parseEnv: (val: string) => +val,
69
56
  description:
70
57
  'The maximum possible size of the world state archive tree in KB. Overwrites the general worldStateDbMapSizeKb.',
71
58
  },
72
59
  nullifierTreeMapSizeKb: {
73
60
  env: 'NULLIFIER_TREE_MAP_SIZE_KB',
74
- parseEnv: (val: string | undefined) => (val ? +val : undefined),
61
+ parseEnv: (val: string) => +val,
75
62
  description:
76
63
  'The maximum possible size of the world state nullifier tree in KB. Overwrites the general worldStateDbMapSizeKb.',
77
64
  },
78
65
  noteHashTreeMapSizeKb: {
79
66
  env: 'NOTE_HASH_TREE_MAP_SIZE_KB',
80
- parseEnv: (val: string | undefined) => (val ? +val : undefined),
67
+ parseEnv: (val: string) => +val,
81
68
  description:
82
69
  'The maximum possible size of the world state note hash tree in KB. Overwrites the general worldStateDbMapSizeKb.',
83
70
  },
84
71
  messageTreeMapSizeKb: {
85
72
  env: 'MESSAGE_TREE_MAP_SIZE_KB',
86
- parseEnv: (val: string | undefined) => (val ? +val : undefined),
73
+ parseEnv: (val: string) => +val,
87
74
  description:
88
75
  'The maximum possible size of the world state message tree in KB. Overwrites the general worldStateDbMapSizeKb.',
89
76
  },
90
77
  publicDataTreeMapSizeKb: {
91
78
  env: 'PUBLIC_DATA_TREE_MAP_SIZE_KB',
92
- parseEnv: (val: string | undefined) => (val ? +val : undefined),
79
+ parseEnv: (val: string) => +val,
93
80
  description:
94
81
  'The maximum possible size of the world state public data tree in KB. Overwrites the general worldStateDbMapSizeKb.',
95
82
  },
@@ -97,9 +84,11 @@ export const worldStateConfigMappings: ConfigMappingsType<WorldStateConfig> = {
97
84
  env: 'WS_DATA_DIRECTORY',
98
85
  description: 'Optional directory for the world state database',
99
86
  },
100
- worldStateBlockHistory: {
101
- env: 'WS_NUM_HISTORIC_BLOCKS',
102
- description: 'The number of historic blocks to maintain. Values less than 1 mean all history is maintained',
87
+ worldStateCheckpointHistory: {
88
+ env: 'WS_NUM_HISTORIC_CHECKPOINTS',
89
+ description:
90
+ 'The number of historic checkpoints worth of blocks to maintain. Values less than 1 mean all history is maintained',
91
+ fallback: ['WS_NUM_HISTORIC_BLOCKS'],
103
92
  ...numberConfigHelper(64),
104
93
  },
105
94
  };
@@ -1,7 +1,8 @@
1
- import type { DataStoreConfig } from '@aztec/kv-store/config';
1
+ import type { LoggerBindings } from '@aztec/foundation/log';
2
2
  import type { L2BlockSource } from '@aztec/stdlib/block';
3
+ import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
3
4
  import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
4
- import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
5
+ import { EMPTY_GENESIS_DATA, type GenesisData } from '@aztec/stdlib/world-state';
5
6
  import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
6
7
 
7
8
  import { WorldStateInstrumentation } from '../instrumentation/instrumentation.js';
@@ -20,11 +21,12 @@ export interface WorldStateTreeMapSizes {
20
21
  export async function createWorldStateSynchronizer(
21
22
  config: WorldStateConfig & DataStoreConfig,
22
23
  l2BlockSource: L2BlockSource & L1ToL2MessageSource,
23
- prefilledPublicData: PublicDataTreeLeaf[] = [],
24
+ genesis: GenesisData = EMPTY_GENESIS_DATA,
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, genesis, instrumentation, bindings);
28
30
  return new ServerWorldStateSynchronizer(merkleTrees, l2BlockSource, config, instrumentation);
29
31
  }
30
32
 
@@ -40,8 +42,9 @@ export async function createWorldState(
40
42
  | 'publicDataTreeMapSizeKb'
41
43
  > &
42
44
  Pick<DataStoreConfig, 'dataDirectory' | 'dataStoreMapSizeKb' | 'l1Contracts'>,
43
- prefilledPublicData: PublicDataTreeLeaf[] = [],
45
+ genesis: GenesisData = EMPTY_GENESIS_DATA,
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;
@@ -63,13 +66,16 @@ export async function createWorldState(
63
66
  config.l1Contracts.rollupAddress,
64
67
  dataDirectory,
65
68
  wsTreeMapSizes,
66
- prefilledPublicData,
69
+ genesis,
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
- prefilledPublicData,
76
+ genesis,
77
+ instrumentation,
78
+ bindings,
73
79
  );
74
80
 
75
81
  return merkleTrees;