@aztec/world-state 4.0.0-nightly.20250907 → 4.0.0-nightly.20260108

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 (53) hide show
  1. package/dest/index.d.ts +1 -1
  2. package/dest/instrumentation/instrumentation.d.ts +1 -1
  3. package/dest/instrumentation/instrumentation.d.ts.map +1 -1
  4. package/dest/native/bench_metrics.d.ts +1 -1
  5. package/dest/native/bench_metrics.d.ts.map +1 -1
  6. package/dest/native/fork_checkpoint.d.ts +1 -1
  7. package/dest/native/fork_checkpoint.d.ts.map +1 -1
  8. package/dest/native/index.d.ts +1 -1
  9. package/dest/native/merkle_trees_facade.d.ts +13 -5
  10. package/dest/native/merkle_trees_facade.d.ts.map +1 -1
  11. package/dest/native/merkle_trees_facade.js +29 -4
  12. package/dest/native/message.d.ts +13 -17
  13. package/dest/native/message.d.ts.map +1 -1
  14. package/dest/native/message.js +14 -20
  15. package/dest/native/native_world_state.d.ts +12 -9
  16. package/dest/native/native_world_state.d.ts.map +1 -1
  17. package/dest/native/native_world_state.js +17 -10
  18. package/dest/native/native_world_state_instance.d.ts +10 -1
  19. package/dest/native/native_world_state_instance.d.ts.map +1 -1
  20. package/dest/native/native_world_state_instance.js +21 -0
  21. package/dest/native/world_state_ops_queue.d.ts +1 -1
  22. package/dest/native/world_state_ops_queue.d.ts.map +1 -1
  23. package/dest/synchronizer/config.d.ts +2 -2
  24. package/dest/synchronizer/config.js +1 -1
  25. package/dest/synchronizer/errors.d.ts +1 -1
  26. package/dest/synchronizer/errors.d.ts.map +1 -1
  27. package/dest/synchronizer/factory.d.ts +2 -2
  28. package/dest/synchronizer/factory.js +6 -6
  29. package/dest/synchronizer/index.d.ts +1 -1
  30. package/dest/synchronizer/server_world_state_synchronizer.d.ts +10 -26
  31. package/dest/synchronizer/server_world_state_synchronizer.d.ts.map +1 -1
  32. package/dest/synchronizer/server_world_state_synchronizer.js +37 -53
  33. package/dest/test/index.d.ts +1 -1
  34. package/dest/test/utils.d.ts +16 -9
  35. package/dest/test/utils.d.ts.map +1 -1
  36. package/dest/test/utils.js +56 -52
  37. package/dest/testing.d.ts +2 -2
  38. package/dest/testing.d.ts.map +1 -1
  39. package/dest/testing.js +1 -1
  40. package/dest/world-state-db/index.d.ts +1 -1
  41. package/dest/world-state-db/merkle_tree_db.d.ts +10 -9
  42. package/dest/world-state-db/merkle_tree_db.d.ts.map +1 -1
  43. package/package.json +13 -12
  44. package/src/native/merkle_trees_facade.ts +34 -5
  45. package/src/native/message.ts +24 -39
  46. package/src/native/native_world_state.ts +44 -16
  47. package/src/native/native_world_state_instance.ts +28 -0
  48. package/src/synchronizer/config.ts +2 -2
  49. package/src/synchronizer/factory.ts +7 -7
  50. package/src/synchronizer/server_world_state_synchronizer.ts +69 -84
  51. package/src/test/utils.ts +89 -94
  52. package/src/testing.ts +1 -1
  53. package/src/world-state-db/merkle_tree_db.ts +13 -8
package/src/test/utils.ts CHANGED
@@ -4,122 +4,100 @@ import {
4
4
  NULLIFIER_SUBTREE_HEIGHT,
5
5
  NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
6
6
  } from '@aztec/constants';
7
+ import { asyncMap } from '@aztec/foundation/async-map';
8
+ import { BlockNumber, type CheckpointNumber } from '@aztec/foundation/branded-types';
7
9
  import { padArrayEnd } from '@aztec/foundation/collection';
8
- import { Fr } from '@aztec/foundation/fields';
9
- import { L2Block } from '@aztec/stdlib/block';
10
+ import { Fr } from '@aztec/foundation/curves/bn254';
11
+ import { L2BlockNew } from '@aztec/stdlib/block';
10
12
  import type {
11
13
  IndexedTreeId,
12
14
  MerkleTreeReadOperations,
13
15
  MerkleTreeWriteOperations,
14
16
  } from '@aztec/stdlib/interfaces/server';
