@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
package/src/native/message.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
3
|
import type { Tuple } from '@aztec/foundation/serialize';
|
|
3
4
|
import { AppendOnlyTreeSnapshot, MerkleTreeId } from '@aztec/stdlib/trees';
|
|
4
5
|
import type { StateReference } from '@aztec/stdlib/tx';
|
|
@@ -56,11 +57,11 @@ interface WithTreeId {
|
|
|
56
57
|
|
|
57
58
|
export interface WorldStateStatusSummary {
|
|
58
59
|
/** Last block number that can still be unwound. */
|
|
59
|
-
unfinalizedBlockNumber:
|
|
60
|
+
unfinalizedBlockNumber: BlockNumber;
|
|
60
61
|
/** Last block number that is finalized and cannot be unwound. */
|
|
61
|
-
finalizedBlockNumber:
|
|
62
|
+
finalizedBlockNumber: BlockNumber;
|
|
62
63
|
/** Oldest block still available for historical queries and forks. */
|
|
63
|
-
oldestHistoricalBlock:
|
|
64
|
+
oldestHistoricalBlock: BlockNumber;
|
|
64
65
|
/** Whether the trees are in sync with each other */
|
|
65
66
|
treesAreSynched: boolean;
|
|
66
67
|
}
|
|
@@ -81,11 +82,11 @@ export interface TreeMeta {
|
|
|
81
82
|
/** The tree's initial root value */
|
|
82
83
|
initialRoot: Fr;
|
|
83
84
|
/** The current oldest historical block number of the tree */
|
|
84
|
-
oldestHistoricBlock:
|
|
85
|
+
oldestHistoricBlock: BlockNumber;
|
|
85
86
|
/** The current unfinalized block number of the tree */
|
|
86
|
-
unfinalizedBlockHeight:
|
|
87
|
+
unfinalizedBlockHeight: BlockNumber;
|
|
87
88
|
/** The current finalized block number of the tree */
|
|
88
|
-
finalizedBlockHeight:
|
|
89
|
+
finalizedBlockHeight: BlockNumber;
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
export interface DBStats {
|
|
@@ -173,9 +174,9 @@ export function buildEmptyTreeMeta() {
|
|
|
173
174
|
depth: 0,
|
|
174
175
|
size: 0n,
|
|
175
176
|
committedSize: 0n,
|
|
176
|
-
unfinalizedBlockHeight:
|
|
177
|
-
finalizedBlockHeight:
|
|
178
|
-
oldestHistoricBlock:
|
|
177
|
+
unfinalizedBlockHeight: BlockNumber.ZERO,
|
|
178
|
+
finalizedBlockHeight: BlockNumber.ZERO,
|
|
179
|
+
oldestHistoricBlock: BlockNumber.ZERO,
|
|
179
180
|
root: Fr.ZERO,
|
|
180
181
|
initialRoot: Fr.ZERO,
|
|
181
182
|
initialSize: 0n,
|
|
@@ -204,9 +205,9 @@ export function buildEmptyWorldStateDBStats() {
|
|
|
204
205
|
|
|
205
206
|
export function buildEmptyWorldStateSummary() {
|
|
206
207
|
return {
|
|
207
|
-
unfinalizedBlockNumber:
|
|
208
|
-
finalizedBlockNumber:
|
|
209
|
-
oldestHistoricalBlock:
|
|
208
|
+
unfinalizedBlockNumber: BlockNumber.ZERO,
|
|
209
|
+
finalizedBlockNumber: BlockNumber.ZERO,
|
|
210
|
+
oldestHistoricalBlock: BlockNumber.ZERO,
|
|
210
211
|
treesAreSynched: true,
|
|
211
212
|
} as WorldStateStatusSummary;
|
|
212
213
|
}
|
|
@@ -220,9 +221,9 @@ export function buildEmptyWorldStateStatusFull() {
|
|
|
220
221
|
}
|
|
221
222
|
|
|
222
223
|
export function sanitizeSummary(summary: WorldStateStatusSummary) {
|
|
223
|
-
summary.finalizedBlockNumber = BigInt(summary.finalizedBlockNumber);
|
|
224
|
-
summary.unfinalizedBlockNumber = BigInt(summary.unfinalizedBlockNumber);
|
|
225
|
-
summary.oldestHistoricalBlock = BigInt(summary.oldestHistoricalBlock);
|
|
224
|
+
summary.finalizedBlockNumber = BlockNumber.fromBigInt(BigInt(summary.finalizedBlockNumber));
|
|
225
|
+
summary.unfinalizedBlockNumber = BlockNumber.fromBigInt(BigInt(summary.unfinalizedBlockNumber));
|
|
226
|
+
summary.oldestHistoricalBlock = BlockNumber.fromBigInt(BigInt(summary.oldestHistoricalBlock));
|
|
226
227
|
return summary;
|
|
227
228
|
}
|
|
228
229
|
|
|
@@ -234,11 +235,11 @@ export function sanitizeDBStats(stats: DBStats) {
|
|
|
234
235
|
|
|
235
236
|
export function sanitizeMeta(meta: TreeMeta) {
|
|
236
237
|
meta.committedSize = BigInt(meta.committedSize);
|
|
237
|
-
meta.finalizedBlockHeight = BigInt(meta.finalizedBlockHeight);
|
|
238
|
+
meta.finalizedBlockHeight = BlockNumber.fromBigInt(BigInt(meta.finalizedBlockHeight));
|
|
238
239
|
meta.initialSize = BigInt(meta.initialSize);
|
|
239
|
-
meta.oldestHistoricBlock = BigInt(meta.oldestHistoricBlock);
|
|
240
|
+
meta.oldestHistoricBlock = BlockNumber.fromBigInt(BigInt(meta.oldestHistoricBlock));
|
|
240
241
|
meta.size = BigInt(meta.size);
|
|
241
|
-
meta.unfinalizedBlockHeight = BigInt(meta.unfinalizedBlockHeight);
|
|
242
|
+
meta.unfinalizedBlockHeight = BlockNumber.fromBigInt(BigInt(meta.unfinalizedBlockHeight));
|
|
242
243
|
return meta;
|
|
243
244
|
}
|
|
244
245
|
|
|
@@ -282,6 +283,16 @@ interface WithForkId {
|
|
|
282
283
|
forkId: number;
|
|
283
284
|
}
|
|
284
285
|
|
|
286
|
+
interface CreateCheckpointResponse {
|
|
287
|
+
depth: number;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/** Request to commit/revert all checkpoints down to a target depth. The resulting depth after the operation equals the given depth. */
|
|
291
|
+
interface CheckpointDepthRequest extends WithForkId {
|
|
292
|
+
/** The target depth after the operation. All checkpoints above this depth are committed/reverted. */
|
|
293
|
+
depth: number;
|
|
294
|
+
}
|
|
295
|
+
|
|
285
296
|
interface WithWorldStateRevision {
|
|
286
297
|
revision: WorldStateRevision;
|
|
287
298
|
}
|
|
@@ -310,7 +321,7 @@ interface WithLeafValues {
|
|
|
310
321
|
}
|
|
311
322
|
|
|
312
323
|
interface BlockShiftRequest extends WithCanonicalForkId {
|
|
313
|
-
toBlockNumber:
|
|
324
|
+
toBlockNumber: BlockNumber;
|
|
314
325
|
}
|
|
315
326
|
|
|
316
327
|
interface WithLeaves {
|
|
@@ -409,9 +420,9 @@ interface UpdateArchiveRequest extends WithForkId {
|
|
|
409
420
|
}
|
|
410
421
|
|
|
411
422
|
interface SyncBlockRequest extends WithCanonicalForkId {
|
|
412
|
-
blockNumber:
|
|
423
|
+
blockNumber: BlockNumber;
|
|
413
424
|
blockStateRef: BlockStateReference;
|
|
414
|
-
blockHeaderHash:
|
|
425
|
+
blockHeaderHash: Buffer;
|
|
415
426
|
paddedNoteHashes: readonly SerializedLeafValue[];
|
|
416
427
|
paddedL1ToL2Messages: readonly SerializedLeafValue[];
|
|
417
428
|
paddedNullifiers: readonly SerializedLeafValue[];
|
|
@@ -420,7 +431,7 @@ interface SyncBlockRequest extends WithCanonicalForkId {
|
|
|
420
431
|
|
|
421
432
|
interface CreateForkRequest extends WithCanonicalForkId {
|
|
422
433
|
latest: boolean;
|
|
423
|
-
blockNumber:
|
|
434
|
+
blockNumber: BlockNumber;
|
|
424
435
|
}
|
|
425
436
|
|
|
426
437
|
interface CreateForkResponse {
|
|
@@ -485,8 +496,8 @@ export type WorldStateRequest = {
|
|
|
485
496
|
[WorldStateMessageType.CREATE_CHECKPOINT]: WithForkId;
|
|
486
497
|
[WorldStateMessageType.COMMIT_CHECKPOINT]: WithForkId;
|
|
487
498
|
[WorldStateMessageType.REVERT_CHECKPOINT]: WithForkId;
|
|
488
|
-
[WorldStateMessageType.COMMIT_ALL_CHECKPOINTS]:
|
|
489
|
-
[WorldStateMessageType.REVERT_ALL_CHECKPOINTS]:
|
|
499
|
+
[WorldStateMessageType.COMMIT_ALL_CHECKPOINTS]: CheckpointDepthRequest;
|
|
500
|
+
[WorldStateMessageType.REVERT_ALL_CHECKPOINTS]: CheckpointDepthRequest;
|
|
490
501
|
|
|
491
502
|
[WorldStateMessageType.COPY_STORES]: CopyStoresRequest;
|
|
492
503
|
|
|
@@ -527,7 +538,7 @@ export type WorldStateResponse = {
|
|
|
527
538
|
|
|
528
539
|
[WorldStateMessageType.GET_STATUS]: WorldStateStatusSummary;
|
|
529
540
|
|
|
530
|
-
[WorldStateMessageType.CREATE_CHECKPOINT]:
|
|
541
|
+
[WorldStateMessageType.CREATE_CHECKPOINT]: CreateCheckpointResponse;
|
|
531
542
|
[WorldStateMessageType.COMMIT_CHECKPOINT]: void;
|
|
532
543
|
[WorldStateMessageType.REVERT_CHECKPOINT]: void;
|
|
533
544
|
[WorldStateMessageType.COMMIT_ALL_CHECKPOINTS]: void;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
|
|
2
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
3
|
import { fromEntries, padArrayEnd } from '@aztec/foundation/collection';
|
|
4
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
5
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
4
|
-
import { Fr } from '@aztec/foundation/fields';
|
|
5
6
|
import { tryRmDir } from '@aztec/foundation/fs';
|
|
6
|
-
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
7
|
-
import type { L2Block
|
|
8
|
-
import { DatabaseVersionManager } from '@aztec/stdlib/database-version';
|
|
7
|
+
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
8
|
+
import type { L2Block } from '@aztec/stdlib/block';
|
|
9
|
+
import { DatabaseVersionManager } from '@aztec/stdlib/database-version/manager';
|
|
9
10
|
import type {
|
|
10
11
|
IndexedTreeId,
|
|
11
12
|
MerkleTreeReadOperations,
|
|
@@ -13,8 +14,8 @@ import type {
|
|
|
13
14
|
} from '@aztec/stdlib/interfaces/server';
|
|
14
15
|
import type { SnapshotDataKeys } from '@aztec/stdlib/snapshots';
|
|
15
16
|
import { MerkleTreeId, NullifierLeaf, type NullifierLeafPreimage, PublicDataTreeLeaf } from '@aztec/stdlib/trees';
|
|
16
|
-
import { BlockHeader, PartialStateReference, StateReference } from '@aztec/stdlib/tx';
|
|
17
|
-
import { WorldStateRevision } from '@aztec/stdlib/world-state';
|
|
17
|
+
import { BlockHeader, GlobalVariables, PartialStateReference, StateReference } from '@aztec/stdlib/tx';
|
|
18
|
+
import { EMPTY_GENESIS_DATA, type GenesisData, WorldStateRevision } from '@aztec/stdlib/world-state';
|
|
18
19
|
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
19
20
|
|
|
20
21
|
import assert from 'assert/strict';
|
|
@@ -51,7 +52,8 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
51
52
|
protected constructor(
|
|
52
53
|
protected instance: NativeWorldState,
|
|
53
54
|
protected readonly worldStateInstrumentation: WorldStateInstrumentation,
|
|
54
|
-
protected readonly log: Logger
|
|
55
|
+
protected readonly log: Logger,
|
|
56
|
+
private readonly genesis: GenesisData = EMPTY_GENESIS_DATA,
|
|
55
57
|
private readonly cleanup = () => Promise.resolve(),
|
|
56
58
|
) {}
|
|
57
59
|
|
|
@@ -59,11 +61,12 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
59
61
|
rollupAddress: EthAddress,
|
|
60
62
|
dataDir: string,
|
|
61
63
|
wsTreeMapSizes: WorldStateTreeMapSizes,
|
|
62
|
-
|
|
64
|
+
genesis: GenesisData = EMPTY_GENESIS_DATA,
|
|
63
65
|
instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
|
|
64
|
-
|
|
66
|
+
bindings?: LoggerBindings,
|
|
65
67
|
cleanup = () => Promise.resolve(),
|
|
66
68
|
): Promise<NativeWorldStateService> {
|
|
69
|
+
const log = createLogger('world-state:database', bindings);
|
|
67
70
|
const worldStateDirectory = join(dataDir, WORLD_STATE_DIR);
|
|
68
71
|
// Create a version manager to handle versioning
|
|
69
72
|
const versionManager = new DatabaseVersionManager({
|
|
@@ -71,12 +74,12 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
71
74
|
rollupAddress,
|
|
72
75
|
dataDirectory: worldStateDirectory,
|
|
73
76
|
onOpen: (dir: string) => {
|
|
74
|
-
return Promise.resolve(new NativeWorldState(dir, wsTreeMapSizes,
|
|
77
|
+
return Promise.resolve(new NativeWorldState(dir, wsTreeMapSizes, genesis, instrumentation, bindings));
|
|
75
78
|
},
|
|
76
79
|
});
|
|
77
80
|
|
|
78
81
|
const [instance] = await versionManager.open();
|
|
79
|
-
const worldState = new this(instance, instrumentation, log, cleanup);
|
|
82
|
+
const worldState = new this(instance, instrumentation, log, genesis, cleanup);
|
|
80
83
|
try {
|
|
81
84
|
await worldState.init();
|
|
82
85
|
} catch (e) {
|
|
@@ -90,10 +93,11 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
90
93
|
static async tmp(
|
|
91
94
|
rollupAddress = EthAddress.ZERO,
|
|
92
95
|
cleanupTmpDir = true,
|
|
93
|
-
|
|
96
|
+
genesis: GenesisData = EMPTY_GENESIS_DATA,
|
|
94
97
|
instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
|
|
98
|
+
bindings?: LoggerBindings,
|
|
95
99
|
): Promise<NativeWorldStateService> {
|
|
96
|
-
const log = createLogger('world-state:database');
|
|
100
|
+
const log = createLogger('world-state:database', bindings);
|
|
97
101
|
const dataDir = await mkdtemp(join(tmpdir(), 'aztec-world-state-'));
|
|
98
102
|
const dbMapSizeKb = 10 * 1024 * 1024;
|
|
99
103
|
const worldStateTreeMapSizes: WorldStateTreeMapSizes = {
|
|
@@ -115,7 +119,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
115
119
|
}
|
|
116
120
|
};
|
|
117
121
|
|
|
118
|
-
return this.new(rollupAddress, dataDir, worldStateTreeMapSizes,
|
|
122
|
+
return this.new(rollupAddress, dataDir, worldStateTreeMapSizes, genesis, instrumentation, bindings, cleanup);
|
|
119
123
|
}
|
|
120
124
|
|
|
121
125
|
protected async init() {
|
|
@@ -150,7 +154,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
150
154
|
return new MerkleTreesFacade(this.instance, this.initialHeader!, WorldStateRevision.empty());
|
|
151
155
|
}
|
|
152
156
|
|
|
153
|
-
public getSnapshot(blockNumber:
|
|
157
|
+
public getSnapshot(blockNumber: BlockNumber): MerkleTreeReadOperations {
|
|
154
158
|
return new MerkleTreesFacade(
|
|
155
159
|
this.instance,
|
|
156
160
|
this.initialHeader!,
|
|
@@ -158,16 +162,24 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
158
162
|
);
|
|
159
163
|
}
|
|
160
164
|
|
|
161
|
-
public async fork(
|
|
165
|
+
public async fork(
|
|
166
|
+
blockNumber?: BlockNumber,
|
|
167
|
+
opts: { closeDelayMs?: number } = {},
|
|
168
|
+
): Promise<MerkleTreeWriteOperations> {
|
|
162
169
|
const resp = await this.instance.call(WorldStateMessageType.CREATE_FORK, {
|
|
163
170
|
latest: blockNumber === undefined,
|
|
164
|
-
blockNumber: blockNumber ??
|
|
171
|
+
blockNumber: blockNumber ?? BlockNumber.ZERO,
|
|
165
172
|
canonical: true,
|
|
166
173
|
});
|
|
167
174
|
return new MerkleTreesForkFacade(
|
|
168
175
|
this.instance,
|
|
169
176
|
this.initialHeader!,
|
|
170
|
-
new WorldStateRevision(
|
|
177
|
+
new WorldStateRevision(
|
|
178
|
+
/*forkId=*/ resp.forkId,
|
|
179
|
+
/* blockNumber=*/ BlockNumber.ZERO,
|
|
180
|
+
/* includeUncommitted=*/ true,
|
|
181
|
+
),
|
|
182
|
+
opts,
|
|
171
183
|
);
|
|
172
184
|
}
|
|
173
185
|
|
|
@@ -175,21 +187,24 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
175
187
|
return this.initialHeader!;
|
|
176
188
|
}
|
|
177
189
|
|
|
178
|
-
public async handleL2BlockAndMessages(
|
|
179
|
-
l2Block
|
|
180
|
-
l1ToL2Messages
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
);
|
|
190
|
+
public async handleL2BlockAndMessages(l2Block: L2Block, l1ToL2Messages: Fr[]): Promise<WorldStateStatusFull> {
|
|
191
|
+
const isFirstBlock = l2Block.indexWithinCheckpoint === 0;
|
|
192
|
+
if (!isFirstBlock && l1ToL2Messages.length > 0) {
|
|
193
|
+
throw new Error(
|
|
194
|
+
`L1 to L2 messages must be empty for non-first blocks, but got ${l1ToL2Messages.length} messages for block ${l2Block.number}.`,
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// We have to pad the given l1 to l2 messages, and the note hashes and nullifiers within tx effects, because that's
|
|
199
|
+
// how the trees are built by circuits.
|
|
189
200
|
const paddedL1ToL2Messages = isFirstBlock
|
|
190
201
|
? padArrayEnd<Fr, number>(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP)
|
|
191
202
|
: [];
|
|
192
203
|
|
|
204
|
+
const paddedNoteHashes = l2Block.body.txEffects.flatMap(txEffect =>
|
|
205
|
+
padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
|
|
206
|
+
);
|
|
207
|
+
|
|
193
208
|
const paddedNullifiers = l2Block.body.txEffects
|
|
194
209
|
.flatMap(txEffect => padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX))
|
|
195
210
|
.map(nullifier => new NullifierLeaf(nullifier));
|
|
@@ -208,7 +223,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
208
223
|
WorldStateMessageType.SYNC_BLOCK,
|
|
209
224
|
{
|
|
210
225
|
blockNumber: l2Block.number,
|
|
211
|
-
blockHeaderHash: await l2Block.hash(),
|
|
226
|
+
blockHeaderHash: (await l2Block.hash()).toBuffer(),
|
|
212
227
|
paddedL1ToL2Messages: paddedL1ToL2Messages.map(serializeLeaf),
|
|
213
228
|
paddedNoteHashes: paddedNoteHashes.map(serializeLeaf),
|
|
214
229
|
paddedNullifiers: paddedNullifiers.map(serializeLeaf),
|
|
@@ -232,7 +247,10 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
232
247
|
|
|
233
248
|
private async buildInitialHeader(): Promise<BlockHeader> {
|
|
234
249
|
const state = await this.getInitialStateReference();
|
|
235
|
-
return BlockHeader.empty({
|
|
250
|
+
return BlockHeader.empty({
|
|
251
|
+
state,
|
|
252
|
+
globalVariables: GlobalVariables.empty({ timestamp: this.genesis.genesisTimestamp }),
|
|
253
|
+
});
|
|
236
254
|
}
|
|
237
255
|
|
|
238
256
|
private sanitizeAndCacheSummaryFromFull(response: WorldStateStatusFull) {
|
|
@@ -256,7 +274,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
256
274
|
* @param toBlockNumber The block number that is now the tip of the finalized chain
|
|
257
275
|
* @returns The new WorldStateStatus
|
|
258
276
|
*/
|
|
259
|
-
public async setFinalized(toBlockNumber:
|
|
277
|
+
public async setFinalized(toBlockNumber: BlockNumber) {
|
|
260
278
|
try {
|
|
261
279
|
await this.instance.call(
|
|
262
280
|
WorldStateMessageType.FINALIZE_BLOCKS,
|
|
@@ -279,7 +297,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
279
297
|
* @param toBlockNumber The block number of the new oldest historical block
|
|
280
298
|
* @returns The new WorldStateStatus
|
|
281
299
|
*/
|
|
282
|
-
public async removeHistoricalBlocks(toBlockNumber:
|
|
300
|
+
public async removeHistoricalBlocks(toBlockNumber: BlockNumber) {
|
|
283
301
|
try {
|
|
284
302
|
return await this.instance.call(
|
|
285
303
|
WorldStateMessageType.REMOVE_HISTORICAL_BLOCKS,
|
|
@@ -301,7 +319,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
301
319
|
* @param toBlockNumber The block number of the new tip of the pending chain,
|
|
302
320
|
* @returns The new WorldStateStatus
|
|
303
321
|
*/
|
|
304
|
-
public async unwindBlocks(toBlockNumber:
|
|
322
|
+
public async unwindBlocks(toBlockNumber: BlockNumber) {
|
|
305
323
|
try {
|
|
306
324
|
return await this.instance.call(
|
|
307
325
|
WorldStateMessageType.UNWIND_BLOCKS,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ARCHIVE_HEIGHT,
|
|
3
|
-
|
|
3
|
+
DomainSeparator,
|
|
4
4
|
L1_TO_L2_MSG_TREE_HEIGHT,
|
|
5
5
|
MAX_NULLIFIERS_PER_TX,
|
|
6
6
|
MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
@@ -8,10 +8,10 @@ import {
|
|
|
8
8
|
NULLIFIER_TREE_HEIGHT,
|
|
9
9
|
PUBLIC_DATA_TREE_HEIGHT,
|
|
10
10
|
} from '@aztec/constants';
|
|
11
|
-
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
11
|
+
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
12
12
|
import { NativeWorldState as BaseNativeWorldState, MsgpackChannel } from '@aztec/native';
|
|
13
13
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
14
|
-
import type
|
|
14
|
+
import { EMPTY_GENESIS_DATA, type GenesisData } from '@aztec/stdlib/world-state';
|
|
15
15
|
|
|
16
16
|
import assert from 'assert';
|
|
17
17
|
import { cpus } from 'os';
|
|
@@ -55,9 +55,10 @@ export class NativeWorldState implements NativeWorldStateInstance {
|
|
|
55
55
|
constructor(
|
|
56
56
|
private readonly dataDir: string,
|
|
57
57
|
private readonly wsTreeMapSizes: WorldStateTreeMapSizes,
|
|
58
|
-
private readonly
|
|
58
|
+
private readonly genesis: GenesisData = EMPTY_GENESIS_DATA,
|
|
59
59
|
private readonly instrumentation: WorldStateInstrumentation,
|
|
60
|
-
|
|
60
|
+
bindings?: LoggerBindings,
|
|
61
|
+
private readonly log: Logger = createLogger('world-state:database', bindings),
|
|
61
62
|
) {
|
|
62
63
|
const threads = Math.min(cpus().length, MAX_WORLD_STATE_THREADS);
|
|
63
64
|
log.info(
|
|
@@ -65,7 +66,10 @@ export class NativeWorldState implements NativeWorldStateInstance {
|
|
|
65
66
|
wsTreeMapSizes,
|
|
66
67
|
)} and ${threads} threads.`,
|
|
67
68
|
);
|
|
68
|
-
const prefilledPublicDataBufferArray = prefilledPublicData.map(d => [
|
|
69
|
+
const prefilledPublicDataBufferArray = genesis.prefilledPublicData.map(d => [
|
|
70
|
+
d.slot.toBuffer(),
|
|
71
|
+
d.value.toBuffer(),
|
|
72
|
+
]);
|
|
69
73
|
const ws = new BaseNativeWorldState(
|
|
70
74
|
dataDir,
|
|
71
75
|
{
|
|
@@ -80,7 +84,8 @@ export class NativeWorldState implements NativeWorldStateInstance {
|
|
|
80
84
|
[MerkleTreeId.PUBLIC_DATA_TREE]: 2 * MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
81
85
|
},
|
|
82
86
|
prefilledPublicDataBufferArray,
|
|
83
|
-
|
|
87
|
+
DomainSeparator.BLOCK_HEADER_HASH,
|
|
88
|
+
Number(genesis.genesisTimestamp),
|
|
84
89
|
{
|
|
85
90
|
[MerkleTreeId.NULLIFIER_TREE]: wsTreeMapSizes.nullifierTreeMapSizeKb,
|
|
86
91
|
[MerkleTreeId.NOTE_HASH_TREE]: wsTreeMapSizes.noteHashTreeMapSizeKb,
|
|
@@ -103,8 +108,9 @@ export class NativeWorldState implements NativeWorldStateInstance {
|
|
|
103
108
|
return new NativeWorldState(
|
|
104
109
|
this.dataDir,
|
|
105
110
|
this.wsTreeMapSizes,
|
|
106
|
-
this.
|
|
111
|
+
this.genesis,
|
|
107
112
|
this.instrumentation,
|
|
113
|
+
this.log.getBindings(),
|
|
108
114
|
this.log,
|
|
109
115
|
);
|
|
110
116
|
}
|
|
@@ -96,7 +96,7 @@ export class WorldStateOpsQueue {
|
|
|
96
96
|
// then send the request immediately
|
|
97
97
|
// If a mutating request is in flight then we must wait
|
|
98
98
|
// If a mutating request is not in flight but something is queued then it must be a mutating request
|
|
99
|
-
if (this.inFlightMutatingCount
|
|
99
|
+
if (this.inFlightMutatingCount === 0 && this.requests.length === 0) {
|
|
100
100
|
this.sendEnqueuedRequest(op);
|
|
101
101
|
} else {
|
|
102
102
|
this.requests.push(op);
|
|
@@ -122,7 +122,7 @@ export class WorldStateOpsQueue {
|
|
|
122
122
|
--this.inFlightCount;
|
|
123
123
|
|
|
124
124
|
// If there are still requests in flight then do nothing further
|
|
125
|
-
if (this.inFlightCount
|
|
125
|
+
if (this.inFlightCount !== 0) {
|
|
126
126
|
return;
|
|
127
127
|
}
|
|
128
128
|
|
|
@@ -134,7 +134,7 @@ export class WorldStateOpsQueue {
|
|
|
134
134
|
while (this.requests.length > 0) {
|
|
135
135
|
const next = this.requests[0];
|
|
136
136
|
if (next.mutating) {
|
|
137
|
-
if (this.inFlightCount
|
|
137
|
+
if (this.inFlightCount === 0) {
|
|
138
138
|
// send the mutating request
|
|
139
139
|
this.requests.shift();
|
|
140
140
|
this.sendEnqueuedRequest(next);
|
|
@@ -149,7 +149,7 @@ export class WorldStateOpsQueue {
|
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
// If the queue is empty, there is nothing in flight and we have been told to stop, then resolve the stop promise
|
|
152
|
-
if (this.inFlightCount
|
|
152
|
+
if (this.inFlightCount === 0 && this.stopResolve !== undefined) {
|
|
153
153
|
this.stopResolve();
|
|
154
154
|
}
|
|
155
155
|
}
|
|
@@ -182,7 +182,7 @@ export class WorldStateOpsQueue {
|
|
|
182
182
|
});
|
|
183
183
|
|
|
184
184
|
// If no outstanding requests then immediately resolve the promise
|
|
185
|
-
if (this.requests.length
|
|
185
|
+
if (this.requests.length === 0 && this.inFlightCount === 0 && this.stopResolve !== undefined) {
|
|
186
186
|
this.stopResolve();
|
|
187
187
|
}
|
|
188
188
|
return this.stopPromise;
|
|
@@ -1,18 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type ConfigMappingsType,
|
|
3
|
-
booleanConfigHelper,
|
|
4
|
-
getConfigFromMappings,
|
|
5
|
-
numberConfigHelper,
|
|
6
|
-
} from '@aztec/foundation/config';
|
|
1
|
+
import { type ConfigMappingsType, getConfigFromMappings, numberConfigHelper } from '@aztec/foundation/config';
|
|
7
2
|
|
|
8
3
|
/** World State synchronizer configuration values. */
|
|
9
4
|
export interface WorldStateConfig {
|
|
10
5
|
/** The frequency in which to check. */
|
|
11
6
|
worldStateBlockCheckIntervalMS: number;
|
|
12
7
|
|
|
13
|
-
/** Whether to follow only the proven chain. */
|
|
14
|
-
worldStateProvenBlocksOnly: boolean;
|
|
15
|
-
|
|
16
8
|
/** Size of the batch for each get-blocks request from the synchronizer to the archiver. */
|
|
17
9
|
worldStateBlockRequestBatchSize?: number;
|
|
18
10
|
|
|
@@ -37,8 +29,8 @@ export interface WorldStateConfig {
|
|
|
37
29
|
/** Optional directory for the world state DB, if unspecified will default to the general data directory */
|
|
38
30
|
worldStateDataDirectory?: string;
|
|
39
31
|
|
|
40
|
-
/** The number of historic blocks to maintain */
|
|
41
|
-
|
|
32
|
+
/** The number of historic checkpoints worth of blocks to maintain */
|
|
33
|
+
worldStateCheckpointHistory: number;
|
|
42
34
|
}
|
|
43
35
|
|
|
44
36
|
export const worldStateConfigMappings: ConfigMappingsType<WorldStateConfig> = {
|
|
@@ -48,48 +40,43 @@ export const worldStateConfigMappings: ConfigMappingsType<WorldStateConfig> = {
|
|
|
48
40
|
defaultValue: 100,
|
|
49
41
|
description: 'The frequency in which to check.',
|
|
50
42
|
},
|
|
51
|
-
worldStateProvenBlocksOnly: {
|
|
52
|
-
env: 'WS_PROVEN_BLOCKS_ONLY',
|
|
53
|
-
description: 'Whether to follow only the proven chain.',
|
|
54
|
-
...booleanConfigHelper(),
|
|
55
|
-
},
|
|
56
43
|
worldStateBlockRequestBatchSize: {
|
|
57
44
|
env: 'WS_BLOCK_REQUEST_BATCH_SIZE',
|
|
58
|
-
parseEnv: (val: string
|
|
45
|
+
parseEnv: (val: string) => +val,
|
|
59
46
|
description: 'Size of the batch for each get-blocks request from the synchronizer to the archiver.',
|
|
60
47
|
},
|
|
61
48
|
worldStateDbMapSizeKb: {
|
|
62
49
|
env: 'WS_DB_MAP_SIZE_KB',
|
|
63
|
-
parseEnv: (val: string
|
|
50
|
+
parseEnv: (val: string) => +val,
|
|
64
51
|
description: 'The maximum possible size of the world state DB in KB. Overwrites the general dataStoreMapSizeKb.',
|
|
65
52
|
},
|
|
66
53
|
archiveTreeMapSizeKb: {
|
|
67
54
|
env: 'ARCHIVE_TREE_MAP_SIZE_KB',
|
|
68
|
-
parseEnv: (val: string
|
|
55
|
+
parseEnv: (val: string) => +val,
|
|
69
56
|
description:
|
|
70
57
|
'The maximum possible size of the world state archive tree in KB. Overwrites the general worldStateDbMapSizeKb.',
|
|
71
58
|
},
|
|
72
59
|
nullifierTreeMapSizeKb: {
|
|
73
60
|
env: 'NULLIFIER_TREE_MAP_SIZE_KB',
|
|
74
|
-
parseEnv: (val: string
|
|
61
|
+
parseEnv: (val: string) => +val,
|
|
75
62
|
description:
|
|
76
63
|
'The maximum possible size of the world state nullifier tree in KB. Overwrites the general worldStateDbMapSizeKb.',
|
|
77
64
|
},
|
|
78
65
|
noteHashTreeMapSizeKb: {
|
|
79
66
|
env: 'NOTE_HASH_TREE_MAP_SIZE_KB',
|
|
80
|
-
parseEnv: (val: string
|
|
67
|
+
parseEnv: (val: string) => +val,
|
|
81
68
|
description:
|
|
82
69
|
'The maximum possible size of the world state note hash tree in KB. Overwrites the general worldStateDbMapSizeKb.',
|
|
83
70
|
},
|
|
84
71
|
messageTreeMapSizeKb: {
|
|
85
72
|
env: 'MESSAGE_TREE_MAP_SIZE_KB',
|
|
86
|
-
parseEnv: (val: string
|
|
73
|
+
parseEnv: (val: string) => +val,
|
|
87
74
|
description:
|
|
88
75
|
'The maximum possible size of the world state message tree in KB. Overwrites the general worldStateDbMapSizeKb.',
|
|
89
76
|
},
|
|
90
77
|
publicDataTreeMapSizeKb: {
|
|
91
78
|
env: 'PUBLIC_DATA_TREE_MAP_SIZE_KB',
|
|
92
|
-
parseEnv: (val: string
|
|
79
|
+
parseEnv: (val: string) => +val,
|
|
93
80
|
description:
|
|
94
81
|
'The maximum possible size of the world state public data tree in KB. Overwrites the general worldStateDbMapSizeKb.',
|
|
95
82
|
},
|
|
@@ -97,9 +84,11 @@ export const worldStateConfigMappings: ConfigMappingsType<WorldStateConfig> = {
|
|
|
97
84
|
env: 'WS_DATA_DIRECTORY',
|
|
98
85
|
description: 'Optional directory for the world state database',
|
|
99
86
|
},
|
|
100
|
-
|
|
101
|
-
env: '
|
|
102
|
-
description:
|
|
87
|
+
worldStateCheckpointHistory: {
|
|
88
|
+
env: 'WS_NUM_HISTORIC_CHECKPOINTS',
|
|
89
|
+
description:
|
|
90
|
+
'The number of historic checkpoints worth of blocks to maintain. Values less than 1 mean all history is maintained',
|
|
91
|
+
fallback: ['WS_NUM_HISTORIC_BLOCKS'],
|
|
103
92
|
...numberConfigHelper(64),
|
|
104
93
|
},
|
|
105
94
|
};
|
|
@@ -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 { EMPTY_GENESIS_DATA, type GenesisData } from '@aztec/stdlib/world-state';
|
|
5
6
|
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
|
|
6
7
|
|
|
7
8
|
import { WorldStateInstrumentation } from '../instrumentation/instrumentation.js';
|
|
@@ -20,11 +21,12 @@ export interface WorldStateTreeMapSizes {
|
|
|
20
21
|
export async function createWorldStateSynchronizer(
|
|
21
22
|
config: WorldStateConfig & DataStoreConfig,
|
|
22
23
|
l2BlockSource: L2BlockSource & L1ToL2MessageSource,
|
|
23
|
-
|
|
24
|
+
genesis: GenesisData = EMPTY_GENESIS_DATA,
|
|
24
25
|
client: TelemetryClient = getTelemetryClient(),
|
|
26
|
+
bindings?: LoggerBindings,
|
|
25
27
|
) {
|
|
26
28
|
const instrumentation = new WorldStateInstrumentation(client);
|
|
27
|
-
const merkleTrees = await createWorldState(config,
|
|
29
|
+
const merkleTrees = await createWorldState(config, genesis, instrumentation, bindings);
|
|
28
30
|
return new ServerWorldStateSynchronizer(merkleTrees, l2BlockSource, config, instrumentation);
|
|
29
31
|
}
|
|
30
32
|
|
|
@@ -40,8 +42,9 @@ export async function createWorldState(
|
|
|
40
42
|
| 'publicDataTreeMapSizeKb'
|
|
41
43
|
> &
|
|
42
44
|
Pick<DataStoreConfig, 'dataDirectory' | 'dataStoreMapSizeKb' | 'l1Contracts'>,
|
|
43
|
-
|
|
45
|
+
genesis: GenesisData = EMPTY_GENESIS_DATA,
|
|
44
46
|
instrumentation: WorldStateInstrumentation = new WorldStateInstrumentation(getTelemetryClient()),
|
|
47
|
+
bindings?: LoggerBindings,
|
|
45
48
|
) {
|
|
46
49
|
const dataDirectory = config.worldStateDataDirectory ?? config.dataDirectory;
|
|
47
50
|
const dataStoreMapSizeKb = config.worldStateDbMapSizeKb ?? config.dataStoreMapSizeKb;
|
|
@@ -63,13 +66,16 @@ export async function createWorldState(
|
|
|
63
66
|
config.l1Contracts.rollupAddress,
|
|
64
67
|
dataDirectory,
|
|
65
68
|
wsTreeMapSizes,
|
|
66
|
-
|
|
69
|
+
genesis,
|
|
67
70
|
instrumentation,
|
|
71
|
+
bindings,
|
|
68
72
|
)
|
|
69
73
|
: await NativeWorldStateService.tmp(
|
|
70
74
|
config.l1Contracts.rollupAddress,
|
|
71
75
|
!['true', '1'].includes(process.env.DEBUG_WORLD_STATE!),
|
|
72
|
-
|
|
76
|
+
genesis,
|
|
77
|
+
instrumentation,
|
|
78
|
+
bindings,
|
|
73
79
|
);
|
|
74
80
|
|
|
75
81
|
return merkleTrees;
|