@aztec/world-state 0.0.1-commit.d431d1c → 0.0.1-commit.d939eb5aa
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 +9 -2
- 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 +7 -6
- package/dest/native/merkle_trees_facade.d.ts.map +1 -1
- package/dest/native/merkle_trees_facade.js +17 -9
- package/dest/native/message.d.ts +13 -5
- package/dest/native/message.d.ts.map +1 -1
- package/dest/native/native_world_state.d.ts +10 -8
- package/dest/native/native_world_state.d.ts.map +1 -1
- package/dest/native/native_world_state.js +18 -12
- 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 +4 -4
- package/dest/synchronizer/server_world_state_synchronizer.d.ts.map +1 -1
- package/dest/synchronizer/server_world_state_synchronizer.js +92 -22
- package/dest/test/utils.d.ts +6 -6
- package/dest/test/utils.d.ts.map +1 -1
- package/dest/test/utils.js +3 -3
- package/dest/testing.d.ts +4 -3
- package/dest/testing.d.ts.map +1 -1
- package/dest/testing.js +10 -6
- package/dest/world-state-db/merkle_tree_db.d.ts +3 -12
- package/dest/world-state-db/merkle_tree_db.d.ts.map +1 -1
- package/package.json +9 -10
- package/src/instrumentation/instrumentation.ts +9 -1
- package/src/native/fork_checkpoint.ts +19 -3
- package/src/native/merkle_trees_facade.ts +24 -12
- package/src/native/message.ts +14 -4
- package/src/native/native_world_state.ts +22 -16
- 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 +105 -30
- package/src/test/utils.ts +4 -4
- package/src/testing.ts +8 -9
- package/src/world-state-db/merkle_tree_db.ts +2 -12
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type Logger } from '@aztec/foundation/log';
|
|
2
|
-
import type
|
|
1
|
+
import { type Logger, type LoggerBindings } from '@aztec/foundation/log';
|
|
2
|
+
import { type GenesisData } from '@aztec/stdlib/world-state';
|
|
3
3
|
import type { WorldStateInstrumentation } from '../instrumentation/instrumentation.js';
|
|
4
4
|
import type { WorldStateTreeMapSizes } from '../synchronizer/factory.js';
|
|
5
5
|
import { WorldStateMessageType, type WorldStateRequest, type WorldStateRequestCategories, type WorldStateResponse } from './message.js';
|
|
@@ -13,14 +13,14 @@ export interface NativeWorldStateInstance {
|
|
|
13
13
|
export declare class NativeWorldState implements NativeWorldStateInstance {
|
|
14
14
|
private readonly dataDir;
|
|
15
15
|
private readonly wsTreeMapSizes;
|
|
16
|
-
private readonly
|
|
16
|
+
private readonly genesis;
|
|
17
17
|
private readonly instrumentation;
|
|
18
18
|
private readonly log;
|
|
19
19
|
private open;
|
|
20
20
|
private queues;
|
|
21
21
|
private instance;
|
|
22
22
|
/** Creates a new native WorldState instance */
|
|
23
|
-
constructor(dataDir: string, wsTreeMapSizes: WorldStateTreeMapSizes,
|
|
23
|
+
constructor(dataDir: string, wsTreeMapSizes: WorldStateTreeMapSizes, genesis: GenesisData | undefined, instrumentation: WorldStateInstrumentation, bindings?: LoggerBindings, log?: Logger);
|
|
24
24
|
getDataDir(): string;
|
|
25
25
|
clone(): NativeWorldState;
|
|
26
26
|
/**
|
|
@@ -46,4 +46,4 @@ export declare class NativeWorldState implements NativeWorldStateInstance {
|
|
|
46
46
|
close(): Promise<void>;
|
|
47
47
|
private _sendMessage;
|
|
48
48
|
}
|
|
49
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
49
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF0aXZlX3dvcmxkX3N0YXRlX2luc3RhbmNlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbmF0aXZlL25hdGl2ZV93b3JsZF9zdGF0ZV9pbnN0YW5jZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFVQSxPQUFPLEVBQUUsS0FBSyxNQUFNLEVBQUUsS0FBSyxjQUFjLEVBQWdCLE1BQU0sdUJBQXVCLENBQUM7QUFHdkYsT0FBTyxFQUFzQixLQUFLLFdBQVcsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBS2pGLE9BQU8sS0FBSyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFDdkYsT0FBTyxLQUFLLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN6RSxPQUFPLEVBQ0wscUJBQXFCLEVBQ3JCLEtBQUssaUJBQWlCLEVBQ3RCLEtBQUssMkJBQTJCLEVBQ2hDLEtBQUssa0JBQWtCLEVBSXhCLE1BQU0sY0FBYyxDQUFDO0FBS3RCLE1BQU0sV0FBVyx3QkFBd0I7SUFDdkMsSUFBSSxDQUFDLENBQUMsU0FBUyxxQkFBcUIsRUFDbEMsV0FBVyxFQUFFLENBQUMsRUFDZCxJQUFJLEVBQUUsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLEdBQUcsMkJBQTJCLEdBQ3ZELE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRWxDLFNBQVMsSUFBSSxHQUFHLENBQUM7Q0FDbEI7QUFFRDs7R0FFRztBQUNILHFCQUFhLGdCQUFpQixZQUFXLHdCQUF3QjtJQVU3RCxPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU87SUFDeEIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxjQUFjO0lBQy9CLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTztJQUN4QixPQUFPLENBQUMsUUFBUSxDQUFDLGVBQWU7SUFFaEMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHO0lBZHRCLE9BQU8sQ0FBQyxJQUFJLENBQVE7SUFHcEIsT0FBTyxDQUFDLE1BQU0sQ0FBeUM7SUFFdkQsT0FBTyxDQUFDLFFBQVEsQ0FBK0U7SUFFL0YsK0NBQStDO0lBQy9DLFlBQ21CLE9BQU8sRUFBRSxNQUFNLEVBQ2YsY0FBYyxFQUFFLHNCQUFzQixFQUN0QyxPQUFPLHlCQUFrQyxFQUN6QyxlQUFlLEVBQUUseUJBQXlCLEVBQzNELFFBQVEsQ0FBQyxFQUFFLGNBQWMsRUFDUixHQUFHLEdBQUUsTUFBdUQsRUF3QzlFO0lBRU0sVUFBVSxXQUVoQjtJQUVNLEtBQUsscUJBU1g7SUFFRDs7Ozs7O09BTUc7SUFDSSxTQUFTLElBQUksR0FBRyxDQWlCdEI7SUFFRDs7Ozs7OztPQU9HO0lBQ1UsSUFBSSxDQUFDLENBQUMsU0FBUyxxQkFBcUIsRUFDL0MsV0FBVyxFQUFFLENBQUMsRUFDZCxJQUFJLEVBQUUsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLEdBQUcsMkJBQTJCLEVBRXhELGVBQWUsNkRBQXVFLEVBQ3RGLFlBQVksc0JBQW9CLEdBQy9CLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQXFEaEM7SUFFRDs7T0FFRztJQUNVLEtBQUssSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBZWxDO1lBRWEsWUFBWTtDQThEM0IifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native_world_state_instance.d.ts","sourceRoot":"","sources":["../../src/native/native_world_state_instance.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"native_world_state_instance.d.ts","sourceRoot":"","sources":["../../src/native/native_world_state_instance.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AAGvF,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAKjF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAC;AACvF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,EACL,qBAAqB,EACrB,KAAK,iBAAiB,EACtB,KAAK,2BAA2B,EAChC,KAAK,kBAAkB,EAIxB,MAAM,cAAc,CAAC;AAKtB,MAAM,WAAW,wBAAwB;IACvC,IAAI,CAAC,CAAC,SAAS,qBAAqB,EAClC,WAAW,EAAE,CAAC,EACd,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,2BAA2B,GACvD,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC;IAElC,SAAS,IAAI,GAAG,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,gBAAiB,YAAW,wBAAwB;IAU7D,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,eAAe;IAEhC,OAAO,CAAC,QAAQ,CAAC,GAAG;IAdtB,OAAO,CAAC,IAAI,CAAQ;IAGpB,OAAO,CAAC,MAAM,CAAyC;IAEvD,OAAO,CAAC,QAAQ,CAA+E;IAE/F,+CAA+C;IAC/C,YACmB,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,sBAAsB,EACtC,OAAO,yBAAkC,EACzC,eAAe,EAAE,yBAAyB,EAC3D,QAAQ,CAAC,EAAE,cAAc,EACR,GAAG,GAAE,MAAuD,EAwC9E;IAEM,UAAU,WAEhB;IAEM,KAAK,qBASX;IAED;;;;;;OAMG;IACI,SAAS,IAAI,GAAG,CAiBtB;IAED;;;;;;;OAOG;IACU,IAAI,CAAC,CAAC,SAAS,qBAAqB,EAC/C,WAAW,EAAE,CAAC,EACd,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,2BAA2B,EAExD,eAAe,6DAAuE,EACtF,YAAY,sBAAoB,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAqDhC;IAED;;OAEG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAelC;YAEa,YAAY;CA8D3B"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { ARCHIVE_HEIGHT,
|
|
1
|
+
import { ARCHIVE_HEIGHT, DomainSeparator, L1_TO_L2_MSG_TREE_HEIGHT, MAX_NULLIFIERS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NOTE_HASH_TREE_HEIGHT, NULLIFIER_TREE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT } from '@aztec/constants';
|
|
2
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
3
|
import { NativeWorldState as BaseNativeWorldState, MsgpackChannel } from '@aztec/native';
|
|
4
4
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
5
|
+
import { EMPTY_GENESIS_DATA } from '@aztec/stdlib/world-state';
|
|
5
6
|
import assert from 'assert';
|
|
6
7
|
import { cpus } from 'os';
|
|
7
8
|
import { WorldStateMessageType, isWithCanonical, isWithForkId, isWithRevision } from './message.js';
|
|
@@ -12,24 +13,24 @@ const MAX_WORLD_STATE_THREADS = +(process.env.HARDWARE_CONCURRENCY || '16');
|
|
|
12
13
|
*/ export class NativeWorldState {
|
|
13
14
|
dataDir;
|
|
14
15
|
wsTreeMapSizes;
|
|
15
|
-
|
|
16
|
+
genesis;
|
|
16
17
|
instrumentation;
|
|
17
18
|
log;
|
|
18
19
|
open;
|
|
19
20
|
// We maintain a map of queue to fork
|
|
20
21
|
queues;
|
|
21
22
|
instance;
|
|
22
|
-
/** Creates a new native WorldState instance */ constructor(dataDir, wsTreeMapSizes,
|
|
23
|
+
/** Creates a new native WorldState instance */ constructor(dataDir, wsTreeMapSizes, genesis = EMPTY_GENESIS_DATA, instrumentation, bindings, log = createLogger('world-state:database', bindings)){
|
|
23
24
|
this.dataDir = dataDir;
|
|
24
25
|
this.wsTreeMapSizes = wsTreeMapSizes;
|
|
25
|
-
this.
|
|
26
|
+
this.genesis = genesis;
|
|
26
27
|
this.instrumentation = instrumentation;
|
|
27
28
|
this.log = log;
|
|
28
29
|
this.open = true;
|
|
29
30
|
this.queues = new Map();
|
|
30
31
|
const threads = Math.min(cpus().length, MAX_WORLD_STATE_THREADS);
|
|
31
32
|
log.info(`Creating world state data store at directory ${dataDir} with map sizes ${JSON.stringify(wsTreeMapSizes)} and ${threads} threads.`);
|
|
32
|
-
const prefilledPublicDataBufferArray = prefilledPublicData.map((d)=>[
|
|
33
|
+
const prefilledPublicDataBufferArray = genesis.prefilledPublicData.map((d)=>[
|
|
33
34
|
d.slot.toBuffer(),
|
|
34
35
|
d.value.toBuffer()
|
|
35
36
|
]);
|
|
@@ -42,7 +43,7 @@ const MAX_WORLD_STATE_THREADS = +(process.env.HARDWARE_CONCURRENCY || '16');
|
|
|
42
43
|
}, {
|
|
43
44
|
[MerkleTreeId.NULLIFIER_TREE]: 2 * MAX_NULLIFIERS_PER_TX,
|
|
44
45
|
[MerkleTreeId.PUBLIC_DATA_TREE]: 2 * MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX
|
|
45
|
-
}, prefilledPublicDataBufferArray,
|
|
46
|
+
}, prefilledPublicDataBufferArray, DomainSeparator.BLOCK_HEADER_HASH, Number(genesis.genesisTimestamp), {
|
|
46
47
|
[MerkleTreeId.NULLIFIER_TREE]: wsTreeMapSizes.nullifierTreeMapSizeKb,
|
|
47
48
|
[MerkleTreeId.NOTE_HASH_TREE]: wsTreeMapSizes.noteHashTreeMapSizeKb,
|
|
48
49
|
[MerkleTreeId.PUBLIC_DATA_TREE]: wsTreeMapSizes.publicDataTreeMapSizeKb,
|
|
@@ -57,7 +58,7 @@ const MAX_WORLD_STATE_THREADS = +(process.env.HARDWARE_CONCURRENCY || '16');
|
|
|
57
58
|
return this.dataDir;
|
|
58
59
|
}
|
|
59
60
|
clone() {
|
|
60
|
-
return new NativeWorldState(this.dataDir, this.wsTreeMapSizes, this.
|
|
61
|
+
return new NativeWorldState(this.dataDir, this.wsTreeMapSizes, this.genesis, this.instrumentation, this.log.getBindings(), this.log);
|
|
61
62
|
}
|
|
62
63
|
/**
|
|
63
64
|
* Gets the native WorldState handle from the underlying native instance.
|
|
@@ -67,7 +67,7 @@ export class WorldStateOpsQueue {
|
|
|
67
67
|
// then send the request immediately
|
|
68
68
|
// If a mutating request is in flight then we must wait
|
|
69
69
|
// If a mutating request is not in flight but something is queued then it must be a mutating request
|
|
70
|
-
if (this.inFlightMutatingCount
|
|
70
|
+
if (this.inFlightMutatingCount === 0 && this.requests.length === 0) {
|
|
71
71
|
this.sendEnqueuedRequest(op);
|
|
72
72
|
} else {
|
|
73
73
|
this.requests.push(op);
|
|
@@ -88,7 +88,7 @@ export class WorldStateOpsQueue {
|
|
|
88
88
|
}
|
|
89
89
|
--this.inFlightCount;
|
|
90
90
|
// If there are still requests in flight then do nothing further
|
|
91
|
-
if (this.inFlightCount
|
|
91
|
+
if (this.inFlightCount !== 0) {
|
|
92
92
|
return;
|
|
93
93
|
}
|
|
94
94
|
// No requests in flight, send next queued requests
|
|
@@ -99,7 +99,7 @@ export class WorldStateOpsQueue {
|
|
|
99
99
|
while(this.requests.length > 0){
|
|
100
100
|
const next = this.requests[0];
|
|
101
101
|
if (next.mutating) {
|
|
102
|
-
if (this.inFlightCount
|
|
102
|
+
if (this.inFlightCount === 0) {
|
|
103
103
|
// send the mutating request
|
|
104
104
|
this.requests.shift();
|
|
105
105
|
this.sendEnqueuedRequest(next);
|
|
@@ -112,7 +112,7 @@ export class WorldStateOpsQueue {
|
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
// If the queue is empty, there is nothing in flight and we have been told to stop, then resolve the stop promise
|
|
115
|
-
if (this.inFlightCount
|
|
115
|
+
if (this.inFlightCount === 0 && this.stopResolve !== undefined) {
|
|
116
116
|
this.stopResolve();
|
|
117
117
|
}
|
|
118
118
|
}
|
|
@@ -138,7 +138,7 @@ export class WorldStateOpsQueue {
|
|
|
138
138
|
this.stopResolve = resolve;
|
|
139
139
|
});
|
|
140
140
|
// If no outstanding requests then immediately resolve the promise
|
|
141
|
-
if (this.requests.length
|
|
141
|
+
if (this.requests.length === 0 && this.inFlightCount === 0 && this.stopResolve !== undefined) {
|
|
142
142
|
this.stopResolve();
|
|
143
143
|
}
|
|
144
144
|
return this.stopPromise;
|
|
@@ -3,8 +3,6 @@ import { type ConfigMappingsType } from '@aztec/foundation/config';
|
|
|
3
3
|
export interface WorldStateConfig {
|
|
4
4
|
/** The frequency in which to check. */
|
|
5
5
|
worldStateBlockCheckIntervalMS: number;
|
|
6
|
-
/** Whether to follow only the proven chain. */
|
|
7
|
-
worldStateProvenBlocksOnly: boolean;
|
|
8
6
|
/** Size of the batch for each get-blocks request from the synchronizer to the archiver. */
|
|
9
7
|
worldStateBlockRequestBatchSize?: number;
|
|
10
8
|
/** The map size to be provided to LMDB for each world state tree DB, optional, will inherit from the general dataStoreMapSizeKb if not specified*/
|
|
@@ -21,8 +19,8 @@ export interface WorldStateConfig {
|
|
|
21
19
|
publicDataTreeMapSizeKb?: number;
|
|
22
20
|
/** Optional directory for the world state DB, if unspecified will default to the general data directory */
|
|
23
21
|
worldStateDataDirectory?: string;
|
|
24
|
-
/** The number of historic blocks to maintain */
|
|
25
|
-
|
|
22
|
+
/** The number of historic checkpoints worth of blocks to maintain */
|
|
23
|
+
worldStateCheckpointHistory: number;
|
|
26
24
|
}
|
|
27
25
|
export declare const worldStateConfigMappings: ConfigMappingsType<WorldStateConfig>;
|
|
28
26
|
/**
|
|
@@ -30,4 +28,4 @@ export declare const worldStateConfigMappings: ConfigMappingsType<WorldStateConf
|
|
|
30
28
|
* @returns The configuration values for the world state synchronizer.
|
|
31
29
|
*/
|
|
32
30
|
export declare function getWorldStateConfigFromEnv(): WorldStateConfig;
|
|
33
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
31
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3luY2hyb25pemVyL2NvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsS0FBSyxrQkFBa0IsRUFBNkMsTUFBTSwwQkFBMEIsQ0FBQztBQUU5RyxxREFBcUQ7QUFDckQsTUFBTSxXQUFXLGdCQUFnQjtJQUMvQix1Q0FBdUM7SUFDdkMsOEJBQThCLEVBQUUsTUFBTSxDQUFDO0lBRXZDLDJGQUEyRjtJQUMzRiwrQkFBK0IsQ0FBQyxFQUFFLE1BQU0sQ0FBQztJQUV6QyxtSkFBbUo7SUFDbkoscUJBQXFCLENBQUMsRUFBRSxNQUFNLENBQUM7SUFFL0IsMkpBQTJKO0lBQzNKLG9CQUFvQixDQUFDLEVBQUUsTUFBTSxDQUFDO0lBRTlCLDZKQUE2SjtJQUM3SixzQkFBc0IsQ0FBQyxFQUFFLE1BQU0sQ0FBQztJQUVoQyw2SkFBNko7SUFDN0oscUJBQXFCLENBQUMsRUFBRSxNQUFNLENBQUM7SUFFL0IsMkpBQTJKO0lBQzNKLG9CQUFvQixDQUFDLEVBQUUsTUFBTSxDQUFDO0lBRTlCLCtKQUErSjtJQUMvSix1QkFBdUIsQ0FBQyxFQUFFLE1BQU0sQ0FBQztJQUVqQywyR0FBMkc7SUFDM0csdUJBQXVCLENBQUMsRUFBRSxNQUFNLENBQUM7SUFFakMscUVBQXFFO0lBQ3JFLDJCQUEyQixFQUFFLE1BQU0sQ0FBQztDQUNyQztBQUVELGVBQU8sTUFBTSx3QkFBd0IsRUFBRSxrQkFBa0IsQ0FBQyxnQkFBZ0IsQ0EwRHpFLENBQUM7QUFFRjs7O0dBR0c7QUFDSCx3QkFBZ0IsMEJBQTBCLElBQUksZ0JBQWdCLENBRTdEIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/synchronizer/config.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/synchronizer/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAA6C,MAAM,0BAA0B,CAAC;AAE9G,qDAAqD;AACrD,MAAM,WAAW,gBAAgB;IAC/B,uCAAuC;IACvC,8BAA8B,EAAE,MAAM,CAAC;IAEvC,2FAA2F;IAC3F,+BAA+B,CAAC,EAAE,MAAM,CAAC;IAEzC,mJAAmJ;IACnJ,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B,2JAA2J;IAC3J,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAE9B,6JAA6J;IAC7J,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC,6JAA6J;IAC7J,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B,2JAA2J;IAC3J,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAE9B,+JAA+J;IAC/J,uBAAuB,CAAC,EAAE,MAAM,CAAC;IAEjC,2GAA2G;IAC3G,uBAAuB,CAAC,EAAE,MAAM,CAAC;IAEjC,qEAAqE;IACrE,2BAA2B,EAAE,MAAM,CAAC;CACrC;AAED,eAAO,MAAM,wBAAwB,EAAE,kBAAkB,CAAC,gBAAgB,CA0DzE,CAAC;AAEF;;;GAGG;AACH,wBAAgB,0BAA0B,IAAI,gBAAgB,CAE7D"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getConfigFromMappings, numberConfigHelper } from '@aztec/foundation/config';
|
|
2
2
|
export const worldStateConfigMappings = {
|
|
3
3
|
worldStateBlockCheckIntervalMS: {
|
|
4
4
|
env: 'WS_BLOCK_CHECK_INTERVAL_MS',
|
|
@@ -6,53 +6,51 @@ export const worldStateConfigMappings = {
|
|
|
6
6
|
defaultValue: 100,
|
|
7
7
|
description: 'The frequency in which to check.'
|
|
8
8
|
},
|
|
9
|
-
worldStateProvenBlocksOnly: {
|
|
10
|
-
env: 'WS_PROVEN_BLOCKS_ONLY',
|
|
11
|
-
description: 'Whether to follow only the proven chain.',
|
|
12
|
-
...booleanConfigHelper()
|
|
13
|
-
},
|
|
14
9
|
worldStateBlockRequestBatchSize: {
|
|
15
10
|
env: 'WS_BLOCK_REQUEST_BATCH_SIZE',
|
|
16
|
-
parseEnv: (val)
|
|
11
|
+
parseEnv: (val)=>+val,
|
|
17
12
|
description: 'Size of the batch for each get-blocks request from the synchronizer to the archiver.'
|
|
18
13
|
},
|
|
19
14
|
worldStateDbMapSizeKb: {
|
|
20
15
|
env: 'WS_DB_MAP_SIZE_KB',
|
|
21
|
-
parseEnv: (val)
|
|
16
|
+
parseEnv: (val)=>+val,
|
|
22
17
|
description: 'The maximum possible size of the world state DB in KB. Overwrites the general dataStoreMapSizeKb.'
|
|
23
18
|
},
|
|
24
19
|
archiveTreeMapSizeKb: {
|
|
25
20
|
env: 'ARCHIVE_TREE_MAP_SIZE_KB',
|
|
26
|
-
parseEnv: (val)
|
|
21
|
+
parseEnv: (val)=>+val,
|
|
27
22
|
description: 'The maximum possible size of the world state archive tree in KB. Overwrites the general worldStateDbMapSizeKb.'
|
|
28
23
|
},
|
|
29
24
|
nullifierTreeMapSizeKb: {
|
|
30
25
|
env: 'NULLIFIER_TREE_MAP_SIZE_KB',
|
|
31
|
-
parseEnv: (val)
|
|
26
|
+
parseEnv: (val)=>+val,
|
|
32
27
|
description: 'The maximum possible size of the world state nullifier tree in KB. Overwrites the general worldStateDbMapSizeKb.'
|
|
33
28
|
},
|
|
34
29
|
noteHashTreeMapSizeKb: {
|
|
35
30
|
env: 'NOTE_HASH_TREE_MAP_SIZE_KB',
|
|
36
|
-
parseEnv: (val)
|
|
31
|
+
parseEnv: (val)=>+val,
|
|
37
32
|
description: 'The maximum possible size of the world state note hash tree in KB. Overwrites the general worldStateDbMapSizeKb.'
|
|
38
33
|
},
|
|
39
34
|
messageTreeMapSizeKb: {
|
|
40
35
|
env: 'MESSAGE_TREE_MAP_SIZE_KB',
|
|
41
|
-
parseEnv: (val)
|
|
36
|
+
parseEnv: (val)=>+val,
|
|
42
37
|
description: 'The maximum possible size of the world state message tree in KB. Overwrites the general worldStateDbMapSizeKb.'
|
|
43
38
|
},
|
|
44
39
|
publicDataTreeMapSizeKb: {
|
|
45
40
|
env: 'PUBLIC_DATA_TREE_MAP_SIZE_KB',
|
|
46
|
-
parseEnv: (val)
|
|
41
|
+
parseEnv: (val)=>+val,
|
|
47
42
|
description: 'The maximum possible size of the world state public data tree in KB. Overwrites the general worldStateDbMapSizeKb.'
|
|
48
43
|
},
|
|
49
44
|
worldStateDataDirectory: {
|
|
50
45
|
env: 'WS_DATA_DIRECTORY',
|
|
51
46
|
description: 'Optional directory for the world state database'
|
|
52
47
|
},
|
|
53
|
-
|
|
54
|
-
env: '
|
|
55
|
-
description: 'The number of historic blocks to maintain. Values less than 1 mean all history is maintained',
|
|
48
|
+
worldStateCheckpointHistory: {
|
|
49
|
+
env: 'WS_NUM_HISTORIC_CHECKPOINTS',
|
|
50
|
+
description: 'The number of historic checkpoints worth of blocks to maintain. Values less than 1 mean all history is maintained',
|
|
51
|
+
fallback: [
|
|
52
|
+
'WS_NUM_HISTORIC_BLOCKS'
|
|
53
|
+
],
|
|
56
54
|
...numberConfigHelper(64)
|
|
57
55
|
}
|
|
58
56
|
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { LoggerBindings } from '@aztec/foundation/log';
|
|
2
2
|
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
3
|
+
import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
|
|
3
4
|
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
4
|
-
import type
|
|
5
|
+
import { type GenesisData } from '@aztec/stdlib/world-state';
|
|
5
6
|
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
6
7
|
import { WorldStateInstrumentation } from '../instrumentation/instrumentation.js';
|
|
7
8
|
import { NativeWorldStateService } from '../native/native_world_state.js';
|
|
@@ -14,6 +15,6 @@ export interface WorldStateTreeMapSizes {
|
|
|
14
15
|
messageTreeMapSizeKb: number;
|
|
15
16
|
publicDataTreeMapSizeKb: number;
|
|
16
17
|
}
|
|
17
|
-
export declare function createWorldStateSynchronizer(config: WorldStateConfig & DataStoreConfig, l2BlockSource: L2BlockSource & L1ToL2MessageSource,
|
|
18
|
-
export declare function createWorldState(config: Pick<WorldStateConfig, 'worldStateDataDirectory' | 'worldStateDbMapSizeKb' | 'archiveTreeMapSizeKb' | 'nullifierTreeMapSizeKb' | 'noteHashTreeMapSizeKb' | 'messageTreeMapSizeKb' | 'publicDataTreeMapSizeKb'> & Pick<DataStoreConfig, 'dataDirectory' | 'dataStoreMapSizeKb' | 'l1Contracts'>,
|
|
19
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
18
|
+
export declare function createWorldStateSynchronizer(config: WorldStateConfig & DataStoreConfig, l2BlockSource: L2BlockSource & L1ToL2MessageSource, genesis?: GenesisData, client?: TelemetryClient, bindings?: LoggerBindings): Promise<ServerWorldStateSynchronizer>;
|
|
19
|
+
export declare function createWorldState(config: Pick<WorldStateConfig, 'worldStateDataDirectory' | 'worldStateDbMapSizeKb' | 'archiveTreeMapSizeKb' | 'nullifierTreeMapSizeKb' | 'noteHashTreeMapSizeKb' | 'messageTreeMapSizeKb' | 'publicDataTreeMapSizeKb'> & Pick<DataStoreConfig, 'dataDirectory' | 'dataStoreMapSizeKb' | 'l1Contracts'>, genesis?: GenesisData, instrumentation?: WorldStateInstrumentation, bindings?: LoggerBindings): Promise<NativeWorldStateService>;
|
|
20
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjdG9yeS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N5bmNocm9uaXplci9mYWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLGNBQWMsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzVELE9BQU8sS0FBSyxFQUFFLGFBQWEsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3pELE9BQU8sS0FBSyxFQUFFLGVBQWUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzlELE9BQU8sS0FBSyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDbkUsT0FBTyxFQUFzQixLQUFLLFdBQVcsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ2pGLE9BQU8sRUFBRSxLQUFLLGVBQWUsRUFBc0IsTUFBTSx5QkFBeUIsQ0FBQztBQUVuRixPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUNsRixPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUMxRSxPQUFPLEtBQUssRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNwRCxPQUFPLEVBQUUsNEJBQTRCLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUVwRixNQUFNLFdBQVcsc0JBQXNCO0lBQ3JDLG9CQUFvQixFQUFFLE1BQU0sQ0FBQztJQUM3QixzQkFBc0IsRUFBRSxNQUFNLENBQUM7SUFDL0IscUJBQXFCLEVBQUUsTUFBTSxDQUFDO0lBQzlCLG9CQUFvQixFQUFFLE1BQU0sQ0FBQztJQUM3Qix1QkFBdUIsRUFBRSxNQUFNLENBQUM7Q0FDakM7QUFFRCx3QkFBc0IsNEJBQTRCLENBQ2hELE1BQU0sRUFBRSxnQkFBZ0IsR0FBRyxlQUFlLEVBQzFDLGFBQWEsRUFBRSxhQUFhLEdBQUcsbUJBQW1CLEVBQ2xELE9BQU8sR0FBRSxXQUFnQyxFQUN6QyxNQUFNLEdBQUUsZUFBc0MsRUFDOUMsUUFBUSxDQUFDLEVBQUUsY0FBYyx5Q0FLMUI7QUFFRCx3QkFBc0IsZ0JBQWdCLENBQ3BDLE1BQU0sRUFBRSxJQUFJLENBQ1YsZ0JBQWdCLEVBQ2QseUJBQXlCLEdBQ3pCLHVCQUF1QixHQUN2QixzQkFBc0IsR0FDdEIsd0JBQXdCLEdBQ3hCLHVCQUF1QixHQUN2QixzQkFBc0IsR0FDdEIseUJBQXlCLENBQzVCLEdBQ0MsSUFBSSxDQUFDLGVBQWUsRUFBRSxlQUFlLEdBQUcsb0JBQW9CLEdBQUcsYUFBYSxDQUFDLEVBQy9FLE9BQU8sR0FBRSxXQUFnQyxFQUN6QyxlQUFlLEdBQUUseUJBQStFLEVBQ2hHLFFBQVEsQ0FBQyxFQUFFLGNBQWMsb0NBbUMxQiJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/synchronizer/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/synchronizer/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACjF,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,yBAAyB,CAAC;AAEnF,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAC;AAEpF,MAAM,WAAW,sBAAsB;IACrC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,uBAAuB,EAAE,MAAM,CAAC;CACjC;AAED,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,gBAAgB,GAAG,eAAe,EAC1C,aAAa,EAAE,aAAa,GAAG,mBAAmB,EAClD,OAAO,GAAE,WAAgC,EACzC,MAAM,GAAE,eAAsC,EAC9C,QAAQ,CAAC,EAAE,cAAc,yCAK1B;AAED,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,IAAI,CACV,gBAAgB,EACd,yBAAyB,GACzB,uBAAuB,GACvB,sBAAsB,GACtB,wBAAwB,GACxB,uBAAuB,GACvB,sBAAsB,GACtB,yBAAyB,CAC5B,GACC,IAAI,CAAC,eAAe,EAAE,eAAe,GAAG,oBAAoB,GAAG,aAAa,CAAC,EAC/E,OAAO,GAAE,WAAgC,EACzC,eAAe,GAAE,yBAA+E,EAChG,QAAQ,CAAC,EAAE,cAAc,oCAmC1B"}
|
|
@@ -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
1
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import { type Logger } from '@aztec/foundation/log';
|
|
3
|
-
import { type L2BlockSource, L2BlockStream, type L2BlockStreamEvent, type L2BlockStreamEventHandler, type L2BlockStreamLocalDataProvider, type L2Tips } from '@aztec/stdlib/block';
|
|
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';
|
|
@@ -45,10 +45,10 @@ export declare class ServerWorldStateSynchronizer implements WorldStateSynchroni
|
|
|
45
45
|
/**
|
|
46
46
|
* Forces an immediate sync.
|
|
47
47
|
* @param targetBlockNumber - The target block number that we must sync to. Will download unproven blocks if needed to reach it.
|
|
48
|
-
* @param
|
|
48
|
+
* @param blockHash - If provided, verifies the block at targetBlockNumber matches this hash. On mismatch, triggers a resync (reorg detection).
|
|
49
49
|
* @returns A promise that resolves with the block number the world state was synced to
|
|
50
50
|
*/
|
|
51
|
-
syncImmediate(targetBlockNumber?: BlockNumber,
|
|
51
|
+
syncImmediate(targetBlockNumber?: BlockNumber, blockHash?: BlockHash): Promise<BlockNumber>;
|
|
52
52
|
/** Returns the L2 block hash for a given number. Used by the L2BlockStream for detecting reorgs. */
|
|
53
53
|
getL2BlockHash(number: BlockNumber): Promise<string | undefined>;
|
|
54
54
|
/** Returns the latest L2 block number for each tip of the chain (latest, proven, finalized). */
|
|
@@ -66,4 +66,4 @@ export declare class ServerWorldStateSynchronizer implements WorldStateSynchroni
|
|
|
66
66
|
*/
|
|
67
67
|
private setCurrentState;
|
|
68
68
|
}
|
|
69
|
-
//# 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":"AACA,OAAO,EAAE,WAAW,
|
|
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,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
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 { GENESIS_CHECKPOINT_HEADER_HASH, L2BlockStream } from '@aztec/stdlib/block';
|
|
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
9
|
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
@@ -38,7 +38,7 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
38
38
|
this.currentState = WorldStateRunningState.IDLE;
|
|
39
39
|
this.syncPromise = promiseWithResolvers();
|
|
40
40
|
this.merkleTreeCommitted = this.merkleTreeDb.getCommitted();
|
|
41
|
-
this.historyToKeep = config.
|
|
41
|
+
this.historyToKeep = config.worldStateCheckpointHistory < 1 ? undefined : config.worldStateCheckpointHistory;
|
|
42
42
|
this.log.info(`Created world state synchroniser with block history of ${this.historyToKeep === undefined ? 'infinity' : this.historyToKeep}`);
|
|
43
43
|
}
|
|
44
44
|
getCommitted() {
|
|
@@ -64,7 +64,7 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
64
64
|
return this.syncPromise;
|
|
65
65
|
}
|
|
66
66
|
// Get the current latest block number
|
|
67
|
-
this.latestBlockNumberAtStart = BlockNumber(await
|
|
67
|
+
this.latestBlockNumberAtStart = BlockNumber(await this.l2BlockSource.getBlockNumber());
|
|
68
68
|
const blockToDownloadFrom = await this.getLatestBlockNumber() + 1;
|
|
69
69
|
if (blockToDownloadFrom <= this.latestBlockNumberAtStart) {
|
|
70
70
|
// If there are blocks to be retrieved, go to a synching state
|
|
@@ -84,7 +84,6 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
84
84
|
createBlockStream() {
|
|
85
85
|
const logger = createLogger('world-state:block_stream');
|
|
86
86
|
return new L2BlockStream(this.l2BlockSource, this, this, logger, {
|
|
87
|
-
proven: this.config.worldStateProvenBlocksOnly,
|
|
88
87
|
pollIntervalMS: this.config.worldStateBlockCheckIntervalMS,
|
|
89
88
|
batchSize: this.config.worldStateBlockRequestBatchSize,
|
|
90
89
|
ignoreCheckpoints: true
|
|
@@ -131,9 +130,9 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
131
130
|
/**
|
|
132
131
|
* Forces an immediate sync.
|
|
133
132
|
* @param targetBlockNumber - The target block number that we must sync to. Will download unproven blocks if needed to reach it.
|
|
134
|
-
* @param
|
|
133
|
+
* @param blockHash - If provided, verifies the block at targetBlockNumber matches this hash. On mismatch, triggers a resync (reorg detection).
|
|
135
134
|
* @returns A promise that resolves with the block number the world state was synced to
|
|
136
|
-
*/ async syncImmediate(targetBlockNumber,
|
|
135
|
+
*/ async syncImmediate(targetBlockNumber, blockHash) {
|
|
137
136
|
if (this.currentState !== WorldStateRunningState.RUNNING) {
|
|
138
137
|
throw new Error(`World State is not running. Unable to perform sync.`);
|
|
139
138
|
}
|
|
@@ -143,7 +142,16 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
143
142
|
// If we have been given a block number to sync to and we have reached that number then return
|
|
144
143
|
const currentBlockNumber = await this.getLatestBlockNumber();
|
|
145
144
|
if (targetBlockNumber !== undefined && targetBlockNumber <= currentBlockNumber) {
|
|
146
|
-
|
|
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.`);
|
|
147
155
|
}
|
|
148
156
|
this.log.debug(`World State at ${currentBlockNumber} told to sync to ${targetBlockNumber ?? 'latest'}`);
|
|
149
157
|
// If the archiver is behind the target block, force an archiver sync
|
|
@@ -158,7 +166,7 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
158
166
|
await this.blockStream.sync();
|
|
159
167
|
// If we have been given a block number to sync to and we have not reached that number then fail
|
|
160
168
|
const updatedBlockNumber = await this.getLatestBlockNumber();
|
|
161
|
-
if (
|
|
169
|
+
if (targetBlockNumber !== undefined && targetBlockNumber > updatedBlockNumber) {
|
|
162
170
|
throw new WorldStateSynchronizerError(`Unable to sync to block number ${targetBlockNumber} (last synced is ${updatedBlockNumber})`, {
|
|
163
171
|
cause: {
|
|
164
172
|
reason: 'block_not_available',
|
|
@@ -168,6 +176,20 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
168
176
|
}
|
|
169
177
|
});
|
|
170
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
|
+
}
|
|
171
193
|
return updatedBlockNumber;
|
|
172
194
|
}
|
|
173
195
|
/** Returns the L2 block hash for a given number. Used by the L2BlockStream for detecting reorgs. */ async getL2BlockHash(number) {
|
|
@@ -203,7 +225,17 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
203
225
|
hash: GENESIS_BLOCK_HEADER_HASH.toString()
|
|
204
226
|
},
|
|
205
227
|
checkpoint: {
|
|
206
|
-
number:
|
|
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,
|
|
207
239
|
hash: genesisCheckpointHeaderHash
|
|
208
240
|
}
|
|
209
241
|
},
|
|
@@ -213,7 +245,7 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
213
245
|
hash: finalizedBlockHash ?? ''
|
|
214
246
|
},
|
|
215
247
|
checkpoint: {
|
|
216
|
-
number:
|
|
248
|
+
number: INITIAL_CHECKPOINT_NUMBER,
|
|
217
249
|
hash: genesisCheckpointHeaderHash
|
|
218
250
|
}
|
|
219
251
|
},
|
|
@@ -223,7 +255,7 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
223
255
|
hash: provenBlockHash ?? ''
|
|
224
256
|
},
|
|
225
257
|
checkpoint: {
|
|
226
|
-
number:
|
|
258
|
+
number: INITIAL_CHECKPOINT_NUMBER,
|
|
227
259
|
hash: genesisCheckpointHeaderHash
|
|
228
260
|
}
|
|
229
261
|
}
|
|
@@ -250,7 +282,7 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
250
282
|
* @param l2Blocks - The L2 blocks to handle.
|
|
251
283
|
* @returns Whether the block handled was produced by this same node.
|
|
252
284
|
*/ async handleL2Blocks(l2Blocks) {
|
|
253
|
-
this.log.
|
|
285
|
+
this.log.debug(`Handling L2 blocks ${l2Blocks[0].number} to ${l2Blocks.at(-1).number}`);
|
|
254
286
|
// Fetch the L1->L2 messages for the first block in a checkpoint.
|
|
255
287
|
const messagesForBlocks = new Map();
|
|
256
288
|
await Promise.all(l2Blocks.filter((b)=>b.indexWithinCheckpoint === 0).map(async (block)=>{
|
|
@@ -281,10 +313,12 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
281
313
|
* @param l1ToL2Messages - The L1 to L2 messages for the block.
|
|
282
314
|
* @returns Whether the block handled was produced by this same node.
|
|
283
315
|
*/ async handleL2Block(l2Block, l1ToL2Messages) {
|
|
284
|
-
this.log.
|
|
316
|
+
this.log.debug(`Pushing L2 block ${l2Block.number} to merkle tree db `, {
|
|
285
317
|
blockNumber: l2Block.number,
|
|
286
318
|
blockHash: await l2Block.hash().then((h)=>h.toString()),
|
|
287
|
-
l1ToL2Messages: l1ToL2Messages.map((msg)=>msg.toString())
|
|
319
|
+
l1ToL2Messages: l1ToL2Messages.map((msg)=>msg.toString()),
|
|
320
|
+
blockHeader: l2Block.header.toInspect(),
|
|
321
|
+
blockStats: l2Block.getStats()
|
|
288
322
|
});
|
|
289
323
|
const result = await this.merkleTreeDb.handleL2BlockAndMessages(l2Block, l1ToL2Messages);
|
|
290
324
|
if (this.currentState === WorldStateRunningState.SYNCHING && l2Block.number >= this.latestBlockNumberAtStart) {
|
|
@@ -295,16 +329,50 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
295
329
|
}
|
|
296
330
|
async handleChainFinalized(blockNumber) {
|
|
297
331
|
this.log.verbose(`Finalized chain is now at block ${blockNumber}`);
|
|
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
|
+
}
|
|
298
342
|
const summary = await this.merkleTreeDb.setFinalized(blockNumber);
|
|
299
343
|
if (this.historyToKeep === undefined) {
|
|
300
344
|
return;
|
|
301
345
|
}
|
|
302
|
-
|
|
303
|
-
|
|
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}`);
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
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`);
|
|
304
361
|
return;
|
|
305
362
|
}
|
|
306
|
-
|
|
307
|
-
|
|
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));
|
|
308
376
|
this.log.debug(`World state summary `, status.summary);
|
|
309
377
|
}
|
|
310
378
|
handleChainProven(blockNumber) {
|
|
@@ -313,9 +381,11 @@ import { WorldStateSynchronizerError } from './errors.js';
|
|
|
313
381
|
return Promise.resolve();
|
|
314
382
|
}
|
|
315
383
|
async handleChainPruned(blockNumber) {
|
|
316
|
-
this.log.
|
|
384
|
+
this.log.info(`Chain pruned to block ${blockNumber}`);
|
|
317
385
|
const status = await this.merkleTreeDb.unwindBlocks(blockNumber);
|
|
318
|
-
this.provenBlockNumber
|
|
386
|
+
if (this.provenBlockNumber !== undefined && this.provenBlockNumber > blockNumber) {
|
|
387
|
+
this.provenBlockNumber = undefined;
|
|
388
|
+
}
|
|
319
389
|
this.instrumentation.updateWorldStateMetrics(status);
|
|
320
390
|
}
|
|
321
391
|
/**
|