17
+ import { mockCheckpointAndMessages, mockL1ToL2Messages } from '@aztec/stdlib/testing';
15
18
  import { AppendOnlyTreeSnapshot, MerkleTreeId } from '@aztec/stdlib/trees';
19
+ import { BlockHeader } from '@aztec/stdlib/tx';
16
20
 
17
21
  import type { NativeWorldStateService } from '../native/native_world_state.js';
18
22
 
19
- export async function mockBlock(
20
- blockNum: number,
21
- size: number,
22
- fork: MerkleTreeWriteOperations,
23
- maxEffects: number | undefined = undefined,
24
- ) {
25
- const l2Block = await L2Block.random(blockNum, size, maxEffects);
26
- const l1ToL2Messages = Array(16).fill(0).map(Fr.random);
27
-
28
- {
29
- const insertData = async (
30
- treeId: IndexedTreeId,
31
- data: Buffer[][],
32
- subTreeHeight: number,
33
- fork: MerkleTreeWriteOperations,
34
- ) => {
35
- for (const dataBatch of data) {
36
- await fork.batchInsert(treeId, dataBatch, subTreeHeight);
37
- }
38
- };
39
-
40
- const publicDataInsert = insertData(
41
- MerkleTreeId.PUBLIC_DATA_TREE,
42
- l2Block.body.txEffects.map(txEffect => txEffect.publicDataWrites.map(write => write.toBuffer())),
43
- 0,
44
- fork,
45
- );
46
- const nullifierInsert = insertData(
47
- MerkleTreeId.NULLIFIER_TREE,
48
- l2Block.body.txEffects.map(txEffect =>
49
- padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX).map(nullifier => nullifier.toBuffer()),
50
- ),
51
- NULLIFIER_SUBTREE_HEIGHT,
52
- fork,
53
- );
54
- const noteHashesPadded = l2Block.body.txEffects.flatMap(txEffect =>
55
- padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
56
- );
57
-
58
- const l1ToL2MessagesPadded = padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
59
-
60
- const noteHashInsert = fork.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, noteHashesPadded);
61
- const messageInsert = fork.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
62
- await Promise.all([publicDataInsert, nullifierInsert, noteHashInsert, messageInsert]);
63
- }
23
+ export async function updateBlockState(block: L2BlockNew, l1ToL2Messages: Fr[], fork: MerkleTreeWriteOperations) {
24
+ const insertData = async (
25
+ treeId: IndexedTreeId,
26
+ data: Buffer[][],
27
+ subTreeHeight: number,
28
+ fork: MerkleTreeWriteOperations,
29
+ ) => {
30
+ for (const dataBatch of data) {
31
+ await fork.batchInsert(treeId, dataBatch, subTreeHeight);
32
+ }
33
+ };
34
+
35
+ const publicDataInsert = insertData(
36
+ MerkleTreeId.PUBLIC_DATA_TREE,
37
+ block.body.txEffects.map(txEffect => txEffect.publicDataWrites.map(write => write.toBuffer())),
38
+ 0,
39
+ fork,
40
+ );
41
+ const nullifierInsert = insertData(
42
+ MerkleTreeId.NULLIFIER_TREE,
43
+ block.body.txEffects.map(txEffect =>
44
+ padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX).map(nullifier => nullifier.toBuffer()),
45
+ ),
46
+ NULLIFIER_SUBTREE_HEIGHT,
47
+ fork,
48
+ );
49
+ const noteHashesPadded = block.body.txEffects.flatMap(txEffect =>
50
+ padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
51
+ );
52
+
53
+ const l1ToL2MessagesPadded =
54
+ block.indexWithinCheckpoint === 0
55
+ ? padArrayEnd<Fr, number>(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP)
56
+ : l1ToL2Messages;
57
+
58
+ const noteHashInsert = fork.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, noteHashesPadded);
59
+ const messageInsert = fork.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
60
+ await Promise.all([publicDataInsert, nullifierInsert, noteHashInsert, messageInsert]);
64
61
 
65
62
  const state = await fork.getStateReference();
66
- l2Block.header.state = state;
67
- await fork.updateArchive(l2Block.header);
63
+ block.header = BlockHeader.from({ ...block.header, state });
64
+ await fork.updateArchive(block.header);
68
65
 
69
66
  const archiveState = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
70
67
 
