@aztec/world-state 0.1.0-alpha11

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 (45) hide show
  1. package/.eslintrc.cjs +1 -0
  2. package/.tsbuildinfo +1 -0
  3. package/README.md +40 -0
  4. package/dest/index.d.ts +4 -0
  5. package/dest/index.d.ts.map +1 -0
  6. package/dest/index.js +4 -0
  7. package/dest/merkle-tree/merkle_tree_operations_facade.d.ts +117 -0
  8. package/dest/merkle-tree/merkle_tree_operations_facade.d.ts.map +1 -0
  9. package/dest/merkle-tree/merkle_tree_operations_facade.js +133 -0
  10. package/dest/synchroniser/config.d.ts +19 -0
  11. package/dest/synchroniser/config.d.ts.map +1 -0
  12. package/dest/synchroniser/config.js +13 -0
  13. package/dest/synchroniser/index.d.ts +3 -0
  14. package/dest/synchroniser/index.d.ts.map +1 -0
  15. package/dest/synchroniser/index.js +3 -0
  16. package/dest/synchroniser/server_world_state_synchroniser.d.ts +62 -0
  17. package/dest/synchroniser/server_world_state_synchroniser.d.ts.map +1 -0
  18. package/dest/synchroniser/server_world_state_synchroniser.js +134 -0
  19. package/dest/synchroniser/server_world_state_synchroniser.test.d.ts +2 -0
  20. package/dest/synchroniser/server_world_state_synchroniser.test.d.ts.map +1 -0
  21. package/dest/synchroniser/server_world_state_synchroniser.test.js +215 -0
  22. package/dest/synchroniser/world_state_synchroniser.d.ts +34 -0
  23. package/dest/synchroniser/world_state_synchroniser.d.ts.map +1 -0
  24. package/dest/synchroniser/world_state_synchroniser.js +11 -0
  25. package/dest/utils.d.ts +12 -0
  26. package/dest/utils.d.ts.map +1 -0
  27. package/dest/utils.js +14 -0
  28. package/dest/world-state-db/index.d.ts +165 -0
  29. package/dest/world-state-db/index.d.ts.map +1 -0
  30. package/dest/world-state-db/index.js +21 -0
  31. package/dest/world-state-db/merkle_trees.d.ts +200 -0
  32. package/dest/world-state-db/merkle_trees.d.ts.map +1 -0
  33. package/dest/world-state-db/merkle_trees.js +373 -0
  34. package/package.json +15 -0
  35. package/src/index.ts +3 -0
  36. package/src/merkle-tree/merkle_tree_operations_facade.ts +164 -0
  37. package/src/synchroniser/config.ts +27 -0
  38. package/src/synchroniser/index.ts +2 -0
  39. package/src/synchroniser/server_world_state_synchroniser.test.ts +281 -0
  40. package/src/synchroniser/server_world_state_synchroniser.ts +151 -0
  41. package/src/synchroniser/world_state_synchroniser.ts +36 -0
  42. package/src/utils.ts +24 -0
  43. package/src/world-state-db/index.ts +215 -0
  44. package/src/world-state-db/merkle_trees.ts +547 -0
  45. package/tsconfig.json +23 -0
