@aztec/world-state 0.6.7 → 0.7.2

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 (35) hide show
  1. package/Dockerfile +18 -0
  2. package/package.json +5 -5
  3. package/src/synchroniser/server_world_state_synchroniser.test.ts +2 -2
  4. package/src/world-state-db/merkle_trees.ts +3 -3
  5. package/.tsbuildinfo +0 -1
  6. package/dest/index.d.ts +0 -5
  7. package/dest/index.d.ts.map +0 -1
  8. package/dest/index.js +0 -5
  9. package/dest/merkle-tree/merkle_tree_operations_facade.d.ts +0 -127
  10. package/dest/merkle-tree/merkle_tree_operations_facade.d.ts.map +0 -1
  11. package/dest/merkle-tree/merkle_tree_operations_facade.js +0 -147
  12. package/dest/synchroniser/config.d.ts +0 -19
  13. package/dest/synchroniser/config.d.ts.map +0 -1
  14. package/dest/synchroniser/config.js +0 -13
  15. package/dest/synchroniser/index.d.ts +0 -3
  16. package/dest/synchroniser/index.d.ts.map +0 -1
  17. package/dest/synchroniser/index.js +0 -3
  18. package/dest/synchroniser/server_world_state_synchroniser.d.ts +0 -55
  19. package/dest/synchroniser/server_world_state_synchroniser.d.ts.map +0 -1
  20. package/dest/synchroniser/server_world_state_synchroniser.js +0 -163
  21. package/dest/synchroniser/server_world_state_synchroniser.test.d.ts +0 -2
  22. package/dest/synchroniser/server_world_state_synchroniser.test.d.ts.map +0 -1
  23. package/dest/synchroniser/server_world_state_synchroniser.test.js +0 -317
  24. package/dest/synchroniser/world_state_synchroniser.d.ts +0 -59
  25. package/dest/synchroniser/world_state_synchroniser.d.ts.map +0 -1
  26. package/dest/synchroniser/world_state_synchroniser.js +0 -11
  27. package/dest/utils.d.ts +0 -18
  28. package/dest/utils.d.ts.map +0 -1
  29. package/dest/utils.js +0 -23
  30. package/dest/world-state-db/index.d.ts +0 -189
  31. package/dest/world-state-db/index.d.ts.map +0 -1
  32. package/dest/world-state-db/index.js +0 -31
  33. package/dest/world-state-db/merkle_trees.d.ts +0 -228
  34. package/dest/world-state-db/merkle_trees.d.ts.map +0 -1
  35. package/dest/world-state-db/merkle_trees.js +0 -407
@@ -1,317 +0,0 @@
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
- startL1ToL2MessageTreeSnapshot: getMockTreeSnapshot(),
45
- startHistoricBlocksTreeSnapshot: getMockTreeSnapshot(),
46
- endPrivateDataTreeSnapshot: getMockTreeSnapshot(),
47
- endNullifierTreeSnapshot: getMockTreeSnapshot(),
48
- endContractTreeSnapshot: getMockTreeSnapshot(),
49
- endPublicDataTreeRoot: Fr.random(),
50
- endL1ToL2MessageTreeSnapshot: 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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
@@ -1,59 +0,0 @@
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
@@ -1 +0,0 @@
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"}
@@ -1,11 +0,0 @@
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
package/dest/utils.d.ts DELETED
@@ -1,18 +0,0 @@
1
- import { GlobalVariables } from '@aztec/circuits.js';
2
- import { AztecAddress } from '@aztec/foundation/aztec-address';
3
- import { Fr } from '@aztec/foundation/fields';
4
- import { IWasmModule } from '@aztec/foundation/wasm';
5
- /**
6
- * Computes the index in the public data tree for a given contract and storage slot.
7
- * @param contract - Address of the contract who owns the storage.
8
- * @param slot - Slot within the contract storage.
9
- * @param bbWasm - Wasm module for computing the hash.
10
- * @returns The leaf index of the public data tree that maps to this storage slot.
11
- */
12
- export declare function computePublicDataTreeLeafIndex(contract: AztecAddress, slot: Fr, wasm: IWasmModule): bigint;
13
- /**
14
- * Computes the hash of the global variables.
15
- * @returns The hash of the global variables.
16
- */
17
- export declare function computeGlobalVariablesHash(globalVariables?: GlobalVariables): Promise<Fr>;
18
- //# sourceMappingURL=utils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGnF,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAE9C,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;AAED;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,eAAe,GAAE,eAAyC,GACzD,OAAO,CAAC,EAAE,CAAC,CAGb"}
package/dest/utils.js DELETED
@@ -1,23 +0,0 @@
1
- import { CircuitsWasm, GeneratorIndex, GlobalVariables } from '@aztec/circuits.js';
2
- import { computeGlobalsHash } from '@aztec/circuits.js/abis';
3
- import { pedersenCompressWithHashIndex } from '@aztec/circuits.js/barretenberg';
4
- import { toBigInt } from '@aztec/foundation/serialize';
5
- /**
6
- * Computes the index in the public data tree for a given contract and storage slot.
7
- * @param contract - Address of the contract who owns the storage.
8
- * @param slot - Slot within the contract storage.
9
- * @param bbWasm - Wasm module for computing the hash.
10
- * @returns The leaf index of the public data tree that maps to this storage slot.
11
- */
12
- export function computePublicDataTreeLeafIndex(contract, slot, wasm) {
13
- return toBigInt(pedersenCompressWithHashIndex(wasm, [contract, slot].map(f => f.toBuffer()), GeneratorIndex.PUBLIC_LEAF_INDEX));
14
- }
15
- /**
16
- * Computes the hash of the global variables.
17
- * @returns The hash of the global variables.
18
- */
19
- export async function computeGlobalVariablesHash(globalVariables = GlobalVariables.empty()) {
20
- const wasm = await CircuitsWasm.get();
21
- return computeGlobalsHash(wasm, globalVariables);
22
- }
23
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxjQUFjLEVBQUUsZUFBZSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDbkYsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDN0QsT0FBTyxFQUFFLDZCQUE2QixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFHaEYsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBR3ZEOzs7Ozs7R0FNRztBQUNILE1BQU0sVUFBVSw4QkFBOEIsQ0FBQyxRQUFzQixFQUFFLElBQVEsRUFBRSxJQUFpQjtJQUNoRyxPQUFPLFFBQVEsQ0FDYiw2QkFBNkIsQ0FDM0IsSUFBSSxFQUNKLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxFQUN2QyxjQUFjLENBQUMsaUJBQWlCLENBQ2pDLENBQ0YsQ0FBQztBQUNKLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLDBCQUEwQixDQUM5QyxrQkFBbUMsZUFBZSxDQUFDLEtBQUssRUFBRTtJQUUxRCxNQUFNLElBQUksR0FBRyxNQUFNLFlBQVksQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUN0QyxPQUFPLGtCQUFrQixDQUFDLElBQUksRUFBRSxlQUFlLENBQUMsQ0FBQztBQUNuRCxDQUFDIn0=