71
- l2Block.archive = new AppendOnlyTreeSnapshot(Fr.fromBuffer(archiveState.root), Number(archiveState.size));
68
+ block.archive = new AppendOnlyTreeSnapshot(Fr.fromBuffer(archiveState.root), Number(archiveState.size));
69
+ }
70
+
71
+ export async function mockBlock(
72
+ blockNum: BlockNumber,
73
+ size: number,
74
+ fork: MerkleTreeWriteOperations,
75
+ maxEffects: number | undefined = 1000, // Defaults to the maximum tx effects.
76
+ numL1ToL2Messages: number = NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
77
+ isFirstBlockInCheckpoint: boolean = true,
78
+ ) {
79
+ const block = await L2BlockNew.random(blockNum, {
80
+ indexWithinCheckpoint: isFirstBlockInCheckpoint ? 0 : 1,
81
+ txsPerBlock: size,
82
+ txOptions: { maxEffects },
83
+ });
84
+ const l1ToL2Messages = mockL1ToL2Messages(numL1ToL2Messages);
85
+
86
+ await updateBlockState(block, l1ToL2Messages, fork);
72
87
 
73
88
  return {
74
- block: l2Block,
89
+ block,
75
90
  messages: l1ToL2Messages,
76
91
  };
77
92
  }
78
93
 
79
- export async function mockEmptyBlock(blockNum: number, fork: MerkleTreeWriteOperations) {
80
- const l2Block = L2Block.empty();
94
+ export async function mockEmptyBlock(blockNum: BlockNumber, fork: MerkleTreeWriteOperations) {
95
+ const l2Block = L2BlockNew.empty();
81
96
  const l1ToL2Messages = Array(16).fill(0).map(Fr.zero);
82
97
 
83
98
  l2Block.header.globalVariables.blockNumber = blockNum;
84
99
 
85
- // Sync the append only trees
86
- {
87
- const noteHashesPadded = l2Block.body.txEffects.flatMap(txEffect =>
88
- padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
89
- );
90
- await fork.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, noteHashesPadded);
91
-
92
- const l1ToL2MessagesPadded = padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
93
- await fork.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
94
- }
95
-
96
- // Sync the indexed trees
97
- {
98
- // We insert the public data tree leaves with one batch per tx to avoid updating the same key twice
99
- for (const txEffect of l2Block.body.txEffects) {
100
- await fork.batchInsert(
101
- MerkleTreeId.PUBLIC_DATA_TREE,
102
- txEffect.publicDataWrites.map(write => write.toBuffer()),
103
- 0,
104
- );
105
-
106
- const nullifiersPadded = padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX);
107
-
108
- await fork.batchInsert(
109
- MerkleTreeId.NULLIFIER_TREE,
110
- nullifiersPadded.map(nullifier => nullifier.toBuffer()),
111
- NULLIFIER_SUBTREE_HEIGHT,
112
- );
113
- }
114
- }
115
-
116
- const state = await fork.getStateReference();
117
- l2Block.header.state = state;
118
- await fork.updateArchive(l2Block.header);
119
-
120
- const archiveState = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
121
-
122
- l2Block.archive = new AppendOnlyTreeSnapshot(Fr.fromBuffer(archiveState.root), Number(archiveState.size));
100
+ await updateBlockState(l2Block, l1ToL2Messages, fork);
123
101
 
124
102
  return {
125
103
  block: l2Block,
@@ -127,13 +105,18 @@ export async function mockEmptyBlock(blockNum: number, fork: MerkleTreeWriteOper
127
105
  };
128
106
  }
129
107
 