@@ -0,0 +1,62 @@
1
+ import { L2BlockSource } from '@aztec/types';
2
+ import { MerkleTreeDb, MerkleTreeOperations } from '../index.js';
3
+ import { WorldStateStatus, WorldStateSynchroniser } from './world_state_synchroniser.js';
4
+ /**
5
+ * Synchronises the world state with the L2 blocks from a L2BlockSource.
6
+ * The synchroniser will download the L2 blocks from the L2BlockSource and insert the new commitments into the merkle
7
+ * tree.
8
+ */
9
+ export declare class ServerWorldStateSynchroniser implements WorldStateSynchroniser {
10
+ private merkleTreeDb;
11
+ private l2BlockSource;
12
+ private log;
13
+ private currentL2BlockNum;
14
+ private latestBlockNumberAtStart;
15
+ private l2BlockDownloader;
16
+ private syncPromise;
17
+ private syncResolve?;
18
+ private stopping;
19
+ private runningPromise;
20
+ private currentState;
21
+ constructor(merkleTreeDb: MerkleTreeDb, l2BlockSource: L2BlockSource, log?: import("@aztec/foundation/log").DebugLogger);
22
+ /**
23
+ * Returns an instance of MerkleTreeOperations that will include uncommitted data.
24
+ * @returns An instance of MerkleTreeOperations that will include uncommitted data.
25
+ */
26
+ getLatest(): MerkleTreeOperations;
27
+ /**
28
+ * Returns an instance of MerkleTreeOperations that will not include uncommitted data.
29
+ * @returns An instance of MerkleTreeOperations that will not include uncommitted data.
30
+ */
31
+ getCommitted(): MerkleTreeOperations;
32
+ /**
33
+ * Starts the synchroniser.
34
+ * @returns A promise that resolves once the initial sync is completed.
35
+ */
36
+ start(): Promise<void>;
37
+ /**
38
+ * Stops the synchroniser.
39
+ */
40
+ stop(): Promise<void>;
41
+ /**
42
+ * Returns the current status of the synchroniser.
43
+ * @returns The current status of the synchroniser.
44
+ */
45
+ status(): Promise<WorldStateStatus>;
46
+ /**
47
+ * Handles a list of L2 blocks (i.e. Inserts the new commitments into the merkle tree).
48
+ * @param l2Blocks - The L2 blocks to handle.
49
+ */
50
+ private handleL2Blocks;
51
+ /**
52
+ * Handles a single L2 block (i.e. Inserts the new commitments into the merkle tree).
53
+ * @param l2Block - The L2 block to handle.
54
+ */
55
+ private handleL2Block;
56
+ /**
57
+ * Method to set the value of the current state.
58
+ * @param newState - New state value.
59
+ */
60
+ private setCurrentState;
61
+ }
62
+ //# sourceMappingURL=server_world_state_synchroniser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server_world_state_synchroniser.d.ts","sourceRoot":"","sources":["../../src/synchroniser/server_world_state_synchroniser.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,aAAa,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,EAA0B,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAIjH;;;;GAIG;AACH,qBAAa,4BAA6B,YAAW,sBAAsB;IAWvE,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,GAAG;IAZb,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,wBAAwB,CAAK;IACrC,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,WAAW,CAAoC;IACvD,OAAO,CAAC,WAAW,CAAC,CAAyB;IAC7C,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,cAAc,CAAoC;IAC1D,OAAO,CAAC,YAAY,CAAuD;gBAGjE,YAAY,EAAE,YAAY,EAC1B,aAAa,EAAE,aAAa,EAC5B,GAAG,8CAAyC;IAMtD;;;OAGG;IACI,SAAS,IAAI,oBAAoB;IAIxC;;;OAGG;IACI,YAAY,IAAI,oBAAoB;IAI3C;;;OAGG;IACU,KAAK;IAwClB;;OAEG;IACU,IAAI;IAQjB;;;OAGG;IACI,MAAM,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAQ1C;;;OAGG;YACW,cAAc;IAM5B;;;OAGG;YACW,aAAa;IAc3B;;;OAGG;IACH,OAAO,CAAC,eAAe;CAIxB"}
@@ -0,0 +1,134 @@
1
+ import { L2BlockDownloader } from '@aztec/types';
2
+ import { MerkleTreeOperationsFacade } from '../merkle-tree/merkle_tree_operations_facade.js';
3
+ import { WorldStateRunningState } from './world_state_synchroniser.js';
4
+ import { getConfigEnvVars } from './config.js';
5
+ import { createDebugLogger } from '@aztec/foundation/log';
6
+ /**
7
+ * Synchronises the world state with the L2 blocks from a L2BlockSource.
8
+ * The synchroniser will download the L2 blocks from the L2BlockSource and insert the new commitments into the merkle
9
+ * tree.
10
+ */
11
+ export class ServerWorldStateSynchroniser {
12
+ constructor(merkleTreeDb, l2BlockSource, log = createDebugLogger('aztec:world_state')) {
13
+ this.merkleTreeDb = merkleTreeDb;
14
+ this.l2BlockSource = l2BlockSource;
15
+ this.log = log;
16
+ this.currentL2BlockNum = 0;
17
+ this.latestBlockNumberAtStart = 0;
18
+ this.syncPromise = Promise.resolve();
19
+ this.syncResolve = undefined;
20
+ this.stopping = false;
21
+ this.runningPromise = Promise.resolve();
22
+ this.currentState = WorldStateRunningState.IDLE;
23
+ const config = getConfigEnvVars();
24
+ this.l2BlockDownloader = new L2BlockDownloader(l2BlockSource, config.l2QueueSize, config.checkInterval);
25
+ }
26
+ /**
27
+ * Returns an instance of MerkleTreeOperations that will include uncommitted data.
28
+ * @returns An instance of MerkleTreeOperations that will include uncommitted data.
29
+ */
30
+ getLatest() {
31
+ return new MerkleTreeOperationsFacade(this.merkleTreeDb, true);
32
+ }
33
+ /**
34
+ * Returns an instance of MerkleTreeOperations that will not include uncommitted data.
35
+ * @returns An instance of MerkleTreeOperations that will not include uncommitted data.
36
+ */
37
+ getCommitted() {
38
+ return new MerkleTreeOperationsFacade(this.merkleTreeDb, false);
39
+ }
40
+ /**
41
+ * Starts the synchroniser.
42
+ * @returns A promise that resolves once the initial sync is completed.
43
+ */
44
+ async start() {
45
+ if (this.currentState === WorldStateRunningState.STOPPED) {
46
+ throw new Error('Synchroniser already stopped');
47
+ }
48
+ if (this.currentState !== WorldStateRunningState.IDLE) {
49
+ return this.syncPromise;
50
+ }
51
+ // get the current latest block number
52
+ this.latestBlockNumberAtStart = await this.l2BlockSource.getBlockHeight();
53
+ const blockToDownloadFrom = this.currentL2BlockNum + 1;
54
+ // if there are blocks to be retrieved, go to a synching state
55
+ if (blockToDownloadFrom <= this.latestBlockNumberAtStart) {
56
+ this.setCurrentState(WorldStateRunningState.SYNCHING);
57
+ this.syncPromise = new Promise(resolve => {
58
+ this.syncResolve = resolve;
59
+ });
60
+ this.log(`Starting sync from ${blockToDownloadFrom}, latest block ${this.latestBlockNumberAtStart}`);
61
+ }
62
+ else {
63
+ // if no blocks to be retrieved, go straight to running
64
+ this.setCurrentState(WorldStateRunningState.RUNNING);
65
+ this.syncPromise = Promise.resolve();
66
+ this.log(`Next block ${blockToDownloadFrom} already beyond latest block at ${this.latestBlockNumberAtStart}`);
67
+ }
68
+ // start looking for further blocks
69
+ const blockProcess = async () => {
70
+ while (!this.stopping) {
71
+ const blocks = await this.l2BlockDownloader.getL2Blocks();
72
+ await this.handleL2Blocks(blocks);
73
+ }
74
+ };
75
+ this.runningPromise = blockProcess();
76
+ this.l2BlockDownloader.start(blockToDownloadFrom);
77
+ this.log(`Started block downloader from block ${blockToDownloadFrom}`);
78
+ return this.syncPromise;
79
+ }
80
+ /**
81
+ * Stops the synchroniser.
82
+ */
83
+ async stop() {
84
+ this.log('Stopping world state...');
85
+ this.stopping = true;
86
+ await this.l2BlockDownloader.stop();
87
+ await this.runningPromise;
88
+ this.setCurrentState(WorldStateRunningState.STOPPED);
89
+ }
90
+ /**
91
+ * Returns the current status of the synchroniser.
92
+ * @returns The current status of the synchroniser.
93
+ */
94
+ status() {
95
+ const status = {
96
+ syncedToL2Block: this.currentL2BlockNum,
97
+ state: this.currentState,
98
+ };
99
+ return Promise.resolve(status);
100
+ }
101
+ /**
102
+ * Handles a list of L2 blocks (i.e. Inserts the new commitments into the merkle tree).
103
+ * @param l2Blocks - The L2 blocks to handle.
104
+ */
105
+ async handleL2Blocks(l2Blocks) {
106
+ for (const l2Block of l2Blocks) {
107
+ await this.handleL2Block(l2Block);
108
+ }
109
+ }
110
+ /**
111
+ * Handles a single L2 block (i.e. Inserts the new commitments into the merkle tree).
112
+ * @param l2Block - The L2 block to handle.
113
+ */
114
+ async handleL2Block(l2Block) {
115
+ await this.merkleTreeDb.handleL2Block(l2Block);
116
+ this.currentL2BlockNum = l2Block.number;
117
+ if (this.currentState === WorldStateRunningState.SYNCHING &&
118
+ this.currentL2BlockNum >= this.latestBlockNumberAtStart) {
119
+ this.setCurrentState(WorldStateRunningState.RUNNING);
120
+ if (this.syncResolve !== undefined) {
121
+ this.syncResolve();
122
+ }
123
+ }
124
+ }
125
+ /**
126
+ * Method to set the value of the current state.
127
+ * @param newState - New state value.
128
+ */
129
+ setCurrentState(newState) {
130
+ this.currentState = newState;
131
+ this.log(`Moved to state ${WorldStateRunningState[this.currentState]}`);
132
+ }
133
+ }
134
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyX3dvcmxkX3N0YXRlX3N5bmNocm9uaXNlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zeW5jaHJvbmlzZXIvc2VydmVyX3dvcmxkX3N0YXRlX3N5bmNocm9uaXNlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQVcsaUJBQWlCLEVBQWlCLE1BQU0sY0FBYyxDQUFDO0FBRXpFLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLGlEQUFpRCxDQUFDO0FBQzdGLE9BQU8sRUFBRSxzQkFBc0IsRUFBNEMsTUFBTSwrQkFBK0IsQ0FBQztBQUNqSCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDL0MsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFMUQ7Ozs7R0FJRztBQUNILE1BQU0sT0FBTyw0QkFBNEI7SUFVdkMsWUFDVSxZQUEwQixFQUMxQixhQUE0QixFQUM1QixNQUFNLGlCQUFpQixDQUFDLG1CQUFtQixDQUFDO1FBRjVDLGlCQUFZLEdBQVosWUFBWSxDQUFjO1FBQzFCLGtCQUFhLEdBQWIsYUFBYSxDQUFlO1FBQzVCLFFBQUcsR0FBSCxHQUFHLENBQXlDO1FBWjlDLHNCQUFpQixHQUFHLENBQUMsQ0FBQztRQUN0Qiw2QkFBd0IsR0FBRyxDQUFDLENBQUM7UUFFN0IsZ0JBQVcsR0FBa0IsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQy9DLGdCQUFXLEdBQWdCLFNBQVMsQ0FBQztRQUNyQyxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBQ2pCLG1CQUFjLEdBQWtCLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNsRCxpQkFBWSxHQUEyQixzQkFBc0IsQ0FBQyxJQUFJLENBQUM7UUFPekUsTUFBTSxNQUFNLEdBQUcsZ0JBQWdCLEVBQUUsQ0FBQztRQUNsQyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxpQkFBaUIsQ0FBQyxhQUFhLEVBQUUs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
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=server_world_state_synchroniser.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server_world_state_synchroniser.test.d.ts","sourceRoot":"","sources":["../../src/synchroniser/server_world_state_synchroniser.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,215 @@
1
+ import { AppendOnlyTreeSnapshot, CircuitsWasm, GlobalVariables, KERNEL_NEW_COMMITMENTS_LENGTH, KERNEL_NEW_CONTRACTS_LENGTH, KERNEL_NEW_NULLIFIERS_LENGTH, KERNEL_PUBLIC_DATA_UPDATE_REQUESTS_LENGTH, NEW_L2_TO_L1_MSGS_LENGTH, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, } from '@aztec/circuits.js';
2
+ import { INITIAL_LEAF, Pedersen, SiblingPath } from '@aztec/merkle-tree';
3
+ import { ContractData, L2Block, L2BlockL2Logs, MerkleTreeId, PublicDataWrite } from '@aztec/types';
4
+ import { jest } from '@jest/globals';
5
+ import { ServerWorldStateSynchroniser } from './server_world_state_synchroniser.js';
6
+ import { WorldStateRunningState } from './world_state_synchroniser.js';
7
+ import { Fr } from '@aztec/foundation/fields';
8
+ import { sleep } from '@aztec/foundation/sleep';
9
+ import { createLogger } from '@aztec/foundation/log';
10
+ import times from 'lodash.times';
11
+ const LATEST_BLOCK_NUMBER = 5;
12
+ const getLatestBlockNumber = () => LATEST_BLOCK_NUMBER;
13
+ let nextBlocks = [];
14
+ const consumeNextBlocks = () => {
15
+ const blocks = nextBlocks;
16
+ nextBlocks = [];
17
+ return Promise.resolve(blocks);
18
+ };
19
+ const getMockTreeSnapshot = () => {
20
+ return new AppendOnlyTreeSnapshot(Fr.random(), 16);
21
+ };
22
+ const getMockContractData = () => {
23
+ return ContractData.random();
24
+ };
25
+ const getMockGlobalVariables = () => {
26
+ return GlobalVariables.from({
27
+ chainId: Fr.random(),
28
+ version: Fr.random(),
29
+ blockNumber: Fr.random(),
30
+ timestamp: Fr.random(),
31
+ });
32
+ };
33
+ const getMockL1ToL2MessagesData = () => {
34
+ return new Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).map(() => Fr.random());
35
+ };
36
+ const getMockBlock = (blockNumber, newContractsCommitments) => {
37
+ const newEncryptedLogs = L2BlockL2Logs.random(1, 2, 3);
38
+ const block = L2Block.fromFields({
39
+ number: blockNumber,
40
+ globalVariables: getMockGlobalVariables(),
41
+ startPrivateDataTreeSnapshot: getMockTreeSnapshot(),
42
+ startNullifierTreeSnapshot: getMockTreeSnapshot(),
43
+ startContractTreeSnapshot: getMockTreeSnapshot(),
44
+ startTreeOfHistoricPrivateDataTreeRootsSnapshot: getMockTreeSnapshot(),
45
+ startTreeOfHistoricContractTreeRootsSnapshot: getMockTreeSnapshot(),
46
+ startPublicDataTreeRoot: Fr.random(),
47
+ startL1ToL2MessageTreeSnapshot: getMockTreeSnapshot(),
48
+ startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot: getMockTreeSnapshot(),
49
+ endPrivateDataTreeSnapshot: getMockTreeSnapshot(),
50
+ endNullifierTreeSnapshot: getMockTreeSnapshot(),
51
+ endContractTreeSnapshot: getMockTreeSnapshot(),
52
+ endTreeOfHistoricPrivateDataTreeRootsSnapshot: getMockTreeSnapshot(),
53
+ endTreeOfHistoricContractTreeRootsSnapshot: getMockTreeSnapshot(),
54
+ endPublicDataTreeRoot: Fr.random(),
55
+ endL1ToL2MessageTreeSnapshot: getMockTreeSnapshot(),
56
+ endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot: getMockTreeSnapshot(),
57
+ newCommitments: times(KERNEL_NEW_COMMITMENTS_LENGTH, Fr.random),
58
+ newNullifiers: times(KERNEL_NEW_NULLIFIERS_LENGTH, Fr.random),
59
+ newContracts: newContractsCommitments?.map(x => Fr.fromBuffer(x)) ?? [Fr.random()],
60
+ newContractData: times(KERNEL_NEW_CONTRACTS_LENGTH, getMockContractData),
61
+ newPublicDataWrites: times(KERNEL_PUBLIC_DATA_UPDATE_REQUESTS_LENGTH, PublicDataWrite.random),
62
+ newL1ToL2Messages: getMockL1ToL2MessagesData(),
63
+ newL2ToL1Msgs: times(NEW_L2_TO_L1_MSGS_LENGTH, Fr.random),
64
+ newEncryptedLogs,
65
+ });
66
+ return block;
67
+ };
68
+ const createSynchroniser = (merkleTreeDb, rollupSource) => new ServerWorldStateSynchroniser(merkleTreeDb, rollupSource);
69
+ const log = createLogger('aztec:server_world_state_synchroniser_test');
70
+ describe('server_world_state_synchroniser', () => {
71
+ const rollupSource = {
72
+ getBlockHeight: jest.fn().mockImplementation(getLatestBlockNumber),
73
+ getL2Blocks: jest.fn().mockImplementation(consumeNextBlocks),
74
+ };
75
+ const merkleTreeDb = {
76
+ getTreeInfo: jest
77
+ .fn()
78
+ .mockImplementation(() => Promise.resolve({ treeId: MerkleTreeId.CONTRACT_TREE, root: Buffer.alloc(32, 0), size: 0n })),
79
+ appendLeaves: jest.fn().mockImplementation(() => Promise.resolve()),
80
+ updateLeaf: jest.fn().mockImplementation(() => Promise.resolve()),
81
+ getSiblingPath: jest.fn().mockImplementation(() => {
82
+ return async () => {
83
+ const wasm = await CircuitsWasm.get();
84
+ const pedersen = new Pedersen(wasm);
85
+ SiblingPath.ZERO(32, INITIAL_LEAF, pedersen);
86
+ }; //Promise.resolve();
87
+ }),
88
+ updateHistoricRootsTrees: jest.fn().mockImplementation(() => Promise.resolve()),
89
+ commit: jest.fn().mockImplementation(() => Promise.resolve()),
90
+ rollback: jest.fn().mockImplementation(() => Promise.resolve()),
91
+ handleL2Block: jest.fn().mockImplementation(() => Promise.resolve()),
92
+ };
93
+ it('can be constructed', () => {
94
+ expect(() => createSynchroniser(merkleTreeDb, rollupSource)).not.toThrow();
95
+ });
96
+ it('updates sync progress', async () => {
97
+ const server = createSynchroniser(merkleTreeDb, rollupSource);
98
+ // test initial state
99
+ let status = await server.status();
100
+ expect(status.syncedToL2Block).toEqual(0);
101
+ expect(status.state).toEqual(WorldStateRunningState.IDLE);
102
+ // create an initial block
103
+ let currentBlockNumber = 0;
104
+ nextBlocks = [getMockBlock(currentBlockNumber + 1)];
105
+ // start the sync process but don't await
106
+ server.start().catch(err => log('Sync not completed: ', err));
107
+ // now setup a loop to monitor the sync progress and push new blocks in
108
+ while (currentBlockNumber <= LATEST_BLOCK_NUMBER) {
109
+ status = await server.status();
110
+ expect(status.syncedToL2Block >= currentBlockNumber || status.syncedToL2Block <= currentBlockNumber + 1).toBeTruthy();
111
+ if (status.syncedToL2Block === LATEST_BLOCK_NUMBER) {
112
+ break;
113
+ }
114
+ expect(status.state >= WorldStateRunningState.IDLE || status.state <= WorldStateRunningState.SYNCHING).toBeTruthy();
115
+ if (status.syncedToL2Block === currentBlockNumber) {
116
+ await sleep(100);
117
+ continue;
118
+ }
119
+ currentBlockNumber++;
120
+ nextBlocks = [getMockBlock(currentBlockNumber + 1)];
121
+ }
122
+ // check the status agian, should be fully synced
123
+ status = await server.status();
124
+ expect(status.state).toEqual(WorldStateRunningState.RUNNING);
125
+ expect(status.syncedToL2Block).toEqual(LATEST_BLOCK_NUMBER);
126
+ // stop the synchroniser
127
+ await server.stop();
128
+ // check the final status
129
+ status = await server.status();
130
+ expect(status.state).toEqual(WorldStateRunningState.STOPPED);
131
+ expect(status.syncedToL2Block).toEqual(LATEST_BLOCK_NUMBER);
132
+ });
133
+ it('enables blocking until synced', async () => {
134
+ const server = createSynchroniser(merkleTreeDb, rollupSource);
135
+ let currentBlockNumber = 0;
136
+ const newBlocks = async () => {
137
+ while (currentBlockNumber <= LATEST_BLOCK_NUMBER) {
138
+ await sleep(100);
139
+ nextBlocks = [...nextBlocks, getMockBlock(++currentBlockNumber)];
140
+ }
141
+ };
142
+ // kick off the background queueing of blocks
143
+ const newBlockPromise = newBlocks();
144
+ // kick off the synching
145
+ const syncPromise = server.start();
146
+ // await the synching
147
+ await syncPromise;
148
+ await newBlockPromise;
149
+ let status = await server.status();
150
+ expect(status.state).toEqual(WorldStateRunningState.RUNNING);
151
+ expect(status.syncedToL2Block).toEqual(LATEST_BLOCK_NUMBER);
152
+ await server.stop();
153
+ status = await server.status();
154
+ expect(status.state).toEqual(WorldStateRunningState.STOPPED);
155
+ expect(status.syncedToL2Block).toEqual(LATEST_BLOCK_NUMBER);
156
+ });
157
+ it('handles multiple calls to start', async () => {
158
+ const server = createSynchroniser(merkleTreeDb, rollupSource);
159
+ let currentBlockNumber = 0;
160
+ const newBlocks = async () => {
161
+ while (currentBlockNumber < LATEST_BLOCK_NUMBER) {
162
+ await sleep(100);
163
+ const newBlock = getMockBlock(++currentBlockNumber);
164
+ nextBlocks = [...nextBlocks, newBlock];
165
+ }
166
+ };
167
+ // kick off the background queueing of blocks
168
+ const newBlockPromise = newBlocks();
169
+ // kick off the synching
170
+ await server.start();
171
+ // call start again, should get back the same promise
172
+ await server.start();
173
+ // wait until the block production has finished
174
+ await newBlockPromise;
175
+ await server.stop();
176
+ });
177
+ it('immediately syncs if no new blocks', async () => {
178
+ const server = createSynchroniser(merkleTreeDb, rollupSource);
179
+ rollupSource.getBlockHeight.mockImplementationOnce(() => {
180
+ return Promise.resolve(0);
181
+ });
182
+ // kick off the synching
183
+ const syncPromise = server.start();
184
+ // it should already be synced, no need to push new blocks
185
+ await syncPromise;
186
+ const status = await server.status();
187
+ expect(status.state).toBe(WorldStateRunningState.RUNNING);
188
+ expect(status.syncedToL2Block).toBe(0);
189
+ await server.stop();
190
+ });
191
+ it("can't be started if already stopped", async () => {
192
+ const server = createSynchroniser(merkleTreeDb, rollupSource);
193
+ rollupSource.getBlockHeight.mockImplementationOnce(() => {
194
+ return Promise.resolve(0);
195
+ });
196
+ // kick off the synching
197
+ const syncPromise = server.start();
198
+ await syncPromise;
199
+ await server.stop();
200
+ await expect(server.start()).rejects.toThrow();
201
+ });
202
+ it('adds the received L2 blocks', async () => {
203
+ merkleTreeDb.handleL2Block.mockReset();
204
+ const server = createSynchroniser(merkleTreeDb, rollupSource);
205
+ const totalBlocks = LATEST_BLOCK_NUMBER + 1;
206
+ nextBlocks = Array(totalBlocks)
207
+ .fill(0)
208
+ .map((_, index) => getMockBlock(index, [Buffer.alloc(32, index)]));
209
+ // sync the server
210
+ await server.start();
211
+ expect(merkleTreeDb.handleL2Block).toHaveBeenCalledTimes(totalBlocks);
212
+ await server.stop();
213
+ });
214
+ });
215
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyX3dvcmxkX3N0YXRlX3N5bmNocm9uaXNlci50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N5bmNocm9uaXNlci9zZXJ2ZXJfd29ybGRfc3RhdGVfc3luY2hyb25pc2VyLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHNCQUFzQixFQUN0QixZQUFZLEVBQ1osZUFBZSxFQUNmLDZCQUE2QixFQUM3QiwyQkFBMkIsRUFDM0IsNEJBQTRCLEVBQzVCLHlDQUF5QyxFQUN6Qyx3QkFBd0IsRUFDeEIsbUNBQW1DLEdBQ3BDLE1BQU0sb0JBQW9CLENBQUM7QUFDNUIsT0FBTyxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDekUsT0FBTyxFQUFFLFlBQVksRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFpQixZQUFZLEVBQUUsZUFBZSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ2xILE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFckMsT0FBTyxFQUFFLDRCQUE0QixFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFDcEYsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDdkUsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNoRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDckQsT0FBTyxLQUFLLE1BQU0sY0FBYyxDQUFDO0FBU2pDLE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxDQUFDO0FBQzlCLE1BQU0sb0JBQW9CLEdBQUcsR0FBRyxFQUFFLENBQUMsbUJBQW1CLENBQUM7QUFDdkQsSUFBSSxVQUFVLEdBQWMsRUFBRSxDQUFDO0FBQy9CLE1BQU0saUJBQWlCLEdBQUcsR0FBRyxFQUFFO0lBQzdCLE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQztJQUMxQixVQUFVLEdBQUcsRUFBRSxDQUFDO0lBQ2hCLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUNqQyxDQUFDLENBQUM7QUFFRixNQUFNLG1CQUFtQixHQUFHLEdBQUcsRUFBRTtJQUMvQixPQUFPLElBQUksc0JBQXNCLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ3JELENBQUMsQ0FBQztBQUVGLE1BQU0sbUJBQW1CLEdBQUcsR0FBRyxFQUFFO0lBQy9CLE9BQU8sWUFBWSxDQUFDLE1BQU0sRUFBRSxDQUFDO0FBQy9CLENBQUMsQ0FBQztBQUVGLE1BQU0sc0JBQXNCLEdBQUcsR0FBRyxFQUFFO0lBQ2xDLE9BQU8sZUFBZSxDQUFDLElBQUksQ0FBQztRQUMxQixPQUFPLEVBQUUsRUFBRSxDQUFDLE1BQU0sRUFBRTtRQUNwQixPQUFPLEVBQUUsRUFBRSxDQUFDLE1BQU0sRUFBRTtRQUNwQixXQUFXLEVBQUUsRUFBRSxDQUFDLE1BQU0sRUFBRTtRQUN4QixTQUFTLEVBQUUsRUFBRSxDQUFDLE1BQU0sRUFBRTtLQUN2QixDQUFDLENBQUM7QUFDTCxDQUFDLENBQUM7QUFFRixNQUFNLHlCQUF5QixHQUFHLEdBQUcsRUFBRTtJQUNyQyxPQUFPLElBQUksS0FBSyxDQUFDLG1DQUFtQyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0FBQy9FLENBQUMsQ0FBQztBQUVGLE1BQU0sWUFBWSxHQUFHLENBQUMsV0FBbUIsRUFBRSx1QkFBa0MsRUFBRSxFQUFFO0lBQy9FLE1BQU0sZ0JBQWdCLEdBQUcsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3ZELE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUM7UUFDL0IsTUFBTSxFQUFFLFdBQVc7UUFDbkIsZUFBZSxFQUFFLHNCQUFzQixFQUFFO1FBQ3pDLDRCQUE0QixFQUFFLG1CQUFtQixFQUFFO1FBQ25ELDBCQUEwQixFQUFFLG1CQUFtQixFQUFFO1FBQ2pELHlCQUF5QixFQUFFLG1CQUFtQixFQUFFO1FBQ2hELCtDQUErQyxFQUFFLG1CQUFtQixFQUFFO1FBQ3RFLDRDQUE0QyxFQUFFLG1CQUFtQixFQUFFO1FBQ25FLHVCQUF1QixFQUFFLEVBQUUsQ0FBQyxNQUFNLEVBQUU7UUFDcEMsOEJBQThCLEVBQUUsbUJBQW1CLEVBQUU7UUFDckQsaURBQWlELEVBQUUsbUJBQW1CLEVBQUU7UUFDeEUsMEJBQTBCLEVBQUUsbUJBQW1CLEVBQUU7UUFDakQsd0JBQXdCLEVBQUUsbUJBQW1CLEVBQUU7UUFDL0MsdUJBQXVCLEVBQUUsbUJBQW1CLEVBQUU7UUFDOUMsNkNBQTZDLEVBQUUsbUJBQW1CLEVBQUU7UUFDcEUsMENBQTBDLEVBQUUsbUJBQW1CLEVBQUU7UUFDakUscUJBQXFCLEVBQUUsRUFBRSxDQUFDLE1BQU0sRUFBRTtRQUNsQyw0QkFBNEIsRUFBRSxtQkFBbUIsRUFBRTtRQUNuRCwrQ0FBK0MsRUFBRSxtQkFBbUIsRUFBRTtRQUN0RSxjQUFjLEVBQUUsS0FBSyxDQUFDLDZCQUE2QixFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUM7UUFDL0QsYUFBYSxFQUFFLEtBQUssQ0FBQyw0QkFBNEIsRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDO1FBQzdELFlBQVksRUFBRSx1QkFBdUIsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDbEYsZUFBZSxFQUFFLEtBQUssQ0FBQywyQkFBMkIsRUFBRSxtQkFBbUIsQ0FBQztRQUN4RSxtQkFBbUIsRUFBRSxLQUFLLENBQUMseUNBQXlDLEVBQUUsZUFBZSxDQUFDLE1BQU0sQ0FBQztRQUM3RixpQkFBaUIsRUFBRSx5QkFBeUIsRUFBRTtRQUM5QyxhQUFhLEVBQUUsS0FBSyxDQUFDLHdCQUF3QixFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUM7UUFDekQsZ0JBQWdCO0tBQ2pCLENBQUMsQ0FBQztJQUNILE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQyxDQUFDO0FBRUYsTUFBTSxrQkFBa0IsR0FBRyxDQUFDLFlBQWlCLEVBQUUsWUFBaUIsRUFBRSxFQUFFLENBQ2xFLElBQUksNEJBQTRCLENBQUMsWUFBNEIsRUFBRSxZQUE2QixDQUFDLENBQUM7QUFFaEcsTUFBTSxHQUFHLEdBQUcsWUFBWSxDQUFDLDRDQUE0QyxDQUFDLENBQUM7QUFFdkUsUUFBUSxDQUFDLGlDQUFpQyxFQUFFLEdBQUcsRUFBRTtJQUMvQyxNQUFNLFlBQVksR0FBbUU7UUFDbkYsY0FBYyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQyxvQkFBb0IsQ0FBQztRQUNsRSxXQUFXLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLGtCQUFrQixDQUFDLGlCQUFpQixDQUFDO0tBQzdELENBQUM7SUFFRixNQUFNLFlBQVksR0FBMEI7UUFDMUMsV0FBVyxFQUFFLElBQUk7YUFDZCxFQUFFLEVBQUU7YUFDSixrQkFBa0IsQ0FBQyxHQUFHLEVBQUUsQ0FDdkIsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLE1BQU0sRUFBRSxZQUFZLENBQUMsYUFBYSxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FDN0Y7UUFDSCxZQUFZLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNuRSxVQUFVLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNqRSxjQUFjLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsRUFBRTtZQUNoRCxPQUFPLEtBQUssSUFBSSxFQUFFO2dCQUNoQixNQUFNLElBQUksR0FBRyxNQUFNLFlBQVksQ0FBQyxHQUFHLEVBQUUsQ0FBQztnQkFDdEMsTUFBTSxRQUFRLEdBQWEsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQzlDLFdBQVcsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLFlBQVksRUFBRSxRQUFRLENBQUMsQ0FBQztZQUMvQyxDQUFDLENBQUMsQ0FBQyxvQkFBb0I7UUFDekIsQ0FBQyxDQUFDO1FBQ0Ysd0JBQXdCLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUMvRSxNQUFNLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUM3RCxRQUFRLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUMvRCxhQUFhLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztLQUM5RCxDQUFDO0lBRVQsRUFBRSxDQUFDLG9CQUFvQixFQUFFLEdBQUcsRUFBRTtRQUM1QixNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsa0JBQWtCLENBQUMsWUFBWSxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQzdFLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLHVCQUF1QixFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3JDLE1BQU0sTUFBTSxHQUFHLGtCQUFrQixDQUFDLFlBQVksRUFBRSxZQUFZLENBQUMsQ0FBQztRQUU5RCxxQkFBcUI7UUFDckIsSUFBSSxNQUFNLEdBQUcsTUFBTSxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDbkMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFMUQsMEJBQTBCO1FBQzFCLElBQUksa0JBQWtCLEdBQUcsQ0FBQyxDQUFDO1FBQzNCLFVBQVUsR0FBRyxDQUFDLFlBQVksQ0FBQyxrQkFBa0IsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRXBELHlDQUF5QztRQUN6QyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLHNCQUFzQixFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFFOUQsdUVBQXVFO1FBQ3ZFLE9BQU8sa0JBQWtCLElBQUksbUJBQW1CLEVBQUU7WUFDaEQsTUFBTSxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQy9CLE1BQU0sQ0FDSixNQUFNLENBQUMsZUFBZSxJQUFJLGtCQUFrQixJQUFJLE1BQU0sQ0FBQyxlQUFlLElBQUksa0JBQWtCLEdBQUcsQ0FBQyxDQUNqRyxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ2YsSUFBSSxNQUFNLENBQUMsZUFBZSxLQUFLLG1CQUFtQixFQUFFO2dCQUNsRCxNQUFNO2FBQ1A7WUFDRCxNQUFNLENBQ0osTUFBTSxDQUFDLEtBQUssSUFBSSxzQkFBc0IsQ0FBQyxJQUFJLElBQUksTUFBTSxDQUFDLEtBQUssSUFBSSxzQkFBc0IsQ0FBQyxRQUFRLENBQy9GLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDZixJQUFJLE1BQU0sQ0FBQyxlQUFlLEtBQUssa0JBQWtCLEVBQUU7Z0JBQ2pELE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUNqQixTQUFTO2FBQ1Y7WUFDRCxrQkFBa0IsRUFBRSxDQUFDO1lBQ3JCLFVBQVUsR0FBRyxDQUFDLFlBQVksQ0FBQyxrQkFBa0IsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQ3JEO1FBRUQsaURBQWlEO1FBQ2pELE1BQU0sR0FBRyxNQUFNLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUMvQixNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUM3RCxNQUFNLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBRTVELHdCQUF3QjtRQUN4QixNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUVwQix5QkFBeUI7UUFDekIsTUFBTSxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQy9CLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLHNCQUFzQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzdELE1BQU0sQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDLENBQUMsT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFDOUQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsK0JBQStCLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDN0MsTUFBTSxNQUFNLEdBQUcsa0JBQWtCLENBQUMsWUFBWSxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQzlELElBQUksa0JBQWtCLEdBQUcsQ0FBQyxDQUFDO1FBRTNCLE1BQU0sU0FBUyxHQUFHLEtBQUssSUFBSSxFQUFFO1lBQzNCLE9BQU8sa0JBQWtCLElBQUksbUJBQW1CLEVBQUU7Z0JBQ2hELE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUNqQixVQUFVLEdBQUcsQ0FBQyxHQUFHLFVBQVUsRUFBRSxZQUFZLENBQUMsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7YUFDbEU7UUFDSCxDQUFDLENBQUM7UUFFRiw2Q0FBNkM7UUFDN0MsTUFBTSxlQUFlLEdBQUcsU0FBUyxFQUFFLENBQUM7UUFFcEMsd0JBQXdCO1FBQ3hCLE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUVuQyxxQkFBcUI7UUFDckIsTUFBTSxXQUFXLENBQUM7UUFFbEIsTUFBTSxlQUFlLENBQUM7UUFFdEIsSUFBSSxNQUFNLEdBQUcsTUFBTSxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDbkMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsc0JBQXNCLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDN0QsTUFBTSxDQUFDLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQyxPQUFPLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUM1RCxNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNwQixNQUFNLEdBQUcsTUFBTSxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDL0IsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsc0JBQXNCLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDN0QsTUFBTSxDQUFDLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQyxPQUFPLENBQUMsbUJBQW1CLENBQUMsQ0FBQztJQUM5RCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxpQ0FBaUMsRUFBRSxLQUFLLElBQUksRUFBRTtRQUMvQyxNQUFNLE1BQU0sR0FBRyxrQkFBa0IsQ0FBQyxZQUFZLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDOUQsSUFBSSxrQkFBa0IsR0FBRyxDQUFDLENBQUM7UUFFM0IsTUFBTSxTQUFTLEdBQUcsS0FBSyxJQUFJLEVBQUU7WUFDM0IsT0FBTyxrQkFBa0IsR0FBRyxtQkFBbUIsRUFBRTtnQkFDL0MsTUFBTSxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ2pCLE1BQU0sUUFBUSxHQUFHLFlBQVksQ0FBQyxFQUFFLGtCQUFrQixDQUFDLENBQUM7Z0JBQ3BELFVBQVUsR0FBRyxDQUFDLEdBQUcsVUFBVSxFQUFFLFFBQVEsQ0FBQyxDQUFDO2FBQ3hDO1FBQ0gsQ0FBQyxDQUFDO1FBRUYsNkNBQTZDO1FBQzdDLE1BQU0sZUFBZSxHQUFHLFNBQVMsRUFBRSxDQUFDO1FBRXBDLHdCQUF3QjtRQUN4QixNQUFNLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUVyQixxREFBcUQ7UUFDckQsTUFBTSxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7UUFFckIsK0NBQStDO1FBQy9DLE1BQU0sZUFBZSxDQUFDO1FBRXRCLE1BQU0sTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ3RCLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLG9DQUFvQyxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ2xELE1BQU0sTUFBTSxHQUFHLGtCQUFrQixDQUFDLFlBQVksRUFBRSxZQUFZLENBQUMsQ0FBQztRQUM5RCxZQUFZLENBQUMsY0FBYyxDQUFDLHNCQUFzQixDQUFDLEdBQUcsRUFBRTtZQUN0RCxPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDNUIsQ0FBQyxDQUFDLENBQUM7UUFFSCx3QkFBd0I7UUFDeEIsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBRW5DLDBEQUEwRDtRQUMxRCxNQUFNLFdBQVcsQ0FBQztRQUVsQixNQUFNLE1BQU0sR0FBRyxNQUFNLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNyQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxRCxNQUFNLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN2QyxNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUN0QixDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxxQ0FBcUMsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNuRCxNQUFNLE1BQU0sR0FBRyxrQkFBa0IsQ0FBQyxZQUFZLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDOUQsWUFBWSxDQUFDLGNBQWMsQ0FBQyxzQkFBc0IsQ0FBQyxHQUFHLEVBQUU7WUFDdEQsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzVCLENBQUMsQ0FBQyxDQUFDO1FBRUgsd0JBQXdCO1FBQ3hCLE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNuQyxNQUFNLFdBQVcsQ0FBQztRQUNsQixNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUVwQixNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDakQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsNkJBQTZCLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDM0MsWUFBWSxDQUFDLGFBQWEsQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUN2QyxNQUFNLE1BQU0sR0FBRyxrQkFBa0IsQ0FBQyxZQUFZLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDOUQsTUFBTSxXQUFXLEdBQUcsbUJBQW1CLEdBQUcsQ0FBQyxDQUFDO1FBQzVDLFVBQVUsR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFDO2FBQzVCLElBQUksQ0FBQyxDQUFDLENBQUM7YUFDUCxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckUsa0JBQWtCO1FBQ2xCLE1BQU0sTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBRXJCLE1BQU0sQ0FBQyxZQUFZLENBQUMsYUFBYSxDQUFDLENBQUMscUJBQXFCLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDdEUsTUFBTSxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDdEIsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyJ9
@@ -0,0 +1,34 @@
1
+ import { MerkleTreeOperations } from '../index.js';
2
+ /**
3
+ * Defines the possible states of the world state synchroniser.
4
+ */
5
+ export declare enum WorldStateRunningState {
6
+ IDLE = 0,
7
+ SYNCHING = 1,
8
+ RUNNING = 2,
9
+ STOPPED = 3
10
+ }
11
+ /**
12
+ * Defines the status of the world state synchroniser.
13
+ */
14
+ export interface WorldStateStatus {
15
+ /**
16
+ * The current state of the world state synchroniser.
17
+ */
18
+ state: WorldStateRunningState;
19
+ /**
20
+ * The block number that the world state synchroniser is synced to.
21
+ */
22
+ syncedToL2Block: number;
23
+ }
24
+ /**
25
+ * Defines the interface for a world state synchroniser.
26
+ */
27
+ export interface WorldStateSynchroniser {
28
+ start(): void;
29
+ status(): Promise<WorldStateStatus>;
30
+ stop(): Promise<void>;
31
+ getLatest(): MerkleTreeOperations;
32
+ getCommitted(): MerkleTreeOperations;
33
+ }
34
+ //# sourceMappingURL=world_state_synchroniser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"world_state_synchroniser.d.ts","sourceRoot":"","sources":["../../src/synchroniser/world_state_synchroniser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD;;GAEG;AACH,oBAAY,sBAAsB;IAChC,IAAI,IAAA;IACJ,QAAQ,IAAA;IACR,OAAO,IAAA;IACP,OAAO,IAAA;CACR;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,KAAK,EAAE,sBAAsB,CAAC;IAC9B;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACpC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,SAAS,IAAI,oBAAoB,CAAC;IAClC,YAAY,IAAI,oBAAoB,CAAC;CACtC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Defines the possible states of the world state synchroniser.
3
+ */
4
+ export var WorldStateRunningState;
5
+ (function (WorldStateRunningState) {
6
+ WorldStateRunningState[WorldStateRunningState["IDLE"] = 0] = "IDLE";
7
+ WorldStateRunningState[WorldStateRunningState["SYNCHING"] = 1] = "SYNCHING";
8
+ WorldStateRunningState[WorldStateRunningState["RUNNING"] = 2] = "RUNNING";
9
+ WorldStateRunningState[WorldStateRunningState["STOPPED"] = 3] = "STOPPED";
10
+ })(WorldStateRunningState || (WorldStateRunningState = {}));
11
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29ybGRfc3RhdGVfc3luY2hyb25pc2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N5bmNocm9uaXNlci93b3JsZF9zdGF0ZV9zeW5jaHJvbmlzZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUE7O0dBRUc7QUFDSCxNQUFNLENBQU4sSUFBWSxzQkFLWDtBQUxELFdBQVksc0JBQXNCO0lBQ2hDLG1FQUFJLENBQUE7SUFDSiwyRUFBUSxDQUFBO0lBQ1IseUVBQU8sQ0FBQTtJQUNQLHlFQUFPLENBQUE7QUFDVCxDQUFDLEVBTFcsc0JBQXNCLEtBQXRCLHNCQUFzQixRQUtqQyJ9
@@ -0,0 +1,12 @@
1
+ import { AztecAddress } from '@aztec/foundation/aztec-address';
2
+ import { Fr } from '@aztec/foundation/fields';
3
+ import { IWasmModule } from '@aztec/foundation/wasm';
4
+ /**
5
+ * Computes the index in the public data tree for a given contract and storage slot.
6
+ * @param contract - Address of the contract who owns the storage.
7
+ * @param slot - Slot within the contract storage.
8
+ * @param bbWasm - Wasm module for computing the hash.
9
+ * @returns The leaf index of the public data tree that maps to this storage slot.
10
+ */
11
+ export declare function computePublicDataTreeLeafIndex(contract: AztecAddress, slot: Fr, wasm: IWasmModule): bigint;
12
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAG9C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,GAAG,MAAM,CAQ1G"}
package/dest/utils.js ADDED
@@ -0,0 +1,14 @@
1
+ import { GeneratorIndex } from '@aztec/circuits.js';
2
+ import { pedersenCompressWithHashIndex } from '@aztec/circuits.js/barretenberg';
3
+ import { toBigInt } from '@aztec/foundation/serialize';
4
+ /**
5
+ * Computes the index in the public data tree for a given contract and storage slot.
6
+ * @param contract - Address of the contract who owns the storage.
7
+ * @param slot - Slot within the contract storage.
8
+ * @param bbWasm - Wasm module for computing the hash.
9
+ * @returns The leaf index of the public data tree that maps to this storage slot.
10
+ */
11
+ export function computePublicDataTreeLeafIndex(contract, slot, wasm) {
12
+ return toBigInt(pedersenCompressWithHashIndex(wasm, [contract, slot].map(f => f.toBuffer()), GeneratorIndex.PUBLIC_LEAF_INDEX));
13
+ }
14
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3BELE9BQU8sRUFBRSw2QkFBNkIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBR2hGLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUl2RDs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsOEJBQThCLENBQUMsUUFBc0IsRUFBRSxJQUFRLEVBQUUsSUFBaUI7SUFDaEcsT0FBTyxRQUFRLENBQ2IsNkJBQTZCLENBQzNCLElBQUksRUFDSixDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsRUFDdkMsY0FBYyxDQUFDLGlCQUFpQixDQUNqQyxDQUNGLENBQUM7QUFDSixDQUFDIn0=