@aztec/world-state 0.0.1-commit.9b94fc1 → 0.0.1-commit.9badcec54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/instrumentation/instrumentation.d.ts +1 -1
- package/dest/instrumentation/instrumentation.d.ts.map +1 -1
- package/dest/instrumentation/instrumentation.js +17 -41
- package/dest/native/fork_checkpoint.d.ts +7 -1
- package/dest/native/fork_checkpoint.d.ts.map +1 -1
- package/dest/native/fork_checkpoint.js +15 -3
- package/dest/native/merkle_trees_facade.d.ts +15 -8
- package/dest/native/merkle_trees_facade.d.ts.map +1 -1
- package/dest/native/merkle_trees_facade.js +53 -15
- package/dest/native/message.d.ts +24 -15
- package/dest/native/message.d.ts.map +1 -1
- package/dest/native/message.js +14 -13
- package/dest/native/native_world_state.d.ts +19 -14
- package/dest/native/native_world_state.d.ts.map +1 -1
- package/dest/native/native_world_state.js +31 -21
- package/dest/native/native_world_state_instance.d.ts +5 -5
- package/dest/native/native_world_state_instance.d.ts.map +1 -1
- package/dest/native/native_world_state_instance.js +8 -7
- package/dest/native/world_state_ops_queue.js +5 -5
- package/dest/synchronizer/config.d.ts +3 -5
- package/dest/synchronizer/config.d.ts.map +1 -1
- package/dest/synchronizer/config.js +14 -16
- package/dest/synchronizer/factory.d.ts +6 -5
- package/dest/synchronizer/factory.d.ts.map +1 -1
- package/dest/synchronizer/factory.js +6 -5
- package/dest/synchronizer/server_world_state_synchronizer.d.ts +11 -17
- package/dest/synchronizer/server_world_state_synchronizer.d.ts.map +1 -1
- package/dest/synchronizer/server_world_state_synchronizer.js +162 -81
- package/dest/test/utils.d.ts +12 -5
- package/dest/test/utils.d.ts.map +1 -1
- package/dest/test/utils.js +54 -50
- package/dest/testing.d.ts +5 -4
- package/dest/testing.d.ts.map +1 -1
- package/dest/testing.js +11 -7
- package/dest/world-state-db/merkle_tree_db.d.ts +10 -20
- package/dest/world-state-db/merkle_tree_db.d.ts.map +1 -1
- package/package.json +12 -13
- package/src/instrumentation/instrumentation.ts +17 -41
- package/src/native/fork_checkpoint.ts +19 -3
- package/src/native/merkle_trees_facade.ts +62 -16
- package/src/native/message.ts +37 -26
- package/src/native/native_world_state.ts +52 -34
- package/src/native/native_world_state_instance.ts +14 -8
- package/src/native/world_state_ops_queue.ts +5 -5
- package/src/synchronizer/config.ts +15 -26
- package/src/synchronizer/factory.ts +13 -7
- package/src/synchronizer/server_world_state_synchronizer.ts +184 -106
- package/src/test/utils.ts +86 -91
- package/src/testing.ts +9 -10
- package/src/world-state-db/merkle_tree_db.ts +13 -24
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
import { EMPTY_GENESIS_DATA } from '@aztec/stdlib/world-state';
|
|
1
2
|
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
2
3
|
import { WorldStateInstrumentation } from '../instrumentation/instrumentation.js';
|
|
3
4
|
import { NativeWorldStateService } from '../native/native_world_state.js';
|
|
4
5
|
import { ServerWorldStateSynchronizer } from './server_world_state_synchronizer.js';
|
|
5
|
-
export async function createWorldStateSynchronizer(config, l2BlockSource,
|
|
6
|
+
export async function createWorldStateSynchronizer(config, l2BlockSource, genesis = EMPTY_GENESIS_DATA, client = getTelemetryClient(), bindings) {
|
|
6
7
|
const instrumentation = new WorldStateInstrumentation(client);
|
|
7
|
-
const merkleTrees = await createWorldState(config,
|
|
8
|
+
const merkleTrees = await createWorldState(config, genesis, instrumentation, bindings);
|
|
8
9
|
return new ServerWorldStateSynchronizer(merkleTrees, l2BlockSource, config, instrumentation);
|
|
9
10
|
}
|
|
10
|
-
export async function createWorldState(config,
|
|
11
|
+
export async function createWorldState(config, genesis = EMPTY_GENESIS_DATA, instrumentation = new WorldStateInstrumentation(getTelemetryClient()), bindings) {
|
|
11
12
|
const dataDirectory = config.worldStateDataDirectory ?? config.dataDirectory;
|
|
12
13
|
const dataStoreMapSizeKb = config.worldStateDbMapSizeKb ?? config.dataStoreMapSizeKb;
|
|
13
14
|
const wsTreeMapSizes = {
|
|
@@ -21,9 +22,9 @@ export async function createWorldState(config, prefilledPublicData = [], instrum
|
|
|
21
22
|
throw new Error('Rollup address is required to create a world state synchronizer.');
|
|
22
23
|
}
|
|
23
24
|
// If a data directory is provided in config, then create a persistent store.
|
|
24
|
-
const merkleTrees = dataDirectory ? await NativeWorldStateService.new(config.l1Contracts.rollupAddress, dataDirectory, wsTreeMapSizes,
|
|
25
|
+
const merkleTrees = dataDirectory ? await NativeWorldStateService.new(config.l1Contracts.rollupAddress, dataDirectory, wsTreeMapSizes, genesis, instrumentation, bindings) : await NativeWorldStateService.tmp(config.l1Contracts.rollupAddress, ![
|
|
25
26
|
'true',
|
|
26
27
|
'1'
|
|
27
|
-
].includes(process.env.DEBUG_WORLD_STATE),
|
|
28
|
+
].includes(process.env.DEBUG_WORLD_STATE), genesis, instrumentation, bindings);
|
|
28
29
|
return merkleTrees;
|
|
29
30
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import { type Logger } from '@aztec/foundation/log';
|
|
3
|
-
import type
|
|
3
|
+
import { type BlockHash, type L2BlockSource, L2BlockStream, type L2BlockStreamEvent, type L2BlockStreamEventHandler, type L2BlockStreamLocalDataProvider, type L2Tips } from '@aztec/stdlib/block';
|
|
4
4
|
import { type WorldStateSynchronizer, type WorldStateSynchronizerStatus } from '@aztec/stdlib/interfaces/server';
|
|
5
5
|
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
6
6
|
import type { SnapshotDataKeys } from '@aztec/stdlib/snapshots';
|
|
@@ -24,32 +24,33 @@ export declare class ServerWorldStateSynchronizer implements WorldStateSynchroni
|
|
|
24
24
|
private latestBlockNumberAtStart;
|
|
25
25
|
private historyToKeep;
|
|
26
26
|
private currentState;
|
|
27
|
-
private latestBlockHashQuery;
|
|
28
27
|
private syncPromise;
|
|
29
28
|
protected blockStream: L2BlockStream | undefined;
|
|
30
29
|
private provenBlockNumber;
|
|
31
30
|
constructor(merkleTreeDb: MerkleTreeAdminDatabase, l2BlockSource: L2BlockSource & L1ToL2MessageSource, config: WorldStateConfig, instrumentation?: WorldStateInstrumentation, log?: Logger);
|
|
32
31
|
getCommitted(): MerkleTreeReadOperations;
|
|
33
|
-
getSnapshot(blockNumber:
|
|
34
|
-
fork(blockNumber?:
|
|
32
|
+
getSnapshot(blockNumber: BlockNumber): MerkleTreeReadOperations;
|
|
33
|
+
fork(blockNumber?: BlockNumber, opts?: {
|
|
34
|
+
closeDelayMs?: number;
|
|
35
|
+
}): Promise<MerkleTreeWriteOperations>;
|
|
35
36
|
backupTo(dstPath: string, compact?: boolean): Promise<Record<Exclude<SnapshotDataKeys, 'archiver'>, string>>;
|
|
36
37
|
clear(): Promise<void>;
|
|
37
38
|
start(): Promise<void | import("@aztec/foundation/promise").PromiseWithResolvers<void>>;
|
|
38
39
|
protected createBlockStream(): L2BlockStream;
|
|
39
40
|
stop(): Promise<void>;
|
|
40
41
|
status(): Promise<WorldStateSynchronizerStatus>;
|
|
41
|
-
getLatestBlockNumber(): Promise<
|
|
42
|
+
getLatestBlockNumber(): Promise<BlockNumber>;
|
|
42
43
|
stopSync(): Promise<void>;
|
|
43
44
|
resumeSync(): void;
|
|
44
45
|
/**
|
|
45
46
|
* Forces an immediate sync.
|
|
46
47
|
* @param targetBlockNumber - The target block number that we must sync to. Will download unproven blocks if needed to reach it.
|
|
47
|
-
* @param
|
|
48
|
+
* @param blockHash - If provided, verifies the block at targetBlockNumber matches this hash. On mismatch, triggers a resync (reorg detection).
|
|
48
49
|
* @returns A promise that resolves with the block number the world state was synced to
|
|
49
50
|
*/
|
|
50
|
-
syncImmediate(targetBlockNumber?:
|
|
51
|
+
syncImmediate(targetBlockNumber?: BlockNumber, blockHash?: BlockHash): Promise<BlockNumber>;
|
|
51
52
|
/** Returns the L2 block hash for a given number. Used by the L2BlockStream for detecting reorgs. */
|
|
52
|
-
getL2BlockHash(number:
|
|
53
|
+
getL2BlockHash(number: BlockNumber): Promise<string | undefined>;
|
|
53
54
|
/** Returns the latest L2 block number for each tip of the chain (latest, proven, finalized). */
|
|
54
55
|
getL2Tips(): Promise<L2Tips>;
|
|
55
56
|
/** Handles an event emitted by the block stream. */
|
|
@@ -64,12 +65,5 @@ export declare class ServerWorldStateSynchronizer implements WorldStateSynchroni
|
|
|
64
65
|
* @param newState - New state value.
|
|
65
66
|
*/
|
|
66
67
|
private setCurrentState;
|
|
67
|
-
/**
|
|
68
|
-
* Verifies that the L1 to L2 messages hash to the block inHash.
|
|
69
|
-
* @param l1ToL2Messages - The L1 to L2 messages for the block.
|
|
70
|
-
* @param inHash - The inHash of the block.
|
|
71
|
-
* @throws If the L1 to L2 messages do not hash to the block inHash.
|
|
72
|
-
*/
|
|
73
|
-
protected verifyMessagesHashToInHash(l1ToL2Messages: Fr[], inHash: Fr): Promise<void>;
|
|
74
68
|
}
|
|
75
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
69
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyX3dvcmxkX3N0YXRlX3N5bmNocm9uaXplci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N5bmNocm9uaXplci9zZXJ2ZXJfd29ybGRfc3RhdGVfc3luY2hyb25pemVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxXQUFXLEVBQW9CLE1BQU0saUNBQWlDLENBQUM7QUFFaEYsT0FBTyxFQUFFLEtBQUssTUFBTSxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBR2xFLE9BQU8sRUFDTCxLQUFLLFNBQVMsRUFLZCxLQUFLLGFBQWEsRUFDbEIsYUFBYSxFQUNiLEtBQUssa0JBQWtCLEVBQ3ZCLEtBQUsseUJBQXlCLEVBQzlCLEtBQUssOEJBQThCLEVBQ25DLEtBQUssTUFBTSxFQUNaLE1BQU0scUJBQXFCLENBQUM7QUFDN0IsT0FBTyxFQUdMLEtBQUssc0JBQXNCLEVBQzNCLEtBQUssNEJBQTRCLEVBQ2xDLE1BQU0saUNBQWlDLENBQUM7QUFDekMsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNuRSxPQUFPLEtBQUssRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRWhFLE9BQU8sRUFBZ0IsS0FBSyx3QkFBd0IsRUFBRSxLQUFLLHlCQUF5QixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFHbEgsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFFbEYsT0FBTyxLQUFLLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUNuRixPQUFPLEtBQUssRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUdwRCxZQUFZLEVBQUUsZ0JBQWdCLEVBQUUsQ0FBQztBQUVqQzs7OztHQUlHO0FBQ0gscUJBQWEsNEJBQ1gsWUFBVyxzQkFBc0IsRUFBRSw4QkFBOEIsRUFBRSx5QkFBeUI7SUFnQjFGLE9BQU8sQ0FBQyxRQUFRLENBQUMsWUFBWTtJQUM3QixPQUFPLENBQUMsUUFBUSxDQUFDLGFBQWE7SUFDOUIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNO0lBQ3ZCLE9BQU8sQ0FBQyxlQUFlO0lBQ3ZCLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRztJQWxCdEIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxtQkFBbUIsQ0FBMkI7SUFFL0QsT0FBTyxDQUFDLHdCQUF3QixDQUFvQjtJQUNwRCxPQUFPLENBQUMsYUFBYSxDQUFxQjtJQUMxQyxPQUFPLENBQUMsWUFBWSxDQUF1RDtJQUUzRSxPQUFPLENBQUMsV0FBVyxDQUFnQztJQUNuRCxTQUFTLENBQUMsV0FBVyxFQUFFLGFBQWEsR0FBRyxTQUFTLENBQUM7SUFJakQsT0FBTyxDQUFDLGlCQUFpQixDQUEwQjtJQUVuRCxZQUNtQixZQUFZLEVBQUUsdUJBQXVCLEVBQ3JDLGFBQWEsRUFBRSxhQUFhLEdBQUcsbUJBQW1CLEVBQ2xELE1BQU0sRUFBRSxnQkFBZ0IsRUFDakMsZUFBZSw0QkFBc0QsRUFDNUQsR0FBRyxHQUFFLE1BQW9DLEVBUzNEO0lBRU0sWUFBWSxJQUFJLHdCQUF3QixDQUU5QztJQUVNLFdBQVcsQ0FBQyxXQUFXLEVBQUUsV0FBVyxHQUFHLHdCQUF3QixDQUVyRTtJQUVNLElBQUksQ0FBQyxXQUFXLENBQUMsRUFBRSxXQUFXLEVBQUUsSUFBSSxDQUFDLEVBQUU7UUFBRSxZQUFZLENBQUMsRUFBRSxNQUFNLENBQUE7S0FBRSxHQUFHLE9BQU8sQ0FBQyx5QkFBeUIsQ0FBQyxDQUUzRztJQUVNLFFBQVEsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxFQUFFLE9BQU8sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxVQUFVLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUVsSDtJQUVNLEtBQUssSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBRTVCO0lBRVksS0FBSyxtRkE0QmpCO0lBRUQsU0FBUyxDQUFDLGlCQUFpQixJQUFJLGFBQWEsQ0FPM0M7SUFFWSxJQUFJLGtCQU9oQjtJQUVZLE1BQU0sSUFBSSxPQUFPLENBQUMsNEJBQTRCLENBQUMsQ0FhM0Q7SUFFWSxvQkFBb0IseUJBRWhDO0lBRVksUUFBUSxrQkFJcEI7SUFFTSxVQUFVLFNBT2hCO0lBRUQ7Ozs7O09BS0c7SUFDVSxhQUFhLENBQUMsaUJBQWlCLENBQUMsRUFBRSxXQUFXLEVBQUUsU0FBUyxDQUFDLEVBQUUsU0FBUyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0EyRXZHO0lBRUQsb0dBQW9HO0lBQ3ZGLGNBQWMsQ0FBQyxNQUFNLEVBQUUsV0FBVyxHQUFHLE9BQU8sQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDLENBSzVFO0lBRUQsZ0dBQWdHO0lBQ25GLFNBQVMsSUFBSSxPQUFPLENBQUMsTUFBTSxDQUFDLENBdUN4QztJQUVELG9EQUFvRDtJQUN2QyxzQkFBc0IsQ0FBQyxLQUFLLEVBQUUsa0JBQWtCLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQWU1RTtZQU9hLGNBQWM7WUF5Q2QsYUFBYTtZQWtCYixvQkFBb0I7SUEwRGxDLE9BQU8sQ0FBQyxpQkFBaUI7WUFNWCxpQkFBaUI7SUFTL0I7OztPQUdHO0lBQ0gsT0FBTyxDQUFDLGVBQWU7Q0FJeEIifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server_world_state_synchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/server_world_state_synchronizer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server_world_state_synchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/server_world_state_synchronizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { INITIAL_CHECKPOINT_NUMBER, INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
|
|
2
|
+
import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
3
3
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import { promiseWithResolvers } from '@aztec/foundation/promise';
|
|
5
5
|
import { elapsed } from '@aztec/foundation/timer';
|
|
6
|
-
import {
|
|
6
|
+
import { GENESIS_BLOCK_HEADER_HASH, GENESIS_CHECKPOINT_HEADER_HASH, L2BlockStream } from '@aztec/stdlib/block';
|
|
7
7
|
import { WorldStateRunningState } from '@aztec/stdlib/interfaces/server';
|
|
8
8
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
9
|
-
import {
|
|
9
|
+
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
10
10
|
import { WorldStateInstrumentation } from '../instrumentation/instrumentation.js';
|
|
11
11
|
import { WorldStateSynchronizerError } from './errors.js';
|
|
12
12
|
/**
|
|
@@ -23,7 +23,6 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
23
23
|
latestBlockNumberAtStart;
|
|
24
24
|
historyToKeep;
|
|
25
25
|
currentState;
|
|
26
|
-
latestBlockHashQuery;
|
|
27
26
|
syncPromise;
|
|
28
27
|
blockStream;
|
|
29
28
|
// WorldState doesn't track the proven block number, it only tracks the latest tips of the pending chain and the finalized chain
|
|
@@ -35,12 +34,11 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
35
34
|
this.config = config;
|
|
36
35
|
this.instrumentation = instrumentation;
|
|
37
36
|
this.log = log;
|
|
38
|
-
this.latestBlockNumberAtStart =
|
|
37
|
+
this.latestBlockNumberAtStart = BlockNumber.ZERO;
|
|
39
38
|
this.currentState = WorldStateRunningState.IDLE;
|
|
40
|
-
this.latestBlockHashQuery = undefined;
|
|
41
39
|
this.syncPromise = promiseWithResolvers();
|
|
42
40
|
this.merkleTreeCommitted = this.merkleTreeDb.getCommitted();
|
|
43
|
-
this.historyToKeep = config.
|
|
41
|
+
this.historyToKeep = config.worldStateCheckpointHistory < 1 ? undefined : config.worldStateCheckpointHistory;
|
|
44
42
|
this.log.info(`Created world state synchroniser with block history of ${this.historyToKeep === undefined ? 'infinity' : this.historyToKeep}`);
|
|
45
43
|
}
|
|
46
44
|
getCommitted() {
|
|
@@ -49,8 +47,8 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
49
47
|
getSnapshot(blockNumber) {
|
|
50
48
|
return this.merkleTreeDb.getSnapshot(blockNumber);
|
|
51
49
|
}
|
|
52
|
-
fork(blockNumber) {
|
|
53
|
-
return this.merkleTreeDb.fork(blockNumber);
|
|
50
|
+
fork(blockNumber, opts) {
|
|
51
|
+
return this.merkleTreeDb.fork(blockNumber, opts);
|
|
54
52
|
}
|
|
55
53
|
backupTo(dstPath, compact) {
|
|
56
54
|
return this.merkleTreeDb.backupTo(dstPath, compact);
|
|
@@ -66,7 +64,7 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
66
64
|
return this.syncPromise;
|
|
67
65
|
}
|
|
68
66
|
// Get the current latest block number
|
|
69
|
-
this.latestBlockNumberAtStart = await
|
|
67
|
+
this.latestBlockNumberAtStart = BlockNumber(await this.l2BlockSource.getBlockNumber());
|
|
70
68
|
const blockToDownloadFrom = await this.getLatestBlockNumber() + 1;
|
|
71
69
|
if (blockToDownloadFrom <= this.latestBlockNumberAtStart) {
|
|
72
70
|
// If there are blocks to be retrieved, go to a synching state
|
|
@@ -84,12 +82,11 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
84
82
|
return this.syncPromise.promise;
|
|
85
83
|
}
|
|
86
84
|
createBlockStream() {
|
|
87
|
-
const tracer = this.instrumentation.telemetry.getTracer('WorldStateL2BlockStream');
|
|
88
85
|
const logger = createLogger('world-state:block_stream');
|
|
89
|
-
return new
|
|
90
|
-
proven: this.config.worldStateProvenBlocksOnly,
|
|
86
|
+
return new L2BlockStream(this.l2BlockSource, this, this, logger, {
|
|
91
87
|
pollIntervalMS: this.config.worldStateBlockCheckIntervalMS,
|
|
92
|
-
batchSize: this.config.worldStateBlockRequestBatchSize
|
|
88
|
+
batchSize: this.config.worldStateBlockRequestBatchSize,
|
|
89
|
+
ignoreCheckpoints: true
|
|
93
90
|
});
|
|
94
91
|
}
|
|
95
92
|
async stop() {
|
|
@@ -103,10 +100,10 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
103
100
|
async status() {
|
|
104
101
|
const summary = await this.merkleTreeDb.getStatusSummary();
|
|
105
102
|
const status = {
|
|
106
|
-
latestBlockNumber:
|
|
107
|
-
latestBlockHash: await this.getL2BlockHash(
|
|
108
|
-
finalizedBlockNumber:
|
|
109
|
-
oldestHistoricBlockNumber:
|
|
103
|
+
latestBlockNumber: summary.unfinalizedBlockNumber,
|
|
104
|
+
latestBlockHash: await this.getL2BlockHash(summary.unfinalizedBlockNumber) ?? '',
|
|
105
|
+
finalizedBlockNumber: summary.finalizedBlockNumber,
|
|
106
|
+
oldestHistoricBlockNumber: summary.oldestHistoricalBlock,
|
|
110
107
|
treesAreSynched: summary.treesAreSynched
|
|
111
108
|
};
|
|
112
109
|
return {
|
|
@@ -115,7 +112,7 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
115
112
|
};
|
|
116
113
|
}
|
|
117
114
|
async getLatestBlockNumber() {
|
|
118
|
-
return (await this.getL2Tips()).
|
|
115
|
+
return (await this.getL2Tips()).proposed.number;
|
|
119
116
|
}
|
|
120
117
|
async stopSync() {
|
|
121
118
|
this.log.debug('Stopping sync...');
|
|
@@ -133,9 +130,9 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
133
130
|
/**
|
|
134
131
|
* Forces an immediate sync.
|
|
135
132
|
* @param targetBlockNumber - The target block number that we must sync to. Will download unproven blocks if needed to reach it.
|
|
136
|
-
* @param
|
|
133
|
+
* @param blockHash - If provided, verifies the block at targetBlockNumber matches this hash. On mismatch, triggers a resync (reorg detection).
|
|
137
134
|
* @returns A promise that resolves with the block number the world state was synced to
|
|
138
|
-
*/ async syncImmediate(targetBlockNumber,
|
|
135
|
+
*/ async syncImmediate(targetBlockNumber, blockHash) {
|
|
139
136
|
if (this.currentState !== WorldStateRunningState.RUNNING) {
|
|
140
137
|
throw new Error(`World State is not running. Unable to perform sync.`);
|
|
141
138
|
}
|
|
@@ -145,12 +142,21 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
145
142
|
// If we have been given a block number to sync to and we have reached that number then return
|
|
146
143
|
const currentBlockNumber = await this.getLatestBlockNumber();
|
|
147
144
|
if (targetBlockNumber !== undefined && targetBlockNumber <= currentBlockNumber) {
|
|
148
|
-
|
|
145
|
+
if (blockHash === undefined) {
|
|
146
|
+
return currentBlockNumber;
|
|
147
|
+
}
|
|
148
|
+
// If a block hash was provided, verify we're on the expected fork
|
|
149
|
+
const currentHash = await this.getL2BlockHash(targetBlockNumber);
|
|
150
|
+
if (currentHash === blockHash.toString()) {
|
|
151
|
+
return currentBlockNumber;
|
|
152
|
+
}
|
|
153
|
+
// Hash mismatch: a reorg may have occurred, fall through to trigger sync
|
|
154
|
+
this.log.debug(`World state block hash mismatch at ${targetBlockNumber} (expected ${blockHash}, got ${currentHash}). Triggering resync.`);
|
|
149
155
|
}
|
|
150
156
|
this.log.debug(`World State at ${currentBlockNumber} told to sync to ${targetBlockNumber ?? 'latest'}`);
|
|
151
157
|
// If the archiver is behind the target block, force an archiver sync
|
|
152
158
|
if (targetBlockNumber) {
|
|
153
|
-
const archiverLatestBlock = await this.l2BlockSource.getBlockNumber();
|
|
159
|
+
const archiverLatestBlock = BlockNumber(await this.l2BlockSource.getBlockNumber());
|
|
154
160
|
if (archiverLatestBlock < targetBlockNumber) {
|
|
155
161
|
this.log.debug(`Archiver is at ${archiverLatestBlock} behind target block ${targetBlockNumber}.`);
|
|
156
162
|
await this.l2BlockSource.syncImmediate();
|
|
@@ -160,7 +166,7 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
160
166
|
await this.blockStream.sync();
|
|
161
167
|
// If we have been given a block number to sync to and we have not reached that number then fail
|
|
162
168
|
const updatedBlockNumber = await this.getLatestBlockNumber();
|
|
163
|
-
if (
|
|
169
|
+
if (targetBlockNumber !== undefined && targetBlockNumber > updatedBlockNumber) {
|
|
164
170
|
throw new WorldStateSynchronizerError(`Unable to sync to block number ${targetBlockNumber} (last synced is ${updatedBlockNumber})`, {
|
|
165
171
|
cause: {
|
|
166
172
|
reason: 'block_not_available',
|
|
@@ -170,43 +176,95 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
170
176
|
}
|
|
171
177
|
});
|
|
172
178
|
}
|
|
179
|
+
// If a block hash was provided, verify we're on the expected fork after syncing, throw otherwise
|
|
180
|
+
if (blockHash !== undefined && targetBlockNumber !== undefined) {
|
|
181
|
+
const updatedHash = await this.getL2BlockHash(targetBlockNumber);
|
|
182
|
+
if (updatedHash !== blockHash.toString()) {
|
|
183
|
+
throw new WorldStateSynchronizerError(`Block hash mismatch at block ${targetBlockNumber} (expected ${blockHash} but got ${updatedHash})`, {
|
|
184
|
+
cause: {
|
|
185
|
+
reason: 'block_hash_mismatch',
|
|
186
|
+
targetBlockNumber,
|
|
187
|
+
expectedHash: blockHash.toString(),
|
|
188
|
+
actualHash: updatedHash
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
}
|
|
173
193
|
return updatedBlockNumber;
|
|
174
194
|
}
|
|
175
195
|
/** Returns the L2 block hash for a given number. Used by the L2BlockStream for detecting reorgs. */ async getL2BlockHash(number) {
|
|
176
|
-
if (number ===
|
|
196
|
+
if (number === BlockNumber.ZERO) {
|
|
177
197
|
return (await this.merkleTreeCommitted.getInitialHeader().hash()).toString();
|
|
178
198
|
}
|
|
179
|
-
|
|
180
|
-
this.latestBlockHashQuery = {
|
|
181
|
-
hash: await this.merkleTreeCommitted.getLeafValue(MerkleTreeId.ARCHIVE, BigInt(number)).then((leaf)=>leaf?.toString()),
|
|
182
|
-
blockNumber: number
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
return this.latestBlockHashQuery.hash;
|
|
199
|
+
return this.merkleTreeCommitted.getLeafValue(MerkleTreeId.ARCHIVE, BigInt(number)).then((leaf)=>leaf?.toString());
|
|
186
200
|
}
|
|
187
201
|
/** Returns the latest L2 block number for each tip of the chain (latest, proven, finalized). */ async getL2Tips() {
|
|
188
202
|
const status = await this.merkleTreeDb.getStatusSummary();
|
|
189
|
-
const
|
|
203
|
+
const unfinalizedBlockHashPromise = this.getL2BlockHash(status.unfinalizedBlockNumber);
|
|
204
|
+
const finalizedBlockHashPromise = this.getL2BlockHash(status.finalizedBlockNumber);
|
|
205
|
+
const provenBlockNumber = this.provenBlockNumber ?? status.finalizedBlockNumber;
|
|
206
|
+
const provenBlockHashPromise = this.provenBlockNumber === undefined ? finalizedBlockHashPromise : this.getL2BlockHash(this.provenBlockNumber);
|
|
207
|
+
const [unfinalizedBlockHash, finalizedBlockHash, provenBlockHash] = await Promise.all([
|
|
208
|
+
unfinalizedBlockHashPromise,
|
|
209
|
+
finalizedBlockHashPromise,
|
|
210
|
+
provenBlockHashPromise
|
|
211
|
+
]);
|
|
190
212
|
const latestBlockId = {
|
|
191
|
-
number:
|
|
213
|
+
number: status.unfinalizedBlockNumber,
|
|
192
214
|
hash: unfinalizedBlockHash
|
|
193
215
|
};
|
|
216
|
+
// World state doesn't track checkpointed blocks or checkpoints themselves.
|
|
217
|
+
// but we use a block stream so we need to provide 'local' L2Tips.
|
|
218
|
+
// We configure the block stream to ignore checkpoints and set checkpoint values to genesis here.
|
|
219
|
+
const genesisCheckpointHeaderHash = GENESIS_CHECKPOINT_HEADER_HASH.toString();
|
|
194
220
|
return {
|
|
195
|
-
|
|
221
|
+
proposed: latestBlockId,
|
|
222
|
+
checkpointed: {
|
|
223
|
+
block: {
|
|
224
|
+
number: INITIAL_L2_BLOCK_NUM,
|
|
225
|
+
hash: GENESIS_BLOCK_HEADER_HASH.toString()
|
|
226
|
+
},
|
|
227
|
+
checkpoint: {
|
|
228
|
+
number: INITIAL_CHECKPOINT_NUMBER,
|
|
229
|
+
hash: genesisCheckpointHeaderHash
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
proposedCheckpoint: {
|
|
233
|
+
block: {
|
|
234
|
+
number: INITIAL_L2_BLOCK_NUM,
|
|
235
|
+
hash: GENESIS_BLOCK_HEADER_HASH.toString()
|
|
236
|
+
},
|
|
237
|
+
checkpoint: {
|
|
238
|
+
number: INITIAL_CHECKPOINT_NUMBER,
|
|
239
|
+
hash: genesisCheckpointHeaderHash
|
|
240
|
+
}
|
|
241
|
+
},
|
|
196
242
|
finalized: {
|
|
197
|
-
|
|
198
|
-
|
|
243
|
+
block: {
|
|
244
|
+
number: status.finalizedBlockNumber,
|
|
245
|
+
hash: finalizedBlockHash ?? ''
|
|
246
|
+
},
|
|
247
|
+
checkpoint: {
|
|
248
|
+
number: INITIAL_CHECKPOINT_NUMBER,
|
|
249
|
+
hash: genesisCheckpointHeaderHash
|
|
250
|
+
}
|
|
199
251
|
},
|
|
200
252
|
proven: {
|
|
201
|
-
|
|
202
|
-
|
|
253
|
+
block: {
|
|
254
|
+
number: provenBlockNumber,
|
|
255
|
+
hash: provenBlockHash ?? ''
|
|
256
|
+
},
|
|
257
|
+
checkpoint: {
|
|
258
|
+
number: INITIAL_CHECKPOINT_NUMBER,
|
|
259
|
+
hash: genesisCheckpointHeaderHash
|
|
260
|
+
}
|
|
203
261
|
}
|
|
204
262
|
};
|
|
205
263
|
}
|
|
206
264
|
/** Handles an event emitted by the block stream. */ async handleBlockStreamEvent(event) {
|
|
207
265
|
switch(event.type){
|
|
208
266
|
case 'blocks-added':
|
|
209
|
-
await this.handleL2Blocks(event.blocks
|
|
267
|
+
await this.handleL2Blocks(event.blocks);
|
|
210
268
|
break;
|
|
211
269
|
case 'chain-pruned':
|
|
212
270
|
await this.handleChainPruned(event.block.number);
|
|
@@ -224,19 +282,23 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
224
282
|
* @param l2Blocks - The L2 blocks to handle.
|
|
225
283
|
* @returns Whether the block handled was produced by this same node.
|
|
226
284
|
*/ async handleL2Blocks(l2Blocks) {
|
|
227
|
-
this.log.
|
|
228
|
-
|
|
229
|
-
const
|
|
285
|
+
this.log.debug(`Handling L2 blocks ${l2Blocks[0].number} to ${l2Blocks.at(-1).number}`);
|
|
286
|
+
// Fetch the L1->L2 messages for the first block in a checkpoint.
|
|
287
|
+
const messagesForBlocks = new Map();
|
|
288
|
+
await Promise.all(l2Blocks.filter((b)=>b.indexWithinCheckpoint === 0).map(async (block)=>{
|
|
289
|
+
const l1ToL2Messages = await this.l2BlockSource.getL1ToL2Messages(block.checkpointNumber);
|
|
290
|
+
messagesForBlocks.set(block.number, l1ToL2Messages);
|
|
291
|
+
}));
|
|
230
292
|
let updateStatus = undefined;
|
|
231
|
-
for(
|
|
232
|
-
const [duration, result] = await elapsed(()=>this.handleL2Block(
|
|
233
|
-
this.log.info(`World state updated with L2 block ${
|
|
293
|
+
for (const block of l2Blocks){
|
|
294
|
+
const [duration, result] = await elapsed(()=>this.handleL2Block(block, messagesForBlocks.get(block.number) ?? []));
|
|
295
|
+
this.log.info(`World state updated with L2 block ${block.number}`, {
|
|
234
296
|
eventName: 'l2-block-handled',
|
|
235
297
|
duration,
|
|
236
|
-
unfinalizedBlockNumber: result.summary.unfinalizedBlockNumber,
|
|
237
|
-
finalizedBlockNumber: result.summary.finalizedBlockNumber,
|
|
238
|
-
oldestHistoricBlock: result.summary.oldestHistoricalBlock,
|
|
239
|
-
...
|
|
298
|
+
unfinalizedBlockNumber: BigInt(result.summary.unfinalizedBlockNumber),
|
|
299
|
+
finalizedBlockNumber: BigInt(result.summary.finalizedBlockNumber),
|
|
300
|
+
oldestHistoricBlock: BigInt(result.summary.oldestHistoricalBlock),
|
|
301
|
+
...block.getStats()
|
|
240
302
|
});
|
|
241
303
|
updateStatus = result;
|
|
242
304
|
}
|
|
@@ -251,16 +313,12 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
251
313
|
* @param l1ToL2Messages - The L1 to L2 messages for the block.
|
|
252
314
|
* @returns Whether the block handled was produced by this same node.
|
|
253
315
|
*/ async handleL2Block(l2Block, l1ToL2Messages) {
|
|
254
|
-
|
|
255
|
-
// Note that we cannot optimize this check by checking the root of the subtree after inserting the messages
|
|
256
|
-
// to the real L1_TO_L2_MESSAGE_TREE (like we do in merkleTreeDb.handleL2BlockAndMessages(...)) because that
|
|
257
|
-
// tree uses pedersen and we don't have access to the converted root.
|
|
258
|
-
await this.verifyMessagesHashToInHash(l1ToL2Messages, l2Block.header.contentCommitment.inHash);
|
|
259
|
-
// If the above check succeeds, we can proceed to handle the block.
|
|
260
|
-
this.log.trace(`Pushing L2 block ${l2Block.number} to merkle tree db `, {
|
|
316
|
+
this.log.debug(`Pushing L2 block ${l2Block.number} to merkle tree db `, {
|
|
261
317
|
blockNumber: l2Block.number,
|
|
262
318
|
blockHash: await l2Block.hash().then((h)=>h.toString()),
|
|
263
|
-
l1ToL2Messages: l1ToL2Messages.map((msg)=>msg.toString())
|
|
319
|
+
l1ToL2Messages: l1ToL2Messages.map((msg)=>msg.toString()),
|
|
320
|
+
blockHeader: l2Block.header.toInspect(),
|
|
321
|
+
blockStats: l2Block.getStats()
|
|
264
322
|
});
|
|
265
323
|
const result = await this.merkleTreeDb.handleL2BlockAndMessages(l2Block, l1ToL2Messages);
|
|
266
324
|
if (this.currentState === WorldStateRunningState.SYNCHING && l2Block.number >= this.latestBlockNumberAtStart) {
|
|
@@ -271,28 +329,63 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
271
329
|
}
|
|
272
330
|
async handleChainFinalized(blockNumber) {
|
|
273
331
|
this.log.verbose(`Finalized chain is now at block ${blockNumber}`);
|
|
274
|
-
|
|
332
|
+
// If the finalized block number is older than the oldest available block in world state,
|
|
333
|
+
// skip entirely. The finalized block number can jump backwards (e.g. when the finalization
|
|
334
|
+
// heuristic changes) and try to read block data that has already been pruned. When this
|
|
335
|
+
// happens, there is nothing useful to do — the native world state is already finalized
|
|
336
|
+
// past this point and pruning has already happened.
|
|
337
|
+
const currentSummary = await this.merkleTreeDb.getStatusSummary();
|
|
338
|
+
if (blockNumber < currentSummary.oldestHistoricalBlock || blockNumber < 1) {
|
|
339
|
+
this.log.trace(`Finalized block ${blockNumber} is older than the oldest available block ${currentSummary.oldestHistoricalBlock}. Skipping.`);
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
const summary = await this.merkleTreeDb.setFinalized(blockNumber);
|
|
275
343
|
if (this.historyToKeep === undefined) {
|
|
276
344
|
return;
|
|
277
345
|
}
|
|
278
|
-
|
|
279
|
-
|
|
346
|
+
// Get the checkpointed block for the finalized block number
|
|
347
|
+
const finalisedCheckpoint = await this.l2BlockSource.getCheckpointedBlock(summary.finalizedBlockNumber);
|
|
348
|
+
if (finalisedCheckpoint === undefined) {
|
|
349
|
+
this.log.warn(`Failed to retrieve checkpointed block for finalized block number: ${summary.finalizedBlockNumber}`);
|
|
280
350
|
return;
|
|
281
351
|
}
|
|
282
|
-
|
|
283
|
-
const
|
|
352
|
+
// Compute the required historic checkpoint number
|
|
353
|
+
const newHistoricCheckpointNumber = finalisedCheckpoint.checkpointNumber - this.historyToKeep + 1;
|
|
354
|
+
if (newHistoricCheckpointNumber <= 1) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
// Retrieve the historic checkpoint
|
|
358
|
+
const historicCheckpoints = await this.l2BlockSource.getCheckpoints(CheckpointNumber(newHistoricCheckpointNumber), 1);
|
|
359
|
+
if (historicCheckpoints.length === 0 || historicCheckpoints[0] === undefined) {
|
|
360
|
+
this.log.warn(`Failed to retrieve checkpoint number ${newHistoricCheckpointNumber} from Archiver`);
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
const historicCheckpoint = historicCheckpoints[0];
|
|
364
|
+
if (historicCheckpoint.checkpoint.blocks.length === 0 || historicCheckpoint.checkpoint.blocks[0] === undefined) {
|
|
365
|
+
this.log.warn(`Retrieved checkpoint number ${newHistoricCheckpointNumber} has no blocks!`);
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
// Find the block at the start of the checkpoint and remove blocks up to this one
|
|
369
|
+
const newHistoricBlock = historicCheckpoint.checkpoint.blocks[0];
|
|
370
|
+
if (newHistoricBlock.number <= currentSummary.oldestHistoricalBlock) {
|
|
371
|
+
this.log.debug(`Historic block ${newHistoricBlock.number} is not newer than oldest available ${currentSummary.oldestHistoricalBlock}. Skipping prune.`);
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
this.log.verbose(`Pruning historic blocks to ${newHistoricBlock.number}`);
|
|
375
|
+
const status = await this.merkleTreeDb.removeHistoricalBlocks(BlockNumber(newHistoricBlock.number));
|
|
284
376
|
this.log.debug(`World state summary `, status.summary);
|
|
285
377
|
}
|
|
286
378
|
handleChainProven(blockNumber) {
|
|
287
|
-
this.provenBlockNumber =
|
|
379
|
+
this.provenBlockNumber = blockNumber;
|
|
288
380
|
this.log.debug(`Proven chain is now at block ${blockNumber}`);
|
|
289
381
|
return Promise.resolve();
|
|
290
382
|
}
|
|
291
383
|
async handleChainPruned(blockNumber) {
|
|
292
|
-
this.log.
|
|
293
|
-
const status = await this.merkleTreeDb.unwindBlocks(
|
|
294
|
-
this.
|
|
295
|
-
|
|
384
|
+
this.log.info(`Chain pruned to block ${blockNumber}`);
|
|
385
|
+
const status = await this.merkleTreeDb.unwindBlocks(blockNumber);
|
|
386
|
+
if (this.provenBlockNumber !== undefined && this.provenBlockNumber > blockNumber) {
|
|
387
|
+
this.provenBlockNumber = undefined;
|
|
388
|
+
}
|
|
296
389
|
this.instrumentation.updateWorldStateMetrics(status);
|
|
297
390
|
}
|
|
298
391
|
/**
|
|
@@ -302,16 +395,4 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
302
395
|
this.currentState = newState;
|
|
303
396
|
this.log.debug(`Moved to state ${WorldStateRunningState[this.currentState]}`);
|
|
304
397
|
}
|
|
305
|
-
/**
|
|
306
|
-
* Verifies that the L1 to L2 messages hash to the block inHash.
|
|
307
|
-
* @param l1ToL2Messages - The L1 to L2 messages for the block.
|
|
308
|
-
* @param inHash - The inHash of the block.
|
|
309
|
-
* @throws If the L1 to L2 messages do not hash to the block inHash.
|
|
310
|
-
*/ async verifyMessagesHashToInHash(l1ToL2Messages, inHash) {
|
|
311
|
-
const treeCalculator = await MerkleTreeCalculator.create(L1_TO_L2_MSG_SUBTREE_HEIGHT, Buffer.alloc(32), (lhs, rhs)=>Promise.resolve(new SHA256Trunc().hash(lhs, rhs)));
|
|
312
|
-
const root = await treeCalculator.computeTreeRoot(l1ToL2Messages.map((msg)=>msg.toBuffer()));
|
|
313
|
-
if (!root.equals(inHash.toBuffer())) {
|
|
314
|
-
throw new Error('Obtained L1 to L2 messages failed to be hashed to the block inHash');
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
398
|
}
|
package/dest/test/utils.d.ts
CHANGED
|
@@ -1,19 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BlockNumber, type CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
2
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
3
|
import { L2Block } from '@aztec/stdlib/block';
|
|
3
4
|
import type { MerkleTreeReadOperations, MerkleTreeWriteOperations } from '@aztec/stdlib/interfaces/server';
|
|
5
|
+
import { mockCheckpointAndMessages } from '@aztec/stdlib/testing';
|
|
4
6
|
import type { NativeWorldStateService } from '../native/native_world_state.js';
|
|
5
|
-
export declare function
|
|
7
|
+
export declare function updateBlockState(block: L2Block, l1ToL2Messages: Fr[], fork: MerkleTreeWriteOperations): Promise<void>;
|
|
8
|
+
export declare function mockBlock(blockNum: BlockNumber, size: number, fork: MerkleTreeWriteOperations, maxEffects?: number | undefined, numL1ToL2Messages?: number, isFirstBlockInCheckpoint?: boolean): Promise<{
|
|
6
9
|
block: L2Block;
|
|
7
10
|
messages: Fr[];
|
|
8
11
|
}>;
|
|
9
|
-
export declare function mockEmptyBlock(blockNum:
|
|
12
|
+
export declare function mockEmptyBlock(blockNum: BlockNumber, fork: MerkleTreeWriteOperations): Promise<{
|
|
10
13
|
block: L2Block;
|
|
11
14
|
messages: Fr[];
|
|
12
15
|
}>;
|
|
13
|
-
export declare function mockBlocks(from:
|
|
16
|
+
export declare function mockBlocks(from: BlockNumber, count: number, numTxs: number, worldState: NativeWorldStateService): Promise<{
|
|
14
17
|
blocks: L2Block[];
|
|
15
18
|
messages: Fr[][];
|
|
16
19
|
}>;
|
|
20
|
+
export declare function mockCheckpoint(checkpointNumber: CheckpointNumber, fork: MerkleTreeWriteOperations, options?: Partial<Parameters<typeof mockCheckpointAndMessages>[1]>): Promise<{
|
|
21
|
+
checkpoint: import("@aztec/stdlib/checkpoint").Checkpoint;
|
|
22
|
+
messages: Fr[];
|
|
23
|
+
}>;
|
|
17
24
|
export declare function assertSameState(forkA: MerkleTreeReadOperations, forkB: MerkleTreeReadOperations): Promise<void>;
|
|
18
25
|
export declare function compareChains(left: MerkleTreeReadOperations, right: MerkleTreeReadOperations): Promise<void>;
|
|
19
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
26
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0L3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQU9BLE9BQU8sRUFBRSxXQUFXLEVBQUUsS0FBSyxnQkFBZ0IsRUFBeUIsTUFBTSxpQ0FBaUMsQ0FBQztBQUU1RyxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDcEQsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzlDLE9BQU8sS0FBSyxFQUVWLHdCQUF3QixFQUN4Qix5QkFBeUIsRUFDMUIsTUFBTSxpQ0FBaUMsQ0FBQztBQUN6QyxPQUFPLEVBQUUseUJBQXlCLEVBQXNCLE1BQU0sdUJBQXVCLENBQUM7QUFJdEYsT0FBTyxLQUFLLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUUvRSx3QkFBc0IsZ0JBQWdCLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxjQUFjLEVBQUUsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLHlCQUF5QixpQkE4QzNHO0FBRUQsd0JBQXNCLFNBQVMsQ0FDN0IsUUFBUSxFQUFFLFdBQVcsRUFDckIsSUFBSSxFQUFFLE1BQU0sRUFDWixJQUFJLEVBQUUseUJBQXlCLEVBQy9CLFVBQVUsR0FBRSxNQUFNLEdBQUcsU0FBZ0IsRUFDckMsaUJBQWlCLEdBQUUsTUFBNEMsRUFDL0Qsd0JBQXdCLEdBQUUsT0FBYzs7O0dBZXpDO0FBRUQsd0JBQXNCLGNBQWMsQ0FBQyxRQUFRLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSx5QkFBeUI7OztHQVkxRjtBQUVELHdCQUFzQixVQUFVLENBQzlCLElBQUksRUFBRSxXQUFXLEVBQ2pCLEtBQUssRUFBRSxNQUFNLEVBQ2IsTUFBTSxFQUFFLE1BQU0sRUFDZCxVQUFVLEVBQUUsdUJBQXVCOzs7R0FlcEM7QUFFRCx3QkFBc0IsY0FBYyxDQUNsQyxnQkFBZ0IsRUFBRSxnQkFBZ0IsRUFDbEMsSUFBSSxFQUFFLHlCQUF5QixFQUMvQixPQUFPLEdBQUUsT0FBTyxDQUFDLFVBQVUsQ0FBQyxPQUFPLHlCQUF5QixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQU07OztHQU92RTtBQUVELHdCQUFzQixlQUFlLENBQUMsS0FBSyxFQUFFLHdCQUF3QixFQUFFLEtBQUssRUFBRSx3QkFBd0IsaUJBUXJHO0FBRUQsd0JBQXNCLGFBQWEsQ0FBQyxJQUFJLEVBQUUsd0JBQXdCLEVBQUUsS0FBSyxFQUFFLHdCQUF3QixpQkFZbEcifQ==
|
package/dest/test/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/test/utils.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,EAAE,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/test/utils.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAyB,MAAM,iCAAiC,CAAC;AAE5G,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,KAAK,EAEV,wBAAwB,EACxB,yBAAyB,EAC1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,yBAAyB,EAAsB,MAAM,uBAAuB,CAAC;AAItF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAE/E,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,yBAAyB,iBA8C3G;AAED,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,WAAW,EACrB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,yBAAyB,EAC/B,UAAU,GAAE,MAAM,GAAG,SAAgB,EACrC,iBAAiB,GAAE,MAA4C,EAC/D,wBAAwB,GAAE,OAAc;;;GAezC;AAED,wBAAsB,cAAc,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,yBAAyB;;;GAY1F;AAED,wBAAsB,UAAU,CAC9B,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,uBAAuB;;;GAepC;AAED,wBAAsB,cAAc,CAClC,gBAAgB,EAAE,gBAAgB,EAClC,IAAI,EAAE,yBAAyB,EAC/B,OAAO,GAAE,OAAO,CAAC,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAAM;;;GAOvE;AAED,wBAAsB,eAAe,CAAC,KAAK,EAAE,wBAAwB,EAAE,KAAK,EAAE,wBAAwB,iBAQrG;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,wBAAwB,EAAE,KAAK,EAAE,wBAAwB,iBAYlG"}
|