@aztec/world-state 0.7.2 → 0.7.4
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.
- package/.tsbuildinfo +1 -0
- package/dest/index.d.ts +5 -0
- package/dest/index.d.ts.map +1 -0
- package/dest/index.js +5 -0
- package/dest/merkle-tree/merkle_tree_operations_facade.d.ts +127 -0
- package/dest/merkle-tree/merkle_tree_operations_facade.d.ts.map +1 -0
- package/dest/merkle-tree/merkle_tree_operations_facade.js +147 -0
- package/dest/synchroniser/config.d.ts +19 -0
- package/dest/synchroniser/config.d.ts.map +1 -0
- package/dest/synchroniser/config.js +13 -0
- package/dest/synchroniser/index.d.ts +3 -0
- package/dest/synchroniser/index.d.ts.map +1 -0
- package/dest/synchroniser/index.js +3 -0
- package/dest/synchroniser/server_world_state_synchroniser.d.ts +55 -0
- package/dest/synchroniser/server_world_state_synchroniser.d.ts.map +1 -0
- package/dest/synchroniser/server_world_state_synchroniser.js +163 -0
- package/dest/synchroniser/server_world_state_synchroniser.test.d.ts +2 -0
- package/dest/synchroniser/server_world_state_synchroniser.test.d.ts.map +1 -0
- package/dest/synchroniser/server_world_state_synchroniser.test.js +317 -0
- package/dest/synchroniser/world_state_synchroniser.d.ts +59 -0
- package/dest/synchroniser/world_state_synchroniser.d.ts.map +1 -0
- package/dest/synchroniser/world_state_synchroniser.js +11 -0
- package/dest/utils.d.ts +18 -0
- package/dest/utils.d.ts.map +1 -0
- package/dest/utils.js +23 -0
- package/dest/world-state-db/index.d.ts +189 -0
- package/dest/world-state-db/index.d.ts.map +1 -0
- package/dest/world-state-db/index.js +31 -0
- package/dest/world-state-db/merkle_trees.d.ts +228 -0
- package/dest/world-state-db/merkle_trees.d.ts.map +1 -0
- package/dest/world-state-db/merkle_trees.js +407 -0
- package/package.json +5 -5
- package/Dockerfile +0 -18
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { L2BlockSource } from '@aztec/types';
|
|
2
|
+
import { MerkleTreeOperations, MerkleTrees } from '../index.js';
|
|
3
|
+
import { WorldStateConfig } from './config.js';
|
|
4
|
+
import { WorldStateStatus, WorldStateSynchroniser } from './world_state_synchroniser.js';
|
|
5
|
+
/**
|
|
6
|
+
* Synchronises the world state with the L2 blocks from a L2BlockSource.
|
|
7
|
+
* The synchroniser will download the L2 blocks from the L2BlockSource and insert the new commitments into the merkle
|
|
8
|
+
* tree.
|
|
9
|
+
*/
|
|
10
|
+
export declare class ServerWorldStateSynchroniser implements WorldStateSynchroniser {
|
|
11
|
+
private merkleTreeDb;
|
|
12
|
+
private l2BlockSource;
|
|
13
|
+
private log;
|
|
14
|
+
private currentL2BlockNum;
|
|
15
|
+
private latestBlockNumberAtStart;
|
|
16
|
+
private l2BlockDownloader;
|
|
17
|
+
private syncPromise;
|
|
18
|
+
private syncResolve?;
|
|
19
|
+
private jobQueue;
|
|
20
|
+
private stopping;
|
|
21
|
+
private runningPromise;
|
|
22
|
+
private currentState;
|
|
23
|
+
constructor(merkleTreeDb: MerkleTrees, l2BlockSource: L2BlockSource, config: WorldStateConfig, log?: import("@aztec/foundation/log").DebugLogger);
|
|
24
|
+
getLatest(): MerkleTreeOperations;
|
|
25
|
+
getCommitted(): MerkleTreeOperations;
|
|
26
|
+
start(): Promise<void>;
|
|
27
|
+
stop(): Promise<void>;
|
|
28
|
+
status(): Promise<WorldStateStatus>;
|
|
29
|
+
/**
|
|
30
|
+
* Forces an immediate sync
|
|
31
|
+
* @param minBlockNumber - The minimum block number that we must sync to
|
|
32
|
+
* @returns A promise that resolves once the sync has completed.
|
|
33
|
+
*/
|
|
34
|
+
syncImmediate(minBlockNumber?: number): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Checks for the availability of new blocks and processes them.
|
|
37
|
+
*/
|
|
38
|
+
private collectAndProcessBlocks;
|
|
39
|
+
/**
|
|
40
|
+
* Handles a list of L2 blocks (i.e. Inserts the new commitments into the merkle tree).
|
|
41
|
+
* @param l2Blocks - The L2 blocks to handle.
|
|
42
|
+
*/
|
|
43
|
+
private handleL2Blocks;
|
|
44
|
+
/**
|
|
45
|
+
* Handles a single L2 block (i.e. Inserts the new commitments into the merkle tree).
|
|
46
|
+
* @param l2Block - The L2 block to handle.
|
|
47
|
+
*/
|
|
48
|
+
private handleL2Block;
|
|
49
|
+
/**
|
|
50
|
+
* Method to set the value of the current state.
|
|
51
|
+
* @param newState - New state value.
|
|
52
|
+
*/
|
|
53
|
+
private setCurrentState;
|
|
54
|
+
}
|
|
55
|
+
//# 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":"AAEA,OAAO,EAA8B,aAAa,EAAE,MAAM,cAAc,CAAC;AAEzE,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAA0B,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAEjH;;;;GAIG;AACH,qBAAa,4BAA6B,YAAW,sBAAsB;IAavE,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,aAAa;IAErB,OAAO,CAAC,GAAG;IAfb,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,wBAAwB,CAAK;IAErC,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,WAAW,CAAoC;IACvD,OAAO,CAAC,WAAW,CAAC,CAAyB;IAC7C,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,cAAc,CAAoC;IAC1D,OAAO,CAAC,YAAY,CAAuD;gBAGjE,YAAY,EAAE,WAAW,EACzB,aAAa,EAAE,aAAa,EACpC,MAAM,EAAE,gBAAgB,EAChB,GAAG,8CAAyC;IAS/C,SAAS,IAAI,oBAAoB;IAIjC,YAAY,IAAI,oBAAoB;IAI9B,KAAK;IAwCL,IAAI;IAUV,MAAM,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAQ1C;;;;OAIG;IACU,aAAa,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoClE;;OAEG;YACW,uBAAuB;IAMrC;;;OAGG;YACW,cAAc;IAM5B;;;OAGG;YACW,aAAa;IAc3B;;;OAGG;IACH,OAAO,CAAC,eAAe;CAIxB"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { SerialQueue } from '@aztec/foundation/fifo';
|
|
2
|
+
import { createDebugLogger } from '@aztec/foundation/log';
|
|
3
|
+
import { L2BlockDownloader } from '@aztec/types';
|
|
4
|
+
import { MerkleTreeOperationsFacade } from '../merkle-tree/merkle_tree_operations_facade.js';
|
|
5
|
+
import { WorldStateRunningState } from './world_state_synchroniser.js';
|
|
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, config, 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.jobQueue = new SerialQueue();
|
|
21
|
+
this.stopping = false;
|
|
22
|
+
this.runningPromise = Promise.resolve();
|
|
23
|
+
this.currentState = WorldStateRunningState.IDLE;
|
|
24
|
+
this.l2BlockDownloader = new L2BlockDownloader(l2BlockSource, config.l2QueueSize, config.worldStateBlockCheckIntervalMS);
|
|
25
|
+
}
|
|
26
|
+
getLatest() {
|
|
27
|
+
return new MerkleTreeOperationsFacade(this.merkleTreeDb, true);
|
|
28
|
+
}
|
|
29
|
+
getCommitted() {
|
|
30
|
+
return new MerkleTreeOperationsFacade(this.merkleTreeDb, false);
|
|
31
|
+
}
|
|
32
|
+
async start() {
|
|
33
|
+
if (this.currentState === WorldStateRunningState.STOPPED) {
|
|
34
|
+
throw new Error('Synchroniser already stopped');
|
|
35
|
+
}
|
|
36
|
+
if (this.currentState !== WorldStateRunningState.IDLE) {
|
|
37
|
+
return this.syncPromise;
|
|
38
|
+
}
|
|
39
|
+
// get the current latest block number
|
|
40
|
+
this.latestBlockNumberAtStart = await this.l2BlockSource.getBlockNumber();
|
|
41
|
+
const blockToDownloadFrom = this.currentL2BlockNum + 1;
|
|
42
|
+
// if there are blocks to be retrieved, go to a synching state
|
|
43
|
+
if (blockToDownloadFrom <= this.latestBlockNumberAtStart) {
|
|
44
|
+
this.setCurrentState(WorldStateRunningState.SYNCHING);
|
|
45
|
+
this.syncPromise = new Promise(resolve => {
|
|
46
|
+
this.syncResolve = resolve;
|
|
47
|
+
});
|
|
48
|
+
this.log(`Starting sync from ${blockToDownloadFrom}, latest block ${this.latestBlockNumberAtStart}`);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// if no blocks to be retrieved, go straight to running
|
|
52
|
+
this.setCurrentState(WorldStateRunningState.RUNNING);
|
|
53
|
+
this.syncPromise = Promise.resolve();
|
|
54
|
+
this.log(`Next block ${blockToDownloadFrom} already beyond latest block at ${this.latestBlockNumberAtStart}`);
|
|
55
|
+
}
|
|
56
|
+
// start looking for further blocks
|
|
57
|
+
const blockProcess = async () => {
|
|
58
|
+
while (!this.stopping) {
|
|
59
|
+
await this.jobQueue.put(() => this.collectAndProcessBlocks());
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
this.jobQueue.start();
|
|
63
|
+
this.runningPromise = blockProcess();
|
|
64
|
+
this.l2BlockDownloader.start(blockToDownloadFrom);
|
|
65
|
+
this.log(`Started block downloader from block ${blockToDownloadFrom}`);
|
|
66
|
+
return this.syncPromise;
|
|
67
|
+
}
|
|
68
|
+
async stop() {
|
|
69
|
+
this.log('Stopping world state...');
|
|
70
|
+
this.stopping = true;
|
|
71
|
+
await this.l2BlockDownloader.stop();
|
|
72
|
+
await this.jobQueue.cancel();
|
|
73
|
+
await this.merkleTreeDb.stop();
|
|
74
|
+
await this.runningPromise;
|
|
75
|
+
this.setCurrentState(WorldStateRunningState.STOPPED);
|
|
76
|
+
}
|
|
77
|
+
status() {
|
|
78
|
+
const status = {
|
|
79
|
+
syncedToL2Block: this.currentL2BlockNum,
|
|
80
|
+
state: this.currentState,
|
|
81
|
+
};
|
|
82
|
+
return Promise.resolve(status);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Forces an immediate sync
|
|
86
|
+
* @param minBlockNumber - The minimum block number that we must sync to
|
|
87
|
+
* @returns A promise that resolves once the sync has completed.
|
|
88
|
+
*/
|
|
89
|
+
async syncImmediate(minBlockNumber) {
|
|
90
|
+
if (this.currentState !== WorldStateRunningState.RUNNING) {
|
|
91
|
+
throw new Error(`World State is not running, unable to perform sync`);
|
|
92
|
+
}
|
|
93
|
+
// If we have been given a block number to sync to and we have reached that number
|
|
94
|
+
// then return.
|
|
95
|
+
if (minBlockNumber !== undefined && minBlockNumber <= this.currentL2BlockNum) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const blockToSyncTo = minBlockNumber === undefined ? 'latest' : `${minBlockNumber}`;
|
|
99
|
+
this.log(`World State at block ${this.currentL2BlockNum}, told to sync to block ${blockToSyncTo}...`);
|
|
100
|
+
// ensure any outstanding block updates are completed first.
|
|
101
|
+
await this.jobQueue.syncPoint();
|
|
102
|
+
while (true) {
|
|
103
|
+
// Check the block number again
|
|
104
|
+
if (minBlockNumber !== undefined && minBlockNumber <= this.currentL2BlockNum) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
// Poll for more blocks
|
|
108
|
+
const numBlocks = await this.l2BlockDownloader.pollImmediate();
|
|
109
|
+
this.log(`Block download immediate poll yielded ${numBlocks} blocks`);
|
|
110
|
+
if (numBlocks) {
|
|
111
|
+
// More blocks were received, process them and go round again
|
|
112
|
+
await this.jobQueue.put(() => this.collectAndProcessBlocks());
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
// No blocks are available, if we have been given a block number then we can't achieve it
|
|
116
|
+
if (minBlockNumber !== undefined) {
|
|
117
|
+
throw new Error(`Unable to sync to block number ${minBlockNumber}, currently synced to block ${this.currentL2BlockNum}`);
|
|
118
|
+
}
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Checks for the availability of new blocks and processes them.
|
|
124
|
+
*/
|
|
125
|
+
async collectAndProcessBlocks() {
|
|
126
|
+
// This request for blocks will timeout after 1 second if no blocks are received
|
|
127
|
+
const blocks = await this.l2BlockDownloader.getL2Blocks(1);
|
|
128
|
+
await this.handleL2Blocks(blocks);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Handles a list of L2 blocks (i.e. Inserts the new commitments into the merkle tree).
|
|
132
|
+
* @param l2Blocks - The L2 blocks to handle.
|
|
133
|
+
*/
|
|
134
|
+
async handleL2Blocks(l2Blocks) {
|
|
135
|
+
for (const l2Block of l2Blocks) {
|
|
136
|
+
await this.handleL2Block(l2Block);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Handles a single L2 block (i.e. Inserts the new commitments into the merkle tree).
|
|
141
|
+
* @param l2Block - The L2 block to handle.
|
|
142
|
+
*/
|
|
143
|
+
async handleL2Block(l2Block) {
|
|
144
|
+
await this.merkleTreeDb.handleL2Block(l2Block);
|
|
145
|
+
this.currentL2BlockNum = l2Block.number;
|
|
146
|
+
if (this.currentState === WorldStateRunningState.SYNCHING &&
|
|
147
|
+
this.currentL2BlockNum >= this.latestBlockNumberAtStart) {
|
|
148
|
+
this.setCurrentState(WorldStateRunningState.RUNNING);
|
|
149
|
+
if (this.syncResolve !== undefined) {
|
|
150
|
+
this.syncResolve();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Method to set the value of the current state.
|
|
156
|
+
* @param newState - New state value.
|
|
157
|
+
*/
|
|
158
|
+
setCurrentState(newState) {
|
|
159
|
+
this.currentState = newState;
|
|
160
|
+
this.log(`Moved to state ${WorldStateRunningState[this.currentState]}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyX3dvcmxkX3N0YXRlX3N5bmNocm9uaXNlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zeW5jaHJvbmlzZXIvc2VydmVyX3dvcmxkX3N0YXRlX3N5bmNocm9uaXNlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDckQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDMUQsT0FBTyxFQUFXLGlCQUFpQixFQUFpQixNQUFNLGNBQWMsQ0FBQztBQUd6RSxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSxpREFBaUQsQ0FBQztBQUU3RixPQUFPLEVBQUUsc0JBQXNCLEVBQTRDLE1BQU0sK0JBQStCLENBQUM7QUFFakg7Ozs7R0FJRztBQUNILE1BQU0sT0FBTyw0QkFBNEI7SUFZdkMsWUFDVSxZQUF5QixFQUN6QixhQUE0QixFQUNwQyxNQUF3QixFQUNoQixNQUFNLGlCQUFpQixDQUFDLG1CQUFtQixDQUFDO1FBSDVDLGlCQUFZLEdBQVosWUFBWSxDQUFhO1FBQ3pCLGtCQUFhLEdBQWIsYUFBYSxDQUFlO1FBRTVCLFFBQUcsR0FBSCxHQUFHLENBQXlDO1FBZjlDLHNCQUFpQixHQUFHLENBQUMsQ0FBQztRQUN0Qiw2QkFBd0IsR0FBRyxDQUFDLENBQUM7UUFHN0IsZ0JBQVcsR0FBa0IsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQy9DLGdCQUFXLEdBQWdCLFNBQVMsQ0FBQztRQUNyQyxhQUFRLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQztRQUM3QixhQUFRLEdBQUcsS0FBSyxDQUFDO1FBQ2pCLG1CQUFjLEdBQWtCLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNsRCxpQkFBWSxHQUEyQixzQkFBc0IsQ0FBQyxJQUFJLENBQUM7UUFRekUsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksaUJBQWlCLENBQzVD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
|
|
@@ -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,317 @@
|
|
|
1
|
+
import { AppendOnlyTreeSnapshot, CircuitsWasm, Fr, GlobalVariables, MAX_NEW_COMMITMENTS_PER_TX, MAX_NEW_CONTRACTS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, } from '@aztec/circuits.js';
|
|
2
|
+
import { createDebugLogger } from '@aztec/foundation/log';
|
|
3
|
+
import { sleep } from '@aztec/foundation/sleep';
|
|
4
|
+
import { INITIAL_LEAF, Pedersen } from '@aztec/merkle-tree';
|
|
5
|
+
import { ContractData, L2Block, L2BlockL2Logs, MerkleTreeId, PublicDataWrite, SiblingPath, } from '@aztec/types';
|
|
6
|
+
import { jest } from '@jest/globals';
|
|
7
|
+
import times from 'lodash.times';
|
|
8
|
+
import { ServerWorldStateSynchroniser } from './server_world_state_synchroniser.js';
|
|
9
|
+
import { WorldStateRunningState } from './world_state_synchroniser.js';
|
|
10
|
+
const LATEST_BLOCK_NUMBER = 5;
|
|
11
|
+
const getLatestBlockNumber = () => LATEST_BLOCK_NUMBER;
|
|
12
|
+
let nextBlocks = [];
|
|
13
|
+
const consumeNextBlocks = () => {
|
|
14
|
+
const blocks = nextBlocks;
|
|
15
|
+
nextBlocks = [];
|
|
16
|
+
return Promise.resolve(blocks);
|
|
17
|
+
};
|
|
18
|
+
const getMockTreeSnapshot = () => {
|
|
19
|
+
return new AppendOnlyTreeSnapshot(Fr.random(), 16);
|
|
20
|
+
};
|
|
21
|
+
const getMockContractData = () => {
|
|
22
|
+
return ContractData.random();
|
|
23
|
+
};
|
|
24
|
+
const getMockGlobalVariables = () => {
|
|
25
|
+
return GlobalVariables.from({
|
|
26
|
+
chainId: Fr.random(),
|
|
27
|
+
version: Fr.random(),
|
|
28
|
+
blockNumber: Fr.random(),
|
|
29
|
+
timestamp: Fr.random(),
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
const getMockL1ToL2MessagesData = () => {
|
|
33
|
+
return new Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).map(() => Fr.random());
|
|
34
|
+
};
|
|
35
|
+
const getMockBlock = (blockNumber, newContractsCommitments) => {
|
|
36
|
+
const newEncryptedLogs = L2BlockL2Logs.random(1, 2, 3);
|
|
37
|
+
const block = L2Block.fromFields({
|
|
38
|
+
number: blockNumber,
|
|
39
|
+
globalVariables: getMockGlobalVariables(),
|
|
40
|
+
startPrivateDataTreeSnapshot: getMockTreeSnapshot(),
|
|
41
|
+
startNullifierTreeSnapshot: getMockTreeSnapshot(),
|
|
42
|
+
startContractTreeSnapshot: getMockTreeSnapshot(),
|
|
43
|
+
startPublicDataTreeRoot: Fr.random(),
|
|
44
|
+
startL1ToL2MessagesTreeSnapshot: getMockTreeSnapshot(),
|
|
45
|
+
startHistoricBlocksTreeSnapshot: getMockTreeSnapshot(),
|
|
46
|
+
endPrivateDataTreeSnapshot: getMockTreeSnapshot(),
|
|
47
|
+
endNullifierTreeSnapshot: getMockTreeSnapshot(),
|
|
48
|
+
endContractTreeSnapshot: getMockTreeSnapshot(),
|
|
49
|
+
endPublicDataTreeRoot: Fr.random(),
|
|
50
|
+
endL1ToL2MessagesTreeSnapshot: getMockTreeSnapshot(),
|
|
51
|
+
endHistoricBlocksTreeSnapshot: getMockTreeSnapshot(),
|
|
52
|
+
newCommitments: times(MAX_NEW_COMMITMENTS_PER_TX, Fr.random),
|
|
53
|
+
newNullifiers: times(MAX_NEW_NULLIFIERS_PER_TX, Fr.random),
|
|
54
|
+
newContracts: newContractsCommitments?.map(x => Fr.fromBuffer(x)) ?? [Fr.random()],
|
|
55
|
+
newContractData: times(MAX_NEW_CONTRACTS_PER_TX, getMockContractData),
|
|
56
|
+
newPublicDataWrites: times(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite.random),
|
|
57
|
+
newL1ToL2Messages: getMockL1ToL2MessagesData(),
|
|
58
|
+
newL2ToL1Msgs: times(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, Fr.random),
|
|
59
|
+
newEncryptedLogs,
|
|
60
|
+
});
|
|
61
|
+
return block;
|
|
62
|
+
};
|
|
63
|
+
const createSynchroniser = (merkleTreeDb, rollupSource, blockCheckInterval = 100) => {
|
|
64
|
+
const worldStateConfig = {
|
|
65
|
+
worldStateBlockCheckIntervalMS: blockCheckInterval,
|
|
66
|
+
l2QueueSize: 1000,
|
|
67
|
+
};
|
|
68
|
+
return new ServerWorldStateSynchroniser(merkleTreeDb, rollupSource, worldStateConfig);
|
|
69
|
+
};
|
|
70
|
+
const log = createDebugLogger('aztec:server_world_state_synchroniser_test');
|
|
71
|
+
describe('server_world_state_synchroniser', () => {
|
|
72
|
+
const rollupSource = {
|
|
73
|
+
getBlockNumber: jest.fn().mockImplementation(getLatestBlockNumber),
|
|
74
|
+
getL2Blocks: jest.fn().mockImplementation(consumeNextBlocks),
|
|
75
|
+
};
|
|
76
|
+
const merkleTreeDb = {
|
|
77
|
+
getTreeInfo: jest
|
|
78
|
+
.fn()
|
|
79
|
+
.mockImplementation(() => Promise.resolve({ treeId: MerkleTreeId.CONTRACT_TREE, root: Buffer.alloc(32, 0), size: 0n })),
|
|
80
|
+
appendLeaves: jest.fn().mockImplementation(() => Promise.resolve()),
|
|
81
|
+
updateLeaf: jest.fn().mockImplementation(() => Promise.resolve()),
|
|
82
|
+
getSiblingPath: jest.fn().mockImplementation(() => {
|
|
83
|
+
return async () => {
|
|
84
|
+
const wasm = await CircuitsWasm.get();
|
|
85
|
+
const pedersen = new Pedersen(wasm);
|
|
86
|
+
SiblingPath.ZERO(32, INITIAL_LEAF, pedersen);
|
|
87
|
+
}; //Promise.resolve();
|
|
88
|
+
}),
|
|
89
|
+
updateHistoricBlocksTree: jest.fn().mockImplementation(() => Promise.resolve()),
|
|
90
|
+
commit: jest.fn().mockImplementation(() => Promise.resolve()),
|
|
91
|
+
rollback: jest.fn().mockImplementation(() => Promise.resolve()),
|
|
92
|
+
handleL2Block: jest.fn().mockImplementation(() => Promise.resolve()),
|
|
93
|
+
stop: jest.fn().mockImplementation(() => Promise.resolve()),
|
|
94
|
+
};
|
|
95
|
+
const performInitialSync = async (server) => {
|
|
96
|
+
// test initial state
|
|
97
|
+
let status = await server.status();
|
|
98
|
+
expect(status.syncedToL2Block).toEqual(0);
|
|
99
|
+
expect(status.state).toEqual(WorldStateRunningState.IDLE);
|
|
100
|
+
// create the initial blocks
|
|
101
|
+
nextBlocks = Array(LATEST_BLOCK_NUMBER)
|
|
102
|
+
.fill(0)
|
|
103
|
+
.map((_, index) => getMockBlock(index + 1));
|
|
104
|
+
// start the sync process and await it
|
|
105
|
+
await server.start().catch(err => log.error('Sync not completed: ', err));
|
|
106
|
+
status = await server.status();
|
|
107
|
+
expect(status.syncedToL2Block).toBe(LATEST_BLOCK_NUMBER);
|
|
108
|
+
};
|
|
109
|
+
it('can be constructed', () => {
|
|
110
|
+
expect(() => createSynchroniser(merkleTreeDb, rollupSource)).not.toThrow();
|
|
111
|
+
});
|
|
112
|
+
it('updates sync progress', async () => {
|
|
113
|
+
const server = createSynchroniser(merkleTreeDb, rollupSource);
|
|
114
|
+
// test initial state
|
|
115
|
+
let status = await server.status();
|
|
116
|
+
expect(status.syncedToL2Block).toEqual(0);
|
|
117
|
+
expect(status.state).toEqual(WorldStateRunningState.IDLE);
|
|
118
|
+
// create an initial block
|
|
119
|
+
let currentBlockNumber = 0;
|
|
120
|
+
nextBlocks = [getMockBlock(currentBlockNumber + 1)];
|
|
121
|
+
// start the sync process but don't await
|
|
122
|
+
server.start().catch(err => log.error('Sync not completed: ', err));
|
|
123
|
+
// now setup a loop to monitor the sync progress and push new blocks in
|
|
124
|
+
while (currentBlockNumber <= LATEST_BLOCK_NUMBER) {
|
|
125
|
+
status = await server.status();
|
|
126
|
+
expect(status.syncedToL2Block >= currentBlockNumber || status.syncedToL2Block <= currentBlockNumber + 1).toBeTruthy();
|
|
127
|
+
if (status.syncedToL2Block === LATEST_BLOCK_NUMBER) {
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
expect(status.state >= WorldStateRunningState.IDLE || status.state <= WorldStateRunningState.SYNCHING).toBeTruthy();
|
|
131
|
+
if (status.syncedToL2Block === currentBlockNumber) {
|
|
132
|
+
await sleep(100);
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
currentBlockNumber++;
|
|
136
|
+
nextBlocks = [getMockBlock(currentBlockNumber + 1)];
|
|
137
|
+
}
|
|
138
|
+
// check the status agian, should be fully synced
|
|
139
|
+
status = await server.status();
|
|
140
|
+
expect(status.state).toEqual(WorldStateRunningState.RUNNING);
|
|
141
|
+
expect(status.syncedToL2Block).toEqual(LATEST_BLOCK_NUMBER);
|
|
142
|
+
// stop the synchroniser
|
|
143
|
+
await server.stop();
|
|
144
|
+
// check the final status
|
|
145
|
+
status = await server.status();
|
|
146
|
+
expect(status.state).toEqual(WorldStateRunningState.STOPPED);
|
|
147
|
+
expect(status.syncedToL2Block).toEqual(LATEST_BLOCK_NUMBER);
|
|
148
|
+
});
|
|
149
|
+
it('enables blocking until synced', async () => {
|
|
150
|
+
const server = createSynchroniser(merkleTreeDb, rollupSource);
|
|
151
|
+
let currentBlockNumber = 0;
|
|
152
|
+
const newBlocks = async () => {
|
|
153
|
+
while (currentBlockNumber <= LATEST_BLOCK_NUMBER) {
|
|
154
|
+
await sleep(100);
|
|
155
|
+
nextBlocks = [...nextBlocks, getMockBlock(++currentBlockNumber)];
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
// kick off the background queueing of blocks
|
|
159
|
+
const newBlockPromise = newBlocks();
|
|
160
|
+
// kick off the synching
|
|
161
|
+
const syncPromise = server.start();
|
|
162
|
+
// await the synching
|
|
163
|
+
await syncPromise;
|
|
164
|
+
await newBlockPromise;
|
|
165
|
+
let status = await server.status();
|
|
166
|
+
expect(status.state).toEqual(WorldStateRunningState.RUNNING);
|
|
167
|
+
expect(status.syncedToL2Block).toEqual(LATEST_BLOCK_NUMBER);
|
|
168
|
+
await server.stop();
|
|
169
|
+
status = await server.status();
|
|
170
|
+
expect(status.state).toEqual(WorldStateRunningState.STOPPED);
|
|
171
|
+
expect(status.syncedToL2Block).toEqual(LATEST_BLOCK_NUMBER);
|
|
172
|
+
});
|
|
173
|
+
it('handles multiple calls to start', async () => {
|
|
174
|
+
const server = createSynchroniser(merkleTreeDb, rollupSource);
|
|
175
|
+
let currentBlockNumber = 0;
|
|
176
|
+
const newBlocks = async () => {
|
|
177
|
+
while (currentBlockNumber < LATEST_BLOCK_NUMBER) {
|
|
178
|
+
await sleep(100);
|
|
179
|
+
const newBlock = getMockBlock(++currentBlockNumber);
|
|
180
|
+
nextBlocks = [...nextBlocks, newBlock];
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
// kick off the background queueing of blocks
|
|
184
|
+
const newBlockPromise = newBlocks();
|
|
185
|
+
// kick off the synching
|
|
186
|
+
await server.start();
|
|
187
|
+
// call start again, should get back the same promise
|
|
188
|
+
await server.start();
|
|
189
|
+
// wait until the block production has finished
|
|
190
|
+
await newBlockPromise;
|
|
191
|
+
await server.stop();
|
|
192
|
+
});
|
|
193
|
+
it('immediately syncs if no new blocks', async () => {
|
|
194
|
+
const server = createSynchroniser(merkleTreeDb, rollupSource);
|
|
195
|
+
rollupSource.getBlockNumber.mockImplementationOnce(() => {
|
|
196
|
+
return Promise.resolve(0);
|
|
197
|
+
});
|
|
198
|
+
// kick off the synching
|
|
199
|
+
const syncPromise = server.start();
|
|
200
|
+
// it should already be synced, no need to push new blocks
|
|
201
|
+
await syncPromise;
|
|
202
|
+
const status = await server.status();
|
|
203
|
+
expect(status.state).toBe(WorldStateRunningState.RUNNING);
|
|
204
|
+
expect(status.syncedToL2Block).toBe(0);
|
|
205
|
+
await server.stop();
|
|
206
|
+
});
|
|
207
|
+
it("can't be started if already stopped", async () => {
|
|
208
|
+
const server = createSynchroniser(merkleTreeDb, rollupSource);
|
|
209
|
+
rollupSource.getBlockNumber.mockImplementationOnce(() => {
|
|
210
|
+
return Promise.resolve(0);
|
|
211
|
+
});
|
|
212
|
+
// kick off the synching
|
|
213
|
+
const syncPromise = server.start();
|
|
214
|
+
await syncPromise;
|
|
215
|
+
await server.stop();
|
|
216
|
+
await expect(server.start()).rejects.toThrow();
|
|
217
|
+
});
|
|
218
|
+
it('adds the received L2 blocks', async () => {
|
|
219
|
+
merkleTreeDb.handleL2Block.mockReset();
|
|
220
|
+
const server = createSynchroniser(merkleTreeDb, rollupSource);
|
|
221
|
+
const totalBlocks = LATEST_BLOCK_NUMBER + 1;
|
|
222
|
+
nextBlocks = Array(totalBlocks)
|
|
223
|
+
.fill(0)
|
|
224
|
+
.map((_, index) => getMockBlock(index, [Buffer.alloc(32, index)]));
|
|
225
|
+
// sync the server
|
|
226
|
+
await server.start();
|
|
227
|
+
expect(merkleTreeDb.handleL2Block).toHaveBeenCalledTimes(totalBlocks);
|
|
228
|
+
await server.stop();
|
|
229
|
+
});
|
|
230
|
+
it('can immediately sync to latest', async () => {
|
|
231
|
+
const server = createSynchroniser(merkleTreeDb, rollupSource, 10000);
|
|
232
|
+
await performInitialSync(server);
|
|
233
|
+
// the server should now be asleep for a long time
|
|
234
|
+
// we will add a new block and force an immediate sync
|
|
235
|
+
nextBlocks = [getMockBlock(LATEST_BLOCK_NUMBER + 1)];
|
|
236
|
+
await server.syncImmediate();
|
|
237
|
+
let status = await server.status();
|
|
238
|
+
expect(status.syncedToL2Block).toBe(LATEST_BLOCK_NUMBER + 1);
|
|
239
|
+
nextBlocks = [getMockBlock(LATEST_BLOCK_NUMBER + 2), getMockBlock(LATEST_BLOCK_NUMBER + 3)];
|
|
240
|
+
await server.syncImmediate();
|
|
241
|
+
status = await server.status();
|
|
242
|
+
expect(status.syncedToL2Block).toBe(LATEST_BLOCK_NUMBER + 3);
|
|
243
|
+
// stop the synchroniser
|
|
244
|
+
await server.stop();
|
|
245
|
+
// check the final status
|
|
246
|
+
status = await server.status();
|
|
247
|
+
expect(status.state).toEqual(WorldStateRunningState.STOPPED);
|
|
248
|
+
expect(status.syncedToL2Block).toEqual(LATEST_BLOCK_NUMBER + 3);
|
|
249
|
+
});
|
|
250
|
+
it('can immediately sync to a minimum block number', async () => {
|
|
251
|
+
const server = createSynchroniser(merkleTreeDb, rollupSource, 10000);
|
|
252
|
+
await performInitialSync(server);
|
|
253
|
+
// the server should now be asleep for a long time
|
|
254
|
+
// we will add 20 blocks and force a sync to at least LATEST + 5
|
|
255
|
+
nextBlocks = Array(20)
|
|
256
|
+
.fill(0)
|
|
257
|
+
.map((_, index) => getMockBlock(index + 1 + LATEST_BLOCK_NUMBER));
|
|
258
|
+
await server.syncImmediate(LATEST_BLOCK_NUMBER + 5);
|
|
259
|
+
// we should have synced all of the blocks
|
|
260
|
+
let status = await server.status();
|
|
261
|
+
expect(status.syncedToL2Block).toBe(LATEST_BLOCK_NUMBER + 20);
|
|
262
|
+
// stop the synchroniser
|
|
263
|
+
await server.stop();
|
|
264
|
+
// check the final status
|
|
265
|
+
status = await server.status();
|
|
266
|
+
expect(status.state).toEqual(WorldStateRunningState.STOPPED);
|
|
267
|
+
expect(status.syncedToL2Block).toEqual(LATEST_BLOCK_NUMBER + 20);
|
|
268
|
+
});
|
|
269
|
+
it('can immediately sync to a minimum block in the past', async () => {
|
|
270
|
+
const server = createSynchroniser(merkleTreeDb, rollupSource, 10000);
|
|
271
|
+
await performInitialSync(server);
|
|
272
|
+
// syncing to a block in the past should succeed
|
|
273
|
+
await server.syncImmediate(LATEST_BLOCK_NUMBER - 1);
|
|
274
|
+
// syncing to the current block should succeed
|
|
275
|
+
await server.syncImmediate(LATEST_BLOCK_NUMBER);
|
|
276
|
+
// we should have synced all of the blocks
|
|
277
|
+
let status = await server.status();
|
|
278
|
+
expect(status.syncedToL2Block).toBe(LATEST_BLOCK_NUMBER);
|
|
279
|
+
// stop the synchroniser
|
|
280
|
+
await server.stop();
|
|
281
|
+
// check the final status
|
|
282
|
+
status = await server.status();
|
|
283
|
+
expect(status.state).toEqual(WorldStateRunningState.STOPPED);
|
|
284
|
+
expect(status.syncedToL2Block).toEqual(LATEST_BLOCK_NUMBER);
|
|
285
|
+
});
|
|
286
|
+
it('throws if you try to sync to an unavailable block', async () => {
|
|
287
|
+
const server = createSynchroniser(merkleTreeDb, rollupSource, 10000);
|
|
288
|
+
await performInitialSync(server);
|
|
289
|
+
// the server should now be asleep for a long time
|
|
290
|
+
// we will add 2 blocks and force a sync to at least LATEST + 5
|
|
291
|
+
nextBlocks = Array(2)
|
|
292
|
+
.fill(0)
|
|
293
|
+
.map((_, index) => getMockBlock(index + 1 + LATEST_BLOCK_NUMBER));
|
|
294
|
+
await expect(server.syncImmediate(LATEST_BLOCK_NUMBER + 5)).rejects.toThrow(`Unable to sync to block number ${LATEST_BLOCK_NUMBER + 5}, currently synced to block ${LATEST_BLOCK_NUMBER + 2}`);
|
|
295
|
+
let status = await server.status();
|
|
296
|
+
expect(status.syncedToL2Block).toBe(LATEST_BLOCK_NUMBER + 2);
|
|
297
|
+
// stop the synchroniser
|
|
298
|
+
await server.stop();
|
|
299
|
+
// check the final status
|
|
300
|
+
status = await server.status();
|
|
301
|
+
expect(status.state).toEqual(WorldStateRunningState.STOPPED);
|
|
302
|
+
expect(status.syncedToL2Block).toEqual(LATEST_BLOCK_NUMBER + 2);
|
|
303
|
+
});
|
|
304
|
+
it('throws if you try to immediate sync when not running', async () => {
|
|
305
|
+
const server = createSynchroniser(merkleTreeDb, rollupSource, 10000);
|
|
306
|
+
// test initial state
|
|
307
|
+
const status = await server.status();
|
|
308
|
+
expect(status.syncedToL2Block).toEqual(0);
|
|
309
|
+
expect(status.state).toEqual(WorldStateRunningState.IDLE);
|
|
310
|
+
// create an initial block
|
|
311
|
+
nextBlocks = Array(LATEST_BLOCK_NUMBER)
|
|
312
|
+
.fill(0)
|
|
313
|
+
.map((_, index) => getMockBlock(index + 1));
|
|
314
|
+
await expect(server.syncImmediate()).rejects.toThrow(`World State is not running, unable to perform sync`);
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyX3dvcmxkX3N0YXRlX3N5bmNocm9uaXNlci50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N5bmNocm9uaXNlci9zZXJ2ZXJfd29ybGRfc3RhdGVfc3luY2hyb25pc2VyLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHNCQUFzQixFQUN0QixZQUFZLEVBQ1osRUFBRSxFQUNGLGVBQWUsRUFDZiwwQkFBMEIsRUFDMUIsd0JBQXdCLEVBQ3hCLDhCQUE4QixFQUM5Qix5QkFBeUIsRUFDekIsc0NBQXNDLEVBQ3RDLG1DQUFtQyxHQUNwQyxNQUFNLG9CQUFvQixDQUFDO0FBQzVCLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzFELE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNoRCxPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzVELE9BQU8sRUFDTCxZQUFZLEVBQ1osT0FBTyxFQUNQLGFBQWEsRUFFYixZQUFZLEVBQ1osZUFBZSxFQUNmLFdBQVcsR0FDWixNQUFNLGNBQWMsQ0FBQztBQUV0QixPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3JDLE9BQU8sS0FBSyxNQUFNLGNBQWMsQ0FBQztBQUdqQyxPQUFPLEVBQUUsNEJBQTRCLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUNwRixPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQVN2RSxNQUFNLG1CQUFtQixHQUFHLENBQUMsQ0FBQztBQUM5QixNQUFNLG9CQUFvQixHQUFHLEdBQUcsRUFBRSxDQUFDLG1CQUFtQixDQUFDO0FBQ3ZELElBQUksVUFBVSxHQUFjLEVBQUUsQ0FBQztBQUMvQixNQUFNLGlCQUFpQixHQUFHLEdBQUcsRUFBRTtJQUM3QixNQUFNLE1BQU0sR0FBRyxVQUFVLENB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
|
|
@@ -0,0 +1,59 @@
|
|
|
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
|
+
/**
|
|
29
|
+
* Starts the synchroniser.
|
|
30
|
+
* @returns A promise that resolves once the initial sync is completed.
|
|
31
|
+
*/
|
|
32
|
+
start(): void;
|
|
33
|
+
/**
|
|
34
|
+
* Returns the current status of the synchroniser.
|
|
35
|
+
* @returns The current status of the synchroniser.
|
|
36
|
+
*/
|
|
37
|
+
status(): Promise<WorldStateStatus>;
|
|
38
|
+
/**
|
|
39
|
+
* Stops the synchroniser.
|
|
40
|
+
*/
|
|
41
|
+
stop(): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Forces an immediate sync to an optionally provided minimum block number
|
|
44
|
+
* @param minBlockNumber - The minimum block number that we must sync to
|
|
45
|
+
* @returns A promise that resolves once the sync has completed.
|
|
46
|
+
*/
|
|
47
|
+
syncImmediate(minBlockNumber?: number): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Returns an instance of MerkleTreeOperations that will include uncommitted data.
|
|
50
|
+
* @returns An instance of MerkleTreeOperations that will include uncommitted data.
|
|
51
|
+
*/
|
|
52
|
+
getLatest(): MerkleTreeOperations;
|
|
53
|
+
/**
|
|
54
|
+
* Returns an instance of MerkleTreeOperations that will not include uncommitted data.
|
|
55
|
+
* @returns An instance of MerkleTreeOperations that will not include uncommitted data.
|
|
56
|
+
*/
|
|
57
|
+
getCommitted(): MerkleTreeOperations;
|
|
58
|
+
}
|
|
59
|
+
//# 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;;;OAGG;IACH,KAAK,IAAI,IAAI,CAAC;IAEd;;;OAGG;IACH,MAAM,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAEpC;;OAEG;IACH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtB;;;;OAIG;IACH,aAAa,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtD;;;OAGG;IACH,SAAS,IAAI,oBAAoB,CAAC;IAElC;;;OAGG;IACH,YAAY,IAAI,oBAAoB,CAAC;CACtC"}
|