@aztec/world-state 0.0.1-commit.b655e406 → 0.0.1-commit.b9865e97
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/index.d.ts +1 -1
- package/dest/instrumentation/instrumentation.d.ts +4 -3
- package/dest/instrumentation/instrumentation.d.ts.map +1 -1
- package/dest/instrumentation/instrumentation.js +21 -50
- package/dest/native/bench_metrics.d.ts +1 -1
- package/dest/native/bench_metrics.d.ts.map +1 -1
- 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/index.d.ts +1 -1
- package/dest/native/ipc_world_state_instance.d.ts +87 -0
- package/dest/native/ipc_world_state_instance.d.ts.map +1 -0
- package/dest/native/ipc_world_state_instance.js +660 -0
- package/dest/native/merkle_trees_facade.d.ts +18 -8
- package/dest/native/merkle_trees_facade.d.ts.map +1 -1
- package/dest/native/merkle_trees_facade.js +90 -111
- package/dest/native/message.d.ts +22 -228
- package/dest/native/message.d.ts.map +1 -1
- package/dest/native/message.js +14 -55
- package/dest/native/native_world_state.d.ts +30 -15
- package/dest/native/native_world_state.d.ts.map +1 -1
- package/dest/native/native_world_state.js +126 -66
- package/dest/native/native_world_state_instance.d.ts +58 -32
- package/dest/native/native_world_state_instance.d.ts.map +1 -1
- package/dest/native/native_world_state_instance.js +5 -181
- package/dest/native/world_state_operation.d.ts +7 -0
- package/dest/native/world_state_operation.d.ts.map +1 -0
- package/dest/native/world_state_operation.js +5 -0
- package/dest/synchronizer/config.d.ts +3 -5
- package/dest/synchronizer/config.d.ts.map +1 -1
- package/dest/synchronizer/config.js +15 -18
- package/dest/synchronizer/errors.d.ts +1 -1
- package/dest/synchronizer/errors.d.ts.map +1 -1
- package/dest/synchronizer/factory.d.ts +6 -5
- package/dest/synchronizer/factory.d.ts.map +1 -1
- package/dest/synchronizer/factory.js +7 -6
- package/dest/synchronizer/index.d.ts +1 -1
- package/dest/synchronizer/server_world_state_synchronizer.d.ts +11 -28
- package/dest/synchronizer/server_world_state_synchronizer.d.ts.map +1 -1
- package/dest/synchronizer/server_world_state_synchronizer.js +165 -81
- package/dest/test/index.d.ts +1 -1
- 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/index.d.ts +1 -1
- package/dest/world-state-db/merkle_tree_db.d.ts +9 -19
- package/dest/world-state-db/merkle_tree_db.d.ts.map +1 -1
- package/package.json +17 -13
- package/src/instrumentation/instrumentation.ts +23 -59
- package/src/native/fork_checkpoint.ts +19 -3
- package/src/native/ipc_world_state_instance.ts +830 -0
- package/src/native/merkle_trees_facade.ts +118 -104
- package/src/native/message.ts +33 -305
- package/src/native/native_world_state.ts +164 -108
- package/src/native/native_world_state_instance.ts +96 -250
- package/src/native/world_state_operation.ts +33 -0
- package/src/synchronizer/config.ts +16 -23
- package/src/synchronizer/factory.ts +18 -11
- package/src/synchronizer/server_world_state_synchronizer.ts +181 -106
- package/src/test/utils.ts +87 -92
- package/src/testing.ts +9 -10
- package/src/world-state-db/merkle_tree_db.ts +12 -19
- package/dest/native/world_state_ops_queue.d.ts +0 -19
- package/dest/native/world_state_ops_queue.d.ts.map +0 -1
- package/dest/native/world_state_ops_queue.js +0 -146
- package/src/native/world_state_ops_queue.ts +0 -190
|
@@ -1,11 +1,11 @@
|
|
|
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 {
|
|
5
|
-
import { tryRmDir } from '@aztec/foundation/fs';
|
|
6
|
-
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
6
|
+
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
7
7
|
import type { L2Block } from '@aztec/stdlib/block';
|
|
8
|
-
import { DatabaseVersionManager } from '@aztec/stdlib/database-version';
|
|
8
|
+
import { DatabaseVersionManager } from '@aztec/stdlib/database-version/manager';
|
|
9
9
|
import type {
|
|
10
10
|
IndexedTreeId,
|
|
11
11
|
MerkleTreeReadOperations,
|
|
@@ -13,21 +13,21 @@ import type {
|
|
|
13
13
|
} from '@aztec/stdlib/interfaces/server';
|
|
14
14
|
import type { SnapshotDataKeys } from '@aztec/stdlib/snapshots';
|
|
15
15
|
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';
|
|
16
|
+
import { BlockHeader, GlobalVariables, PartialStateReference, StateReference } from '@aztec/stdlib/tx';
|
|
17
|
+
import { EMPTY_GENESIS_DATA, type GenesisData, WorldStateRevision } from '@aztec/stdlib/world-state';
|
|
18
18
|
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
19
19
|
|
|
20
20
|
import assert from 'assert/strict';
|
|
21
|
-
import { mkdtemp, rm } from 'fs/promises';
|
|
21
|
+
import { mkdir, mkdtemp, rm } from 'fs/promises';
|
|
22
22
|
import { tmpdir } from 'os';
|
|
23
23
|
import { join } from 'path';
|
|
24
24
|
|
|
25
25
|
import { WorldStateInstrumentation } from '../instrumentation/instrumentation.js';
|
|
26
26
|
import type { WorldStateTreeMapSizes } from '../synchronizer/factory.js';
|
|
27
27
|
import type { MerkleTreeAdminDatabase as MerkleTreeDatabase } from '../world-state-db/merkle_tree_db.js';
|
|
28
|
+
import { IpcWorldState } from './ipc_world_state_instance.js';
|
|
28
29
|
import { MerkleTreesFacade, MerkleTreesForkFacade, serializeLeaf } from './merkle_trees_facade.js';
|
|
29
30
|
import {
|
|
30
|
-
WorldStateMessageType,
|
|
31
31
|
type WorldStateStatusFull,
|
|
32
32
|
type WorldStateStatusSummary,
|
|
33
33
|
blockStateReference,
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
sanitizeSummary,
|
|
36
36
|
treeStateReferenceToSnapshot,
|
|
37
37
|
} from './message.js';
|
|
38
|
-
import {
|
|
38
|
+
import type { NativeWorldStateInstance } from './native_world_state_instance.js';
|
|
39
39
|
|
|
40
40
|
// The current version of the world state database schema
|
|
41
41
|
// Increment this when making incompatible changes to the database schema
|
|
@@ -49,34 +49,49 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
49
49
|
private cachedStatusSummary: WorldStateStatusSummary | undefined;
|
|
50
50
|
|
|
51
51
|
protected constructor(
|
|
52
|
-
protected instance:
|
|
52
|
+
protected instance: NativeWorldStateInstance,
|
|
53
53
|
protected readonly worldStateInstrumentation: WorldStateInstrumentation,
|
|
54
|
-
protected readonly log: Logger
|
|
54
|
+
protected readonly log: Logger,
|
|
55
|
+
private readonly genesis: GenesisData = EMPTY_GENESIS_DATA,
|
|
55
56
|
private readonly cleanup = () => Promise.resolve(),
|
|
57
|
+
/** Factory to recreate a fresh IpcWorldState after clear(). */
|
|
58
|
+
private readonly recreateInstance?: () => Promise<NativeWorldStateInstance>,
|
|
56
59
|
) {}
|
|
57
60
|
|
|
58
61
|
static async new(
|
|
59
62
|
rollupAddress: EthAddress,
|
|
60
63
|
dataDir: string,
|
|
61
64
|
wsTreeMapSizes: WorldStateTreeMapSizes,
|
|
62
|
-
|
|
65
|
+
genesis: GenesisData = EMPTY_GENESIS_DATA,
|
|
63
66
|
instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
|
|
64
|
-
|
|
67
|
+
bindings?: LoggerBindings,
|
|
65
68
|
cleanup = () => Promise.resolve(),
|
|
66
69
|
): Promise<NativeWorldStateService> {
|
|
70
|
+
for (const [key, value] of Object.entries(wsTreeMapSizes)) {
|
|
71
|
+
if (value <= 0) {
|
|
72
|
+
throw new Error(`Map size must be a positive number, got ${value} for ${key}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const log = createLogger('world-state:database', bindings);
|
|
67
77
|
const worldStateDirectory = join(dataDir, WORLD_STATE_DIR);
|
|
68
|
-
|
|
78
|
+
|
|
69
79
|
const versionManager = new DatabaseVersionManager({
|
|
70
80
|
schemaVersion: WORLD_STATE_DB_VERSION,
|
|
71
81
|
rollupAddress,
|
|
72
82
|
dataDirectory: worldStateDirectory,
|
|
73
|
-
onOpen: (dir
|
|
74
|
-
return Promise.resolve(new NativeWorldState(dir, wsTreeMapSizes, prefilledPublicData, instrumentation));
|
|
75
|
-
},
|
|
83
|
+
onOpen: dir => IpcWorldState.spawn(dir, wsTreeMapSizes, genesis, instrumentation, bindings),
|
|
76
84
|
});
|
|
77
85
|
|
|
78
86
|
const [instance] = await versionManager.open();
|
|
79
|
-
|
|
87
|
+
|
|
88
|
+
const recreateInstance = async () => {
|
|
89
|
+
await rm(worldStateDirectory, { recursive: true, force: true, maxRetries: 3 });
|
|
90
|
+
await mkdir(worldStateDirectory, { recursive: true });
|
|
91
|
+
return IpcWorldState.spawn(worldStateDirectory, wsTreeMapSizes, genesis, instrumentation, bindings);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const worldState = new this(instance, instrumentation, log, genesis, cleanup, recreateInstance);
|
|
80
95
|
try {
|
|
81
96
|
await worldState.init();
|
|
82
97
|
} catch (e) {
|
|
@@ -88,14 +103,18 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
88
103
|
}
|
|
89
104
|
|
|
90
105
|
static async tmp(
|
|
91
|
-
rollupAddress = EthAddress.ZERO,
|
|
92
106
|
cleanupTmpDir = true,
|
|
93
|
-
|
|
107
|
+
genesis: GenesisData = EMPTY_GENESIS_DATA,
|
|
94
108
|
instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
|
|
109
|
+
bindings?: LoggerBindings,
|
|
95
110
|
): Promise<NativeWorldStateService> {
|
|
96
|
-
const log = createLogger('world-state:database');
|
|
111
|
+
const log = createLogger('world-state:database', bindings);
|
|
97
112
|
const dataDir = await mkdtemp(join(tmpdir(), 'aztec-world-state-'));
|
|
98
|
-
|
|
113
|
+
// Temporary (test/dev) world states are small and short-lived. Keep the LMDB
|
|
114
|
+
// map sizes in the MB range: with the IPC backend each tmp() spawns a separate
|
|
115
|
+
// aztec-wsdb that maps these per tree, and oversized maps add real cold-start
|
|
116
|
+
// I/O under parallel CI load. 256 MB/tree is ample for tests.
|
|
117
|
+
const dbMapSizeKb = 256 * 1024;
|
|
99
118
|
const worldStateTreeMapSizes: WorldStateTreeMapSizes = {
|
|
100
119
|
archiveTreeMapSizeKb: dbMapSizeKb,
|
|
101
120
|
nullifierTreeMapSizeKb: dbMapSizeKb,
|
|
@@ -105,7 +124,8 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
105
124
|
};
|
|
106
125
|
log.debug(`Created temporary world state database at: ${dataDir} with tree map size: ${dbMapSizeKb}`);
|
|
107
126
|
|
|
108
|
-
|
|
127
|
+
const instance = await IpcWorldState.spawn(dataDir, worldStateTreeMapSizes, genesis, instrumentation, bindings);
|
|
128
|
+
|
|
109
129
|
const cleanup = async () => {
|
|
110
130
|
if (cleanupTmpDir) {
|
|
111
131
|
await rm(dataDir, { recursive: true, force: true, maxRetries: 3 });
|
|
@@ -115,7 +135,43 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
115
135
|
}
|
|
116
136
|
};
|
|
117
137
|
|
|
118
|
-
|
|
138
|
+
const recreateInstance = async () => {
|
|
139
|
+
await rm(dataDir, { recursive: true, force: true, maxRetries: 3 });
|
|
140
|
+
await mkdir(dataDir, { recursive: true });
|
|
141
|
+
return IpcWorldState.spawn(dataDir, worldStateTreeMapSizes, genesis, instrumentation, bindings);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const worldState = new this(instance, instrumentation, log, genesis, cleanup, recreateInstance);
|
|
145
|
+
try {
|
|
146
|
+
await worldState.init();
|
|
147
|
+
} catch (e) {
|
|
148
|
+
log.error(`Error initializing tmp world state: ${e}`);
|
|
149
|
+
throw e;
|
|
150
|
+
}
|
|
151
|
+
return worldState;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
static ephemeral(
|
|
155
|
+
genesis: GenesisData = EMPTY_GENESIS_DATA,
|
|
156
|
+
instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
|
|
157
|
+
bindings?: LoggerBindings,
|
|
158
|
+
): Promise<NativeWorldStateService> {
|
|
159
|
+
return this.tmp(/*cleanupTmpDir=*/ true, genesis, instrumentation, bindings);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
static async fromIpc(
|
|
163
|
+
wsdbBackend: ConstructorParameters<typeof IpcWorldState>[0],
|
|
164
|
+
instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
|
|
165
|
+
bindings?: LoggerBindings,
|
|
166
|
+
genesis: GenesisData = EMPTY_GENESIS_DATA,
|
|
167
|
+
cleanup = () => Promise.resolve(),
|
|
168
|
+
recreateInstance?: () => Promise<NativeWorldStateInstance>,
|
|
169
|
+
): Promise<NativeWorldStateService> {
|
|
170
|
+
const log = createLogger('world-state:database', bindings);
|
|
171
|
+
const instance = new IpcWorldState(wsdbBackend, instrumentation, bindings);
|
|
172
|
+
const worldState = new this(instance, instrumentation, log, genesis, cleanup, recreateInstance);
|
|
173
|
+
await worldState.init();
|
|
174
|
+
return worldState;
|
|
119
175
|
}
|
|
120
176
|
|
|
121
177
|
protected async init() {
|
|
@@ -139,18 +195,31 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
139
195
|
assert.strictEqual(initialHeaderIndex, 0n, 'Invalid initial archive state');
|
|
140
196
|
}
|
|
141
197
|
|
|
142
|
-
public async clear() {
|
|
198
|
+
public async clear(): Promise<void> {
|
|
199
|
+
if (!this.recreateInstance) {
|
|
200
|
+
throw new Error('clear() is not available for externally-managed IPC backends');
|
|
201
|
+
}
|
|
202
|
+
this.log.warn('Clearing world state: shutting down WSDB, deleting data, and recreating');
|
|
143
203
|
await this.instance.close();
|
|
144
204
|
this.cachedStatusSummary = undefined;
|
|
145
|
-
|
|
146
|
-
|
|
205
|
+
this.instance = await this.recreateInstance();
|
|
206
|
+
await this.init();
|
|
207
|
+
this.log.info('World state cleared and reinitialized from genesis');
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** Returns the IPC path of the underlying IPC backend, if available. */
|
|
211
|
+
public getIpcPath(): string {
|
|
212
|
+
if (this.instance instanceof IpcWorldState) {
|
|
213
|
+
return this.instance.getIpcPath();
|
|
214
|
+
}
|
|
215
|
+
throw new Error('getIpcPath() is only available with IPC world state');
|
|
147
216
|
}
|
|
148
217
|
|
|
149
218
|
public getCommitted(): MerkleTreeReadOperations {
|
|
150
219
|
return new MerkleTreesFacade(this.instance, this.initialHeader!, WorldStateRevision.empty());
|
|
151
220
|
}
|
|
152
221
|
|
|
153
|
-
public getSnapshot(blockNumber:
|
|
222
|
+
public getSnapshot(blockNumber: BlockNumber): MerkleTreeReadOperations {
|
|
154
223
|
return new MerkleTreesFacade(
|
|
155
224
|
this.instance,
|
|
156
225
|
this.initialHeader!,
|
|
@@ -158,16 +227,23 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
158
227
|
);
|
|
159
228
|
}
|
|
160
229
|
|
|
161
|
-
public async fork(
|
|
162
|
-
|
|
230
|
+
public async fork(
|
|
231
|
+
blockNumber?: BlockNumber,
|
|
232
|
+
opts: { closeDelayMs?: number } = {},
|
|
233
|
+
): Promise<MerkleTreeWriteOperations> {
|
|
234
|
+
const forkId = await this.instance.createFork({
|
|
163
235
|
latest: blockNumber === undefined,
|
|
164
|
-
blockNumber: blockNumber ??
|
|
165
|
-
canonical: true,
|
|
236
|
+
blockNumber: blockNumber ?? BlockNumber.ZERO,
|
|
166
237
|
});
|
|
167
238
|
return new MerkleTreesForkFacade(
|
|
168
239
|
this.instance,
|
|
169
240
|
this.initialHeader!,
|
|
170
|
-
new WorldStateRevision(
|
|
241
|
+
new WorldStateRevision(
|
|
242
|
+
/*forkId=*/ forkId,
|
|
243
|
+
/* blockNumber=*/ WorldStateRevision.LATEST,
|
|
244
|
+
/* includeUncommitted=*/ true,
|
|
245
|
+
),
|
|
246
|
+
opts,
|
|
171
247
|
);
|
|
172
248
|
}
|
|
173
249
|
|
|
@@ -175,21 +251,24 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
175
251
|
return this.initialHeader!;
|
|
176
252
|
}
|
|
177
253
|
|
|
178
|
-
public async handleL2BlockAndMessages(
|
|
179
|
-
l2Block
|
|
180
|
-
l1ToL2Messages
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
);
|
|
254
|
+
public async handleL2BlockAndMessages(l2Block: L2Block, l1ToL2Messages: Fr[]): Promise<WorldStateStatusFull> {
|
|
255
|
+
const isFirstBlock = l2Block.indexWithinCheckpoint === 0;
|
|
256
|
+
if (!isFirstBlock && l1ToL2Messages.length > 0) {
|
|
257
|
+
throw new Error(
|
|
258
|
+
`L1 to L2 messages must be empty for non-first blocks, but got ${l1ToL2Messages.length} messages for block ${l2Block.number}.`,
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// We have to pad the given l1 to l2 messages, and the note hashes and nullifiers within tx effects, because that's
|
|
263
|
+
// how the trees are built by circuits.
|
|
189
264
|
const paddedL1ToL2Messages = isFirstBlock
|
|
190
265
|
? padArrayEnd<Fr, number>(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP)
|
|
191
266
|
: [];
|
|
192
267
|
|
|
268
|
+
const paddedNoteHashes = l2Block.body.txEffects.flatMap(txEffect =>
|
|
269
|
+
padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
|
|
270
|
+
);
|
|
271
|
+
|
|
193
272
|
const paddedNullifiers = l2Block.body.txEffects
|
|
194
273
|
.flatMap(txEffect => padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX))
|
|
195
274
|
.map(nullifier => new NullifierLeaf(nullifier));
|
|
@@ -204,35 +283,41 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
204
283
|
});
|
|
205
284
|
|
|
206
285
|
try {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
canonical: true,
|
|
218
|
-
},
|
|
219
|
-
this.sanitizeAndCacheSummaryFromFull.bind(this),
|
|
220
|
-
this.deleteCachedSummary.bind(this),
|
|
221
|
-
);
|
|
286
|
+
const status = await this.instance.syncBlock({
|
|
287
|
+
blockNumber: l2Block.number,
|
|
288
|
+
blockHeaderHash: (await l2Block.hash()).toBuffer(),
|
|
289
|
+
paddedL1ToL2Messages: paddedL1ToL2Messages.map(serializeLeaf),
|
|
290
|
+
paddedNoteHashes: paddedNoteHashes.map(serializeLeaf),
|
|
291
|
+
paddedNullifiers: paddedNullifiers.map(serializeLeaf),
|
|
292
|
+
publicDataWrites: publicDataWrites.map(serializeLeaf),
|
|
293
|
+
blockStateRef: blockStateReference(l2Block.header.state),
|
|
294
|
+
});
|
|
295
|
+
return this.sanitizeAndCacheSummaryFromFull(status);
|
|
222
296
|
} catch (err) {
|
|
297
|
+
this.deleteCachedSummary();
|
|
223
298
|
this.worldStateInstrumentation.incCriticalErrors('synch_pending_block');
|
|
224
299
|
throw err;
|
|
225
300
|
}
|
|
226
301
|
}
|
|
227
302
|
|
|
228
303
|
public async close(): Promise<void> {
|
|
229
|
-
|
|
230
|
-
|
|
304
|
+
try {
|
|
305
|
+
await this.instance.close();
|
|
306
|
+
} finally {
|
|
307
|
+
await this.cleanup();
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
async [Symbol.asyncDispose](): Promise<void> {
|
|
312
|
+
await this.close();
|
|
231
313
|
}
|
|
232
314
|
|
|
233
315
|
private async buildInitialHeader(): Promise<BlockHeader> {
|
|
234
316
|
const state = await this.getInitialStateReference();
|
|
235
|
-
return BlockHeader.empty({
|
|
317
|
+
return BlockHeader.empty({
|
|
318
|
+
state,
|
|
319
|
+
globalVariables: GlobalVariables.empty({ timestamp: this.genesis.genesisTimestamp }),
|
|
320
|
+
});
|
|
236
321
|
}
|
|
237
322
|
|
|
238
323
|
private sanitizeAndCacheSummaryFromFull(response: WorldStateStatusFull) {
|
|
@@ -247,7 +332,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
247
332
|
return sanitized;
|
|
248
333
|
}
|
|
249
334
|
|
|
250
|
-
private deleteCachedSummary(
|
|
335
|
+
private deleteCachedSummary() {
|
|
251
336
|
this.cachedStatusSummary = undefined;
|
|
252
337
|
}
|
|
253
338
|
|
|
@@ -256,18 +341,11 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
256
341
|
* @param toBlockNumber The block number that is now the tip of the finalized chain
|
|
257
342
|
* @returns The new WorldStateStatus
|
|
258
343
|
*/
|
|
259
|
-
public async setFinalized(toBlockNumber:
|
|
344
|
+
public async setFinalized(toBlockNumber: BlockNumber) {
|
|
260
345
|
try {
|
|
261
|
-
await this.instance.
|
|
262
|
-
WorldStateMessageType.FINALIZE_BLOCKS,
|
|
263
|
-
{
|
|
264
|
-
toBlockNumber,
|
|
265
|
-
canonical: true,
|
|
266
|
-
},
|
|
267
|
-
this.sanitizeAndCacheSummary.bind(this),
|
|
268
|
-
this.deleteCachedSummary.bind(this),
|
|
269
|
-
);
|
|
346
|
+
this.sanitizeAndCacheSummary(await this.instance.finalizeBlocks(toBlockNumber));
|
|
270
347
|
} catch (err) {
|
|
348
|
+
this.deleteCachedSummary();
|
|
271
349
|
this.worldStateInstrumentation.incCriticalErrors('finalize_block');
|
|
272
350
|
throw err;
|
|
273
351
|
}
|
|
@@ -279,18 +357,11 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
279
357
|
* @param toBlockNumber The block number of the new oldest historical block
|
|
280
358
|
* @returns The new WorldStateStatus
|
|
281
359
|
*/
|
|
282
|
-
public async removeHistoricalBlocks(toBlockNumber:
|
|
360
|
+
public async removeHistoricalBlocks(toBlockNumber: BlockNumber) {
|
|
283
361
|
try {
|
|
284
|
-
return await this.instance.
|
|
285
|
-
WorldStateMessageType.REMOVE_HISTORICAL_BLOCKS,
|
|
286
|
-
{
|
|
287
|
-
toBlockNumber,
|
|
288
|
-
canonical: true,
|
|
289
|
-
},
|
|
290
|
-
this.sanitizeAndCacheSummaryFromFull.bind(this),
|
|
291
|
-
this.deleteCachedSummary.bind(this),
|
|
292
|
-
);
|
|
362
|
+
return this.sanitizeAndCacheSummaryFromFull(await this.instance.removeHistoricalBlocks(toBlockNumber));
|
|
293
363
|
} catch (err) {
|
|
364
|
+
this.deleteCachedSummary();
|
|
294
365
|
this.worldStateInstrumentation.incCriticalErrors('prune_historical_block');
|
|
295
366
|
throw err;
|
|
296
367
|
}
|
|
@@ -301,18 +372,11 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
301
372
|
* @param toBlockNumber The block number of the new tip of the pending chain,
|
|
302
373
|
* @returns The new WorldStateStatus
|
|
303
374
|
*/
|
|
304
|
-
public async unwindBlocks(toBlockNumber:
|
|
375
|
+
public async unwindBlocks(toBlockNumber: BlockNumber) {
|
|
305
376
|
try {
|
|
306
|
-
return await this.instance.
|
|
307
|
-
WorldStateMessageType.UNWIND_BLOCKS,
|
|
308
|
-
{
|
|
309
|
-
toBlockNumber,
|
|
310
|
-
canonical: true,
|
|
311
|
-
},
|
|
312
|
-
this.sanitizeAndCacheSummaryFromFull.bind(this),
|
|
313
|
-
this.deleteCachedSummary.bind(this),
|
|
314
|
-
);
|
|
377
|
+
return this.sanitizeAndCacheSummaryFromFull(await this.instance.unwindBlocks(toBlockNumber));
|
|
315
378
|
} catch (err) {
|
|
379
|
+
this.deleteCachedSummary();
|
|
316
380
|
this.worldStateInstrumentation.incCriticalErrors('prune_pending_block');
|
|
317
381
|
throw err;
|
|
318
382
|
}
|
|
@@ -322,11 +386,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
322
386
|
if (this.cachedStatusSummary !== undefined) {
|
|
323
387
|
return { ...this.cachedStatusSummary };
|
|
324
388
|
}
|
|
325
|
-
return await this.instance.
|
|
326
|
-
WorldStateMessageType.GET_STATUS,
|
|
327
|
-
{ canonical: true },
|
|
328
|
-
this.sanitizeAndCacheSummary.bind(this),
|
|
329
|
-
);
|
|
389
|
+
return this.sanitizeAndCacheSummary(await this.instance.getStatus());
|
|
330
390
|
}
|
|
331
391
|
|
|
332
392
|
updateLeaf<ID extends IndexedTreeId>(
|
|
@@ -338,14 +398,14 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
338
398
|
}
|
|
339
399
|
|
|
340
400
|
private async getInitialStateReference(): Promise<StateReference> {
|
|
341
|
-
const
|
|
401
|
+
const state = await this.instance.getInitialStateReference();
|
|
342
402
|
|
|
343
403
|
return new StateReference(
|
|
344
|
-
treeStateReferenceToSnapshot(
|
|
404
|
+
treeStateReferenceToSnapshot(state[MerkleTreeId.L1_TO_L2_MESSAGE_TREE]),
|
|
345
405
|
new PartialStateReference(
|
|
346
|
-
treeStateReferenceToSnapshot(
|
|
347
|
-
treeStateReferenceToSnapshot(
|
|
348
|
-
treeStateReferenceToSnapshot(
|
|
406
|
+
treeStateReferenceToSnapshot(state[MerkleTreeId.NOTE_HASH_TREE]),
|
|
407
|
+
treeStateReferenceToSnapshot(state[MerkleTreeId.NULLIFIER_TREE]),
|
|
408
|
+
treeStateReferenceToSnapshot(state[MerkleTreeId.PUBLIC_DATA_TREE]),
|
|
349
409
|
),
|
|
350
410
|
);
|
|
351
411
|
}
|
|
@@ -354,11 +414,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
354
414
|
dstPath: string,
|
|
355
415
|
compact: boolean = true,
|
|
356
416
|
): Promise<Record<Exclude<SnapshotDataKeys, 'archiver'>, string>> {
|
|
357
|
-
await this.instance.
|
|
358
|
-
dstPath,
|
|
359
|
-
compact,
|
|
360
|
-
canonical: true,
|
|
361
|
-
});
|
|
417
|
+
await this.instance.copyStores(dstPath, compact);
|
|
362
418
|
return fromEntries(NATIVE_WORLD_STATE_DBS.map(([name, dir]) => [name, join(dstPath, dir, 'data.mdb')] as const));
|
|
363
419
|
}
|
|
364
420
|
}
|