130
- export async function mockBlocks(from: number, count: number, numTxs: number, worldState: NativeWorldStateService) {
131
- const tempFork = await worldState.fork(from - 1);
108
+ export async function mockBlocks(
109
+ from: BlockNumber,
110
+ count: number,
111
+ numTxs: number,
112
+ worldState: NativeWorldStateService,
113
+ ) {
114
+ const tempFork = await worldState.fork(BlockNumber(from - 1));
132
115
 
133
116
  const blocks = [];
134
117
  const messagesArray = [];
135
118
  for (let blockNumber = from; blockNumber < from + count; blockNumber++) {
136
- const { block, messages } = await mockBlock(blockNumber, numTxs, tempFork);
119
+ const { block, messages } = await mockBlock(BlockNumber(blockNumber), numTxs, tempFork);
137
120
  blocks.push(block);
138
121
  messagesArray.push(messages);
139
122
  }
@@ -143,6 +126,18 @@ export async function mockBlocks(from: number, count: number, numTxs: number, wo
143
126
  return { blocks, messages: messagesArray };
144
127
  }
145
128
 
129
+ export async function mockCheckpoint(
130
+ checkpointNumber: CheckpointNumber,
131
+ fork: MerkleTreeWriteOperations,
132
+ options: Partial<Parameters<typeof mockCheckpointAndMessages>[1]> = {},
133
+ ) {
134
+ const { checkpoint, messages } = await mockCheckpointAndMessages(checkpointNumber, options);
135
+ await asyncMap(checkpoint.blocks, async (block, i) => {
136
+ await updateBlockState(block, i === 0 ? messages : [], fork);
137
+ });
138
+ return { checkpoint, messages };
139
+ }
140
+
146
141
  export async function assertSameState(forkA: MerkleTreeReadOperations, forkB: MerkleTreeReadOperations) {
147
142
  const nativeStateRef = await forkA.getStateReference();
148
143
  const nativeArchive = await forkA.getTreeInfo(MerkleTreeId.ARCHIVE);
package/src/testing.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { GENESIS_ARCHIVE_ROOT } from '@aztec/constants';
2
- import { Fr } from '@aztec/foundation/fields';
2
+ import { Fr } from '@aztec/foundation/curves/bn254';
3
3
  import { computeFeePayerBalanceLeafSlot } from '@aztec/protocol-contracts/fee-juice';
4
4
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
5
5
  import { MerkleTreeId, PublicDataTreeLeaf } from '@aztec/stdlib/trees';
@@ -1,8 +1,13 @@
1
1
  import { MAX_NULLIFIERS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX } from '@aztec/constants';
2
- import type { Fr } from '@aztec/foundation/fields';
2
+ import type { BlockNumber } from '@aztec/foundation/branded-types';
3
+ import type { Fr } from '@aztec/foundation/curves/bn254';
3
4
  import type { IndexedTreeSnapshot, TreeSnapshot } from '@aztec/merkle-tree';
4
- import type { L2Block } from '@aztec/stdlib/block';
5
- import type { ForkMerkleTreeOperations, MerkleTreeReadOperations } from '@aztec/stdlib/interfaces/server';
5
+ import type { L2BlockNew } from '@aztec/stdlib/block';
6
+ import type {
7
+ ForkMerkleTreeOperations,
8
+ MerkleTreeReadOperations,
9
+ ReadonlyWorldStateAccess,
10
+ } from '@aztec/stdlib/interfaces/server';
6
11
  import type { MerkleTreeId } from '@aztec/stdlib/trees';
7
12
 
8
13
  import type { WorldStateStatusFull, WorldStateStatusSummary } from '../native/message.js';
@@ -34,13 +39,13 @@ export type TreeSnapshots = {
34
39
  [MerkleTreeId.ARCHIVE]: TreeSnapshot<Fr>;
35
40
  };
36
41
 
37
- export interface MerkleTreeAdminDatabase extends ForkMerkleTreeOperations {
42
+ export interface MerkleTreeAdminDatabase extends ForkMerkleTreeOperations, ReadonlyWorldStateAccess {
38
43
  /**
39
44
  * Handles a single L2 block (i.e. Inserts the new note hashes into the merkle tree).
40
45
  * @param block - The L2 block to handle.
41
46
  * @param l1ToL2Messages - The L1 to L2 messages for the block.
42
47
  */
43
- handleL2BlockAndMessages(block: L2Block, l1ToL2Messages: Fr[]): Promise<WorldStateStatusFull>;
48
+ handleL2BlockAndMessages(block: L2BlockNew, l1ToL2Messages: Fr[]): Promise<WorldStateStatusFull>;
44
49
 
45
50
  /**
46
51
  * Gets a handle that allows reading the latest committed state
@@ -52,21 +57,21 @@ export interface MerkleTreeAdminDatabase extends ForkMerkleTreeOperations {
52
57
  * @param toBlockNumber The block number of the new oldest historical block
53
58
  * @returns The new WorldStateStatus
54
59
  */
55
- removeHistoricalBlocks(toBlockNumber: bigint): Promise<WorldStateStatusFull>;
60
+ removeHistoricalBlocks(toBlockNumber: BlockNumber): Promise<WorldStateStatusFull>;
56
61
 
57
62
  /**
58
63
  * Removes all pending blocks down to but not including the given block number
59
64
  * @param toBlockNumber The block number of the new tip of the pending chain,
60
65
  * @returns The new WorldStateStatus
61
66
  */
62
- unwindBlocks(toBlockNumber: bigint): Promise<WorldStateStatusFull>;
67
+ unwindBlocks(toBlockNumber: BlockNumber): Promise<WorldStateStatusFull>;
63
68
 
64
69
  /**
65
70
  * Advances the finalized block number to be the number provided
66
71
  * @param toBlockNumber The block number that is now the tip of the finalized chain
67
72
  * @returns The new WorldStateStatus
68
73
  */
69
- setFinalized(toBlockNumber: bigint): Promise<WorldStateStatusSummary>;
74
+ setFinalized(toBlockNumber: BlockNumber): Promise<WorldStateStatusSummary>;
70
75
 
71
76
  /**
72
77
  * Gets the current status summary of the database.