@aztec/world-state 0.0.1-fake-ceab37513c → 0.0.6-commit.a2d1860fe9
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 +1 -1
- package/dest/instrumentation/instrumentation.d.ts.map +1 -1
- package/dest/instrumentation/instrumentation.js +17 -41
- 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 +1 -1
- package/dest/native/fork_checkpoint.d.ts.map +1 -1
- package/dest/native/index.d.ts +1 -1
- package/dest/native/merkle_trees_facade.d.ts +13 -5
- package/dest/native/merkle_trees_facade.d.ts.map +1 -1
- package/dest/native/merkle_trees_facade.js +41 -7
- package/dest/native/message.d.ts +15 -18
- package/dest/native/message.d.ts.map +1 -1
- package/dest/native/message.js +14 -20
- package/dest/native/native_world_state.d.ts +14 -11
- package/dest/native/native_world_state.d.ts.map +1 -1
- package/dest/native/native_world_state.js +26 -18
- package/dest/native/native_world_state_instance.d.ts +12 -3
- package/dest/native/native_world_state_instance.d.ts.map +1 -1
- package/dest/native/native_world_state_instance.js +25 -4
- package/dest/native/world_state_ops_queue.d.ts +1 -1
- package/dest/native/world_state_ops_queue.d.ts.map +1 -1
- package/dest/synchronizer/config.d.ts +3 -5
- package/dest/synchronizer/config.d.ts.map +1 -1
- package/dest/synchronizer/config.js +7 -9
- package/dest/synchronizer/errors.d.ts +1 -1
- package/dest/synchronizer/errors.d.ts.map +1 -1
- package/dest/synchronizer/factory.d.ts +4 -3
- package/dest/synchronizer/factory.d.ts.map +1 -1
- package/dest/synchronizer/factory.js +5 -5
- package/dest/synchronizer/index.d.ts +1 -1
- package/dest/synchronizer/server_world_state_synchronizer.d.ts +10 -27
- package/dest/synchronizer/server_world_state_synchronizer.d.ts.map +1 -1
- package/dest/synchronizer/server_world_state_synchronizer.js +107 -75
- 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 +2 -2
- package/dest/testing.d.ts.map +1 -1
- package/dest/testing.js +1 -1
- package/dest/world-state-db/index.d.ts +1 -1
- package/dest/world-state-db/merkle_tree_db.d.ts +8 -7
- package/dest/world-state-db/merkle_tree_db.d.ts.map +1 -1
- package/package.json +13 -12
- package/src/instrumentation/instrumentation.ts +17 -41
- package/src/native/merkle_trees_facade.ts +44 -6
- package/src/native/message.ts +26 -40
- package/src/native/native_world_state.ts +62 -22
- package/src/native/native_world_state_instance.ts +34 -4
- package/src/synchronizer/config.ts +8 -19
- package/src/synchronizer/factory.ts +7 -1
- package/src/synchronizer/server_world_state_synchronizer.ts +126 -101
- package/src/test/utils.ts +87 -92
- package/src/testing.ts +1 -1
- package/src/world-state-db/merkle_tree_db.ts +11 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/world-state",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6-commit.a2d1860fe9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
"tsconfig": "./tsconfig.json"
|
|
19
19
|
},
|
|
20
20
|
"scripts": {
|
|
21
|
-
"build": "yarn clean && tsc
|
|
22
|
-
"build:dev": "tsc
|
|
21
|
+
"build": "yarn clean && ../scripts/tsc.sh",
|
|
22
|
+
"build:dev": "../scripts/tsc.sh --watch",
|
|
23
23
|
"clean": "rm -rf ./dest .tsbuildinfo",
|
|
24
24
|
"test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}"
|
|
25
25
|
},
|
|
@@ -64,22 +64,23 @@
|
|
|
64
64
|
]
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@aztec/constants": "0.0.
|
|
68
|
-
"@aztec/foundation": "0.0.
|
|
69
|
-
"@aztec/kv-store": "0.0.
|
|
70
|
-
"@aztec/merkle-tree": "0.0.
|
|
71
|
-
"@aztec/native": "0.0.
|
|
72
|
-
"@aztec/protocol-contracts": "0.0.
|
|
73
|
-
"@aztec/stdlib": "0.0.
|
|
74
|
-
"@aztec/telemetry-client": "0.0.
|
|
67
|
+
"@aztec/constants": "0.0.6-commit.a2d1860fe9",
|
|
68
|
+
"@aztec/foundation": "0.0.6-commit.a2d1860fe9",
|
|
69
|
+
"@aztec/kv-store": "0.0.6-commit.a2d1860fe9",
|
|
70
|
+
"@aztec/merkle-tree": "0.0.6-commit.a2d1860fe9",
|
|
71
|
+
"@aztec/native": "0.0.6-commit.a2d1860fe9",
|
|
72
|
+
"@aztec/protocol-contracts": "0.0.6-commit.a2d1860fe9",
|
|
73
|
+
"@aztec/stdlib": "0.0.6-commit.a2d1860fe9",
|
|
74
|
+
"@aztec/telemetry-client": "0.0.6-commit.a2d1860fe9",
|
|
75
75
|
"tslib": "^2.4.0",
|
|
76
76
|
"zod": "^3.23.8"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
|
-
"@aztec/archiver": "0.0.
|
|
79
|
+
"@aztec/archiver": "0.0.6-commit.a2d1860fe9",
|
|
80
80
|
"@jest/globals": "^30.0.0",
|
|
81
81
|
"@types/jest": "^30.0.0",
|
|
82
82
|
"@types/node": "^22.15.17",
|
|
83
|
+
"@typescript/native-preview": "7.0.0-dev.20260113.1",
|
|
83
84
|
"jest": "^30.0.0",
|
|
84
85
|
"jest-mock-extended": "^4.0.0",
|
|
85
86
|
"ts-node": "^10.9.1",
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
Metrics,
|
|
8
8
|
type TelemetryClient,
|
|
9
9
|
type UpDownCounter,
|
|
10
|
-
|
|
10
|
+
createUpDownCounterWithDefault,
|
|
11
11
|
} from '@aztec/telemetry-client';
|
|
12
12
|
|
|
13
13
|
import {
|
|
@@ -46,55 +46,31 @@ export class WorldStateInstrumentation {
|
|
|
46
46
|
private log: Logger = createLogger('world-state:instrumentation'),
|
|
47
47
|
) {
|
|
48
48
|
const meter = telemetry.getMeter('World State');
|
|
49
|
-
this.dbMapSize = meter.createGauge(Metrics.WORLD_STATE_DB_MAP_SIZE
|
|
50
|
-
description: `The current configured map size for each merkle tree`,
|
|
51
|
-
valueType: ValueType.INT,
|
|
52
|
-
});
|
|
49
|
+
this.dbMapSize = meter.createGauge(Metrics.WORLD_STATE_DB_MAP_SIZE);
|
|
53
50
|
|
|
54
|
-
this.dbPhysicalSize = meter.createGauge(Metrics.WORLD_STATE_DB_PHYSICAL_SIZE
|
|
55
|
-
description: `The current physical disk space used for each database`,
|
|
56
|
-
valueType: ValueType.INT,
|
|
57
|
-
});
|
|
51
|
+
this.dbPhysicalSize = meter.createGauge(Metrics.WORLD_STATE_DB_PHYSICAL_SIZE);
|
|
58
52
|
|
|
59
|
-
this.treeSize = meter.createGauge(Metrics.WORLD_STATE_TREE_SIZE
|
|
60
|
-
description: `The current number of leaves in each merkle tree`,
|
|
61
|
-
valueType: ValueType.INT,
|
|
62
|
-
});
|
|
53
|
+
this.treeSize = meter.createGauge(Metrics.WORLD_STATE_TREE_SIZE);
|
|
63
54
|
|
|
64
|
-
this.unfinalizedHeight = meter.createGauge(Metrics.WORLD_STATE_UNFINALIZED_HEIGHT
|
|
65
|
-
description: `The unfinalized block height of each merkle tree`,
|
|
66
|
-
valueType: ValueType.INT,
|
|
67
|
-
});
|
|
55
|
+
this.unfinalizedHeight = meter.createGauge(Metrics.WORLD_STATE_UNFINALIZED_HEIGHT);
|
|
68
56
|
|
|
69
|
-
this.finalizedHeight = meter.createGauge(Metrics.WORLD_STATE_FINALIZED_HEIGHT
|
|
70
|
-
description: `The finalized block height of each merkle tree`,
|
|
71
|
-
valueType: ValueType.INT,
|
|
72
|
-
});
|
|
57
|
+
this.finalizedHeight = meter.createGauge(Metrics.WORLD_STATE_FINALIZED_HEIGHT);
|
|
73
58
|
|
|
74
|
-
this.oldestBlock = meter.createGauge(Metrics.WORLD_STATE_OLDEST_BLOCK
|
|
75
|
-
description: `The oldest historical block of each merkle tree`,
|
|
76
|
-
valueType: ValueType.INT,
|
|
77
|
-
});
|
|
59
|
+
this.oldestBlock = meter.createGauge(Metrics.WORLD_STATE_OLDEST_BLOCK);
|
|
78
60
|
|
|
79
|
-
this.dbUsedSize = meter.createGauge(Metrics.WORLD_STATE_DB_USED_SIZE
|
|
80
|
-
description: `The current used database size for each db of each merkle tree`,
|
|
81
|
-
valueType: ValueType.INT,
|
|
82
|
-
});
|
|
61
|
+
this.dbUsedSize = meter.createGauge(Metrics.WORLD_STATE_DB_USED_SIZE);
|
|
83
62
|
|
|
84
|
-
this.dbNumItems = meter.createGauge(Metrics.WORLD_STATE_DB_NUM_ITEMS
|
|
85
|
-
description: `The current number of items in each database of each merkle tree`,
|
|
86
|
-
valueType: ValueType.INT,
|
|
87
|
-
});
|
|
63
|
+
this.dbNumItems = meter.createGauge(Metrics.WORLD_STATE_DB_NUM_ITEMS);
|
|
88
64
|
|
|
89
|
-
this.requestHistogram = meter.createHistogram(Metrics.WORLD_STATE_REQUEST_TIME
|
|
90
|
-
description: 'The round trip time of world state requests',
|
|
91
|
-
unit: 'us',
|
|
92
|
-
valueType: ValueType.INT,
|
|
93
|
-
});
|
|
65
|
+
this.requestHistogram = meter.createHistogram(Metrics.WORLD_STATE_REQUEST_TIME);
|
|
94
66
|
|
|
95
|
-
this.criticalErrors = meter
|
|
96
|
-
|
|
97
|
-
|
|
67
|
+
this.criticalErrors = createUpDownCounterWithDefault(meter, Metrics.WORLD_STATE_CRITICAL_ERROR_COUNT, {
|
|
68
|
+
[Attributes.ERROR_TYPE]: [
|
|
69
|
+
'synch_pending_block',
|
|
70
|
+
'finalize_block',
|
|
71
|
+
'prune_pending_block',
|
|
72
|
+
'prune_historical_block',
|
|
73
|
+
],
|
|
98
74
|
});
|
|
99
75
|
}
|
|
100
76
|
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
2
4
|
import { serializeToBuffer } from '@aztec/foundation/serialize';
|
|
5
|
+
import { sleep } from '@aztec/foundation/sleep';
|
|
3
6
|
import { type IndexedTreeLeafPreimage, SiblingPath } from '@aztec/foundation/trees';
|
|
4
7
|
import type {
|
|
5
8
|
BatchInsertionResult,
|
|
@@ -18,6 +21,7 @@ import {
|
|
|
18
21
|
PublicDataTreeLeafPreimage,
|
|
19
22
|
} from '@aztec/stdlib/trees';
|
|
20
23
|
import { type BlockHeader, PartialStateReference, StateReference } from '@aztec/stdlib/tx';
|
|
24
|
+
import { type WorldStateRevision, WorldStateRevisionWithHandle } from '@aztec/stdlib/world-state';
|
|
21
25
|
|
|
22
26
|
import assert from 'assert';
|
|
23
27
|
|
|
@@ -25,7 +29,6 @@ import {
|
|
|
25
29
|
type SerializedIndexedLeaf,
|
|
26
30
|
type SerializedLeafValue,
|
|
27
31
|
WorldStateMessageType,
|
|
28
|
-
type WorldStateRevision,
|
|
29
32
|
blockStateReference,
|
|
30
33
|
treeStateReferenceToSnapshot,
|
|
31
34
|
} from './message.js';
|
|
@@ -42,6 +45,10 @@ export class MerkleTreesFacade implements MerkleTreeReadOperations {
|
|
|
42
45
|
return this.initialHeader;
|
|
43
46
|
}
|
|
44
47
|
|
|
48
|
+
getRevision(): WorldStateRevisionWithHandle {
|
|
49
|
+
return WorldStateRevisionWithHandle.fromWorldStateRevision(this.revision, this.instance.getHandle());
|
|
50
|
+
}
|
|
51
|
+
|
|
45
52
|
findLeafIndices(treeId: MerkleTreeId, values: MerkleTreeLeafType<MerkleTreeId>[]): Promise<(bigint | undefined)[]> {
|
|
46
53
|
return this.findLeafIndicesAfter(treeId, values, 0n);
|
|
47
54
|
}
|
|
@@ -187,19 +194,26 @@ export class MerkleTreesFacade implements MerkleTreeReadOperations {
|
|
|
187
194
|
async getBlockNumbersForLeafIndices<ID extends MerkleTreeId>(
|
|
188
195
|
treeId: ID,
|
|
189
196
|
leafIndices: bigint[],
|
|
190
|
-
): Promise<(
|
|
197
|
+
): Promise<(BlockNumber | undefined)[]> {
|
|
191
198
|
const response = await this.instance.call(WorldStateMessageType.GET_BLOCK_NUMBERS_FOR_LEAF_INDICES, {
|
|
192
199
|
treeId,
|
|
193
200
|
revision: this.revision,
|
|
194
201
|
leafIndices,
|
|
195
202
|
});
|
|
196
203
|
|
|
197
|
-
return response.blockNumbers.map(x => (x === undefined || x === null ? undefined :
|
|
204
|
+
return response.blockNumbers.map(x => (x === undefined || x === null ? undefined : BlockNumber(Number(x))));
|
|
198
205
|
}
|
|
199
206
|
}
|
|
200
207
|
|
|
201
208
|
export class MerkleTreesForkFacade extends MerkleTreesFacade implements MerkleTreeWriteOperations {
|
|
202
|
-
|
|
209
|
+
private log = createLogger('world-state:merkle-trees-fork-facade');
|
|
210
|
+
|
|
211
|
+
constructor(
|
|
212
|
+
instance: NativeWorldStateInstance,
|
|
213
|
+
initialHeader: BlockHeader,
|
|
214
|
+
revision: WorldStateRevision,
|
|
215
|
+
private opts: { closeDelayMs?: number },
|
|
216
|
+
) {
|
|
203
217
|
assert.notEqual(revision.forkId, 0, 'Fork ID must be set');
|
|
204
218
|
assert.equal(revision.includeUncommitted, true, 'Fork must include uncommitted data');
|
|
205
219
|
super(instance, initialHeader, revision);
|
|
@@ -278,7 +292,31 @@ export class MerkleTreesForkFacade extends MerkleTreesFacade implements MerkleTr
|
|
|
278
292
|
|
|
279
293
|
public async close(): Promise<void> {
|
|
280
294
|
assert.notEqual(this.revision.forkId, 0, 'Fork ID must be set');
|
|
281
|
-
|
|
295
|
+
try {
|
|
296
|
+
await this.instance.call(WorldStateMessageType.DELETE_FORK, { forkId: this.revision.forkId });
|
|
297
|
+
} catch (err: any) {
|
|
298
|
+
// Ignore errors due to native instance being closed during shutdown.
|
|
299
|
+
// This can happen when validators are still processing block proposals while the node is stopping.
|
|
300
|
+
if (err?.message === 'Native instance is closed') {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
throw err;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
async [Symbol.asyncDispose](): Promise<void> {
|
|
308
|
+
if (this.opts.closeDelayMs) {
|
|
309
|
+
void sleep(this.opts.closeDelayMs)
|
|
310
|
+
.then(() => this.close())
|
|
311
|
+
.catch(err => {
|
|
312
|
+
if (err && 'message' in err && err.message === 'Native instance is closed') {
|
|
313
|
+
return; // Ignore errors due to native instance being closed
|
|
314
|
+
}
|
|
315
|
+
this.log.warn('Error closing MerkleTreesForkFacade after delay', { err });
|
|
316
|
+
});
|
|
317
|
+
} else {
|
|
318
|
+
await this.close();
|
|
319
|
+
}
|
|
282
320
|
}
|
|
283
321
|
|
|
284
322
|
public async createCheckpoint(): Promise<void> {
|
package/src/native/message.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
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';
|
|
4
|
+
import type { BlockHash } from '@aztec/stdlib/block';
|
|
3
5
|
import { AppendOnlyTreeSnapshot, MerkleTreeId } from '@aztec/stdlib/trees';
|
|
4
6
|
import type { StateReference } from '@aztec/stdlib/tx';
|
|
5
7
|
import type { UInt32 } from '@aztec/stdlib/types';
|
|
8
|
+
import type { WorldStateRevision } from '@aztec/stdlib/world-state';
|
|
6
9
|
|
|
7
10
|
export enum WorldStateMessageType {
|
|
8
11
|
GET_TREE_INFO = 100,
|
|
@@ -55,11 +58,11 @@ interface WithTreeId {
|
|
|
55
58
|
|
|
56
59
|
export interface WorldStateStatusSummary {
|
|
57
60
|
/** Last block number that can still be unwound. */
|
|
58
|
-
unfinalizedBlockNumber:
|
|
61
|
+
unfinalizedBlockNumber: BlockNumber;
|
|
59
62
|
/** Last block number that is finalized and cannot be unwound. */
|
|
60
|
-
finalizedBlockNumber:
|
|
63
|
+
finalizedBlockNumber: BlockNumber;
|
|
61
64
|
/** Oldest block still available for historical queries and forks. */
|
|
62
|
-
oldestHistoricalBlock:
|
|
65
|
+
oldestHistoricalBlock: BlockNumber;
|
|
63
66
|
/** Whether the trees are in sync with each other */
|
|
64
67
|
treesAreSynched: boolean;
|
|
65
68
|
}
|
|
@@ -80,11 +83,11 @@ export interface TreeMeta {
|
|
|
80
83
|
/** The tree's initial root value */
|
|
81
84
|
initialRoot: Fr;
|
|
82
85
|
/** The current oldest historical block number of the tree */
|
|
83
|
-
oldestHistoricBlock:
|
|
86
|
+
oldestHistoricBlock: BlockNumber;
|
|
84
87
|
/** The current unfinalized block number of the tree */
|
|
85
|
-
unfinalizedBlockHeight:
|
|
88
|
+
unfinalizedBlockHeight: BlockNumber;
|
|
86
89
|
/** The current finalized block number of the tree */
|
|
87
|
-
finalizedBlockHeight:
|
|
90
|
+
finalizedBlockHeight: BlockNumber;
|
|
88
91
|
}
|
|
89
92
|
|
|
90
93
|
export interface DBStats {
|
|
@@ -172,9 +175,9 @@ export function buildEmptyTreeMeta() {
|
|
|
172
175
|
depth: 0,
|
|
173
176
|
size: 0n,
|
|
174
177
|
committedSize: 0n,
|
|
175
|
-
unfinalizedBlockHeight:
|
|
176
|
-
finalizedBlockHeight:
|
|
177
|
-
oldestHistoricBlock:
|
|
178
|
+
unfinalizedBlockHeight: BlockNumber.ZERO,
|
|
179
|
+
finalizedBlockHeight: BlockNumber.ZERO,
|
|
180
|
+
oldestHistoricBlock: BlockNumber.ZERO,
|
|
178
181
|
root: Fr.ZERO,
|
|
179
182
|
initialRoot: Fr.ZERO,
|
|
180
183
|
initialSize: 0n,
|
|
@@ -203,9 +206,9 @@ export function buildEmptyWorldStateDBStats() {
|
|
|
203
206
|
|
|
204
207
|
export function buildEmptyWorldStateSummary() {
|
|
205
208
|
return {
|
|
206
|
-
unfinalizedBlockNumber:
|
|
207
|
-
finalizedBlockNumber:
|
|
208
|
-
oldestHistoricalBlock:
|
|
209
|
+
unfinalizedBlockNumber: BlockNumber.ZERO,
|
|
210
|
+
finalizedBlockNumber: BlockNumber.ZERO,
|
|
211
|
+
oldestHistoricalBlock: BlockNumber.ZERO,
|
|
209
212
|
treesAreSynched: true,
|
|
210
213
|
} as WorldStateStatusSummary;
|
|
211
214
|
}
|
|
@@ -219,9 +222,9 @@ export function buildEmptyWorldStateStatusFull() {
|
|
|
219
222
|
}
|
|
220
223
|
|
|
221
224
|
export function sanitizeSummary(summary: WorldStateStatusSummary) {
|
|
222
|
-
summary.finalizedBlockNumber = BigInt(summary.finalizedBlockNumber);
|
|
223
|
-
summary.unfinalizedBlockNumber = BigInt(summary.unfinalizedBlockNumber);
|
|
224
|
-
summary.oldestHistoricalBlock = BigInt(summary.oldestHistoricalBlock);
|
|
225
|
+
summary.finalizedBlockNumber = BlockNumber.fromBigInt(BigInt(summary.finalizedBlockNumber));
|
|
226
|
+
summary.unfinalizedBlockNumber = BlockNumber.fromBigInt(BigInt(summary.unfinalizedBlockNumber));
|
|
227
|
+
summary.oldestHistoricalBlock = BlockNumber.fromBigInt(BigInt(summary.oldestHistoricalBlock));
|
|
225
228
|
return summary;
|
|
226
229
|
}
|
|
227
230
|
|
|
@@ -233,11 +236,11 @@ export function sanitizeDBStats(stats: DBStats) {
|
|
|
233
236
|
|
|
234
237
|
export function sanitizeMeta(meta: TreeMeta) {
|
|
235
238
|
meta.committedSize = BigInt(meta.committedSize);
|
|
236
|
-
meta.finalizedBlockHeight = BigInt(meta.finalizedBlockHeight);
|
|
239
|
+
meta.finalizedBlockHeight = BlockNumber.fromBigInt(BigInt(meta.finalizedBlockHeight));
|
|
237
240
|
meta.initialSize = BigInt(meta.initialSize);
|
|
238
|
-
meta.oldestHistoricBlock = BigInt(meta.oldestHistoricBlock);
|
|
241
|
+
meta.oldestHistoricBlock = BlockNumber.fromBigInt(BigInt(meta.oldestHistoricBlock));
|
|
239
242
|
meta.size = BigInt(meta.size);
|
|
240
|
-
meta.unfinalizedBlockHeight = BigInt(meta.unfinalizedBlockHeight);
|
|
243
|
+
meta.unfinalizedBlockHeight = BlockNumber.fromBigInt(BigInt(meta.unfinalizedBlockHeight));
|
|
241
244
|
return meta;
|
|
242
245
|
}
|
|
243
246
|
|
|
@@ -309,7 +312,7 @@ interface WithLeafValues {
|
|
|
309
312
|
}
|
|
310
313
|
|
|
311
314
|
interface BlockShiftRequest extends WithCanonicalForkId {
|
|
312
|
-
toBlockNumber:
|
|
315
|
+
toBlockNumber: BlockNumber;
|
|
313
316
|
}
|
|
314
317
|
|
|
315
318
|
interface WithLeaves {
|
|
@@ -408,9 +411,9 @@ interface UpdateArchiveRequest extends WithForkId {
|
|
|
408
411
|
}
|
|
409
412
|
|
|
410
413
|
interface SyncBlockRequest extends WithCanonicalForkId {
|
|
411
|
-
blockNumber:
|
|
414
|
+
blockNumber: BlockNumber;
|
|
412
415
|
blockStateRef: BlockStateReference;
|
|
413
|
-
blockHeaderHash:
|
|
416
|
+
blockHeaderHash: BlockHash;
|
|
414
417
|
paddedNoteHashes: readonly SerializedLeafValue[];
|
|
415
418
|
paddedL1ToL2Messages: readonly SerializedLeafValue[];
|
|
416
419
|
paddedNullifiers: readonly SerializedLeafValue[];
|
|
@@ -419,7 +422,7 @@ interface SyncBlockRequest extends WithCanonicalForkId {
|
|
|
419
422
|
|
|
420
423
|
interface CreateForkRequest extends WithCanonicalForkId {
|
|
421
424
|
latest: boolean;
|
|
422
|
-
blockNumber:
|
|
425
|
+
blockNumber: BlockNumber;
|
|
423
426
|
}
|
|
424
427
|
|
|
425
428
|
interface CreateForkResponse {
|
|
@@ -537,23 +540,6 @@ export type WorldStateResponse = {
|
|
|
537
540
|
[WorldStateMessageType.CLOSE]: void;
|
|
538
541
|
};
|
|
539
542
|
|
|
540
|
-
export type WorldStateRevision = {
|
|
541
|
-
forkId: number;
|
|
542
|
-
blockNumber: number;
|
|
543
|
-
includeUncommitted: boolean;
|
|
544
|
-
};
|
|
545
|
-
export function worldStateRevision(
|
|
546
|
-
includeUncommitted: boolean,
|
|
547
|
-
forkId: number | undefined,
|
|
548
|
-
blockNumber: number | undefined,
|
|
549
|
-
): WorldStateRevision {
|
|
550
|
-
return {
|
|
551
|
-
forkId: forkId ?? 0,
|
|
552
|
-
blockNumber: blockNumber ?? 0,
|
|
553
|
-
includeUncommitted,
|
|
554
|
-
};
|
|
555
|
-
}
|
|
556
|
-
|
|
557
543
|
type TreeStateReference = readonly [Buffer, number | bigint];
|
|
558
544
|
type BlockStateReference = Map<Exclude<MerkleTreeId, MerkleTreeId.ARCHIVE>, TreeStateReference>;
|
|
559
545
|
|
|
@@ -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 Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
7
8
|
import type { L2Block } from '@aztec/stdlib/block';
|
|
8
|
-
import { DatabaseVersionManager } from '@aztec/stdlib/database-version';
|
|
9
|
+
import { DatabaseVersionManager } from '@aztec/stdlib/database-version/manager';
|
|
9
10
|
import type {
|
|
10
11
|
IndexedTreeId,
|
|
11
12
|
MerkleTreeReadOperations,
|
|
@@ -14,6 +15,7 @@ import type {
|
|
|
14
15
|
import type { SnapshotDataKeys } from '@aztec/stdlib/snapshots';
|
|
15
16
|
import { MerkleTreeId, NullifierLeaf, type NullifierLeafPreimage, PublicDataTreeLeaf } from '@aztec/stdlib/trees';
|
|
16
17
|
import { BlockHeader, PartialStateReference, StateReference } from '@aztec/stdlib/tx';
|
|
18
|
+
import { WorldStateRevision } from '@aztec/stdlib/world-state';
|
|
17
19
|
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
18
20
|
|
|
19
21
|
import assert from 'assert/strict';
|
|
@@ -33,7 +35,6 @@ import {
|
|
|
33
35
|
sanitizeFullStatus,
|
|
34
36
|
sanitizeSummary,
|
|
35
37
|
treeStateReferenceToSnapshot,
|
|
36
|
-
worldStateRevision,
|
|
37
38
|
} from './message.js';
|
|
38
39
|
import { NativeWorldState } from './native_world_state_instance.js';
|
|
39
40
|
|
|
@@ -51,7 +52,7 @@ 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,
|
|
55
56
|
private readonly cleanup = () => Promise.resolve(),
|
|
56
57
|
) {}
|
|
57
58
|
|
|
@@ -61,9 +62,10 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
61
62
|
wsTreeMapSizes: WorldStateTreeMapSizes,
|
|
62
63
|
prefilledPublicData: PublicDataTreeLeaf[] = [],
|
|
63
64
|
instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
|
|
64
|
-
|
|
65
|
+
bindings?: LoggerBindings,
|
|
65
66
|
cleanup = () => Promise.resolve(),
|
|
66
67
|
): Promise<NativeWorldStateService> {
|
|
68
|
+
const log = createLogger('world-state:database', bindings);
|
|
67
69
|
const worldStateDirectory = join(dataDir, WORLD_STATE_DIR);
|
|
68
70
|
// Create a version manager to handle versioning
|
|
69
71
|
const versionManager = new DatabaseVersionManager({
|
|
@@ -71,7 +73,9 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
71
73
|
rollupAddress,
|
|
72
74
|
dataDirectory: worldStateDirectory,
|
|
73
75
|
onOpen: (dir: string) => {
|
|
74
|
-
return Promise.resolve(
|
|
76
|
+
return Promise.resolve(
|
|
77
|
+
new NativeWorldState(dir, wsTreeMapSizes, prefilledPublicData, instrumentation, bindings),
|
|
78
|
+
);
|
|
75
79
|
},
|
|
76
80
|
});
|
|
77
81
|
|
|
@@ -92,8 +96,9 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
92
96
|
cleanupTmpDir = true,
|
|
93
97
|
prefilledPublicData: PublicDataTreeLeaf[] = [],
|
|
94
98
|
instrumentation = new WorldStateInstrumentation(getTelemetryClient()),
|
|
99
|
+
bindings?: LoggerBindings,
|
|
95
100
|
): Promise<NativeWorldStateService> {
|
|
96
|
-
const log = createLogger('world-state:database');
|
|
101
|
+
const log = createLogger('world-state:database', bindings);
|
|
97
102
|
const dataDir = await mkdtemp(join(tmpdir(), 'aztec-world-state-'));
|
|
98
103
|
const dbMapSizeKb = 10 * 1024 * 1024;
|
|
99
104
|
const worldStateTreeMapSizes: WorldStateTreeMapSizes = {
|
|
@@ -115,7 +120,15 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
115
120
|
}
|
|
116
121
|
};
|
|
117
122
|
|
|
118
|
-
return this.new(
|
|
123
|
+
return this.new(
|
|
124
|
+
rollupAddress,
|
|
125
|
+
dataDir,
|
|
126
|
+
worldStateTreeMapSizes,
|
|
127
|
+
prefilledPublicData,
|
|
128
|
+
instrumentation,
|
|
129
|
+
bindings,
|
|
130
|
+
cleanup,
|
|
131
|
+
);
|
|
119
132
|
}
|
|
120
133
|
|
|
121
134
|
protected async init() {
|
|
@@ -134,7 +147,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
134
147
|
|
|
135
148
|
// the initial header _must_ be the first element in the archive tree
|
|
136
149
|
// if this assertion fails, check that the hashing done in Header in yarn-project matches the initial header hash done in world_state.cpp
|
|
137
|
-
const indices = await committed.findLeafIndices(MerkleTreeId.ARCHIVE, [await this.initialHeader.hash()]);
|
|
150
|
+
const indices = await committed.findLeafIndices(MerkleTreeId.ARCHIVE, [(await this.initialHeader.hash()).toFr()]);
|
|
138
151
|
const initialHeaderIndex = indices[0];
|
|
139
152
|
assert.strictEqual(initialHeaderIndex, 0n, 'Invalid initial archive state');
|
|
140
153
|
}
|
|
@@ -147,20 +160,36 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
147
160
|
}
|
|
148
161
|
|
|
149
162
|
public getCommitted(): MerkleTreeReadOperations {
|
|
150
|
-
return new MerkleTreesFacade(this.instance, this.initialHeader!,
|
|
163
|
+
return new MerkleTreesFacade(this.instance, this.initialHeader!, WorldStateRevision.empty());
|
|
151
164
|
}
|
|
152
165
|
|
|
153
|
-
public getSnapshot(blockNumber:
|
|
154
|
-
return new MerkleTreesFacade(
|
|
166
|
+
public getSnapshot(blockNumber: BlockNumber): MerkleTreeReadOperations {
|
|
167
|
+
return new MerkleTreesFacade(
|
|
168
|
+
this.instance,
|
|
169
|
+
this.initialHeader!,
|
|
170
|
+
new WorldStateRevision(/*forkId=*/ 0, /* blockNumber=*/ blockNumber, /* includeUncommitted=*/ false),
|
|
171
|
+
);
|
|
155
172
|
}
|
|
156
173
|
|
|
157
|
-
public async fork(
|
|
174
|
+
public async fork(
|
|
175
|
+
blockNumber?: BlockNumber,
|
|
176
|
+
opts: { closeDelayMs?: number } = {},
|
|
177
|
+
): Promise<MerkleTreeWriteOperations> {
|
|
158
178
|
const resp = await this.instance.call(WorldStateMessageType.CREATE_FORK, {
|
|
159
179
|
latest: blockNumber === undefined,
|
|
160
|
-
blockNumber: blockNumber ??
|
|
180
|
+
blockNumber: blockNumber ?? BlockNumber.ZERO,
|
|
161
181
|
canonical: true,
|
|
162
182
|
});
|
|
163
|
-
return new MerkleTreesForkFacade(
|
|
183
|
+
return new MerkleTreesForkFacade(
|
|
184
|
+
this.instance,
|
|
185
|
+
this.initialHeader!,
|
|
186
|
+
new WorldStateRevision(
|
|
187
|
+
/*forkId=*/ resp.forkId,
|
|
188
|
+
/* blockNumber=*/ BlockNumber.ZERO,
|
|
189
|
+
/* includeUncommitted=*/ true,
|
|
190
|
+
),
|
|
191
|
+
opts,
|
|
192
|
+
);
|
|
164
193
|
}
|
|
165
194
|
|
|
166
195
|
public getInitialHeader(): BlockHeader {
|
|
@@ -168,11 +197,22 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
168
197
|
}
|
|
169
198
|
|
|
170
199
|
public async handleL2BlockAndMessages(l2Block: L2Block, l1ToL2Messages: Fr[]): Promise<WorldStateStatusFull> {
|
|
171
|
-
|
|
200
|
+
const isFirstBlock = l2Block.indexWithinCheckpoint === 0;
|
|
201
|
+
if (!isFirstBlock && l1ToL2Messages.length > 0) {
|
|
202
|
+
throw new Error(
|
|
203
|
+
`L1 to L2 messages must be empty for non-first blocks, but got ${l1ToL2Messages.length} messages for block ${l2Block.number}.`,
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// We have to pad the given l1 to l2 messages, and the note hashes and nullifiers within tx effects, because that's
|
|
208
|
+
// how the trees are built by circuits.
|
|
209
|
+
const paddedL1ToL2Messages = isFirstBlock
|
|
210
|
+
? padArrayEnd<Fr, number>(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP)
|
|
211
|
+
: [];
|
|
212
|
+
|
|
172
213
|
const paddedNoteHashes = l2Block.body.txEffects.flatMap(txEffect =>
|
|
173
214
|
padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
|
|
174
215
|
);
|
|
175
|
-
const paddedL1ToL2Messages = padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
|
|
176
216
|
|
|
177
217
|
const paddedNullifiers = l2Block.body.txEffects
|
|
178
218
|
.flatMap(txEffect => padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX))
|
|
@@ -192,7 +232,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
192
232
|
WorldStateMessageType.SYNC_BLOCK,
|
|
193
233
|
{
|
|
194
234
|
blockNumber: l2Block.number,
|
|
195
|
-
blockHeaderHash: await l2Block.
|
|
235
|
+
blockHeaderHash: await l2Block.hash(),
|
|
196
236
|
paddedL1ToL2Messages: paddedL1ToL2Messages.map(serializeLeaf),
|
|
197
237
|
paddedNoteHashes: paddedNoteHashes.map(serializeLeaf),
|
|
198
238
|
paddedNullifiers: paddedNullifiers.map(serializeLeaf),
|
|
@@ -240,7 +280,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
240
280
|
* @param toBlockNumber The block number that is now the tip of the finalized chain
|
|
241
281
|
* @returns The new WorldStateStatus
|
|
242
282
|
*/
|
|
243
|
-
public async setFinalized(toBlockNumber:
|
|
283
|
+
public async setFinalized(toBlockNumber: BlockNumber) {
|
|
244
284
|
try {
|
|
245
285
|
await this.instance.call(
|
|
246
286
|
WorldStateMessageType.FINALIZE_BLOCKS,
|
|
@@ -263,7 +303,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
263
303
|
* @param toBlockNumber The block number of the new oldest historical block
|
|
264
304
|
* @returns The new WorldStateStatus
|
|
265
305
|
*/
|
|
266
|
-
public async removeHistoricalBlocks(toBlockNumber:
|
|
306
|
+
public async removeHistoricalBlocks(toBlockNumber: BlockNumber) {
|
|
267
307
|
try {
|
|
268
308
|
return await this.instance.call(
|
|
269
309
|
WorldStateMessageType.REMOVE_HISTORICAL_BLOCKS,
|
|
@@ -285,7 +325,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
285
325
|
* @param toBlockNumber The block number of the new tip of the pending chain,
|
|
286
326
|
* @returns The new WorldStateStatus
|
|
287
327
|
*/
|
|
288
|
-
public async unwindBlocks(toBlockNumber:
|
|
328
|
+
public async unwindBlocks(toBlockNumber: BlockNumber) {
|
|
289
329
|
try {
|
|
290
330
|
return await this.instance.call(
|
|
291
331
|
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,7 +8,7 @@ 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
14
|
import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
|
|
@@ -36,6 +36,8 @@ export interface NativeWorldStateInstance {
|
|
|
36
36
|
messageType: T,
|
|
37
37
|
body: WorldStateRequest[T] & WorldStateRequestCategories,
|
|
38
38
|
): Promise<WorldStateResponse[T]>;
|
|
39
|
+
// TODO(dbanks12): this returns any type, but we should strongly type it
|
|
40
|
+
getHandle(): any;
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
/**
|
|
@@ -55,7 +57,8 @@ export class NativeWorldState implements NativeWorldStateInstance {
|
|
|
55
57
|
private readonly wsTreeMapSizes: WorldStateTreeMapSizes,
|
|
56
58
|
private readonly prefilledPublicData: PublicDataTreeLeaf[] = [],
|
|
57
59
|
private readonly instrumentation: WorldStateInstrumentation,
|
|
58
|
-
|
|
60
|
+
bindings?: LoggerBindings,
|
|
61
|
+
private readonly log: Logger = createLogger('world-state:database', bindings),
|
|
59
62
|
) {
|
|
60
63
|
const threads = Math.min(cpus().length, MAX_WORLD_STATE_THREADS);
|
|
61
64
|
log.info(
|
|
@@ -78,7 +81,7 @@ export class NativeWorldState implements NativeWorldStateInstance {
|
|
|
78
81
|
[MerkleTreeId.PUBLIC_DATA_TREE]: 2 * MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
79
82
|
},
|
|
80
83
|
prefilledPublicDataBufferArray,
|
|
81
|
-
|
|
84
|
+
DomainSeparator.BLOCK_HEADER_HASH,
|
|
82
85
|
{
|
|
83
86
|
[MerkleTreeId.NULLIFIER_TREE]: wsTreeMapSizes.nullifierTreeMapSizeKb,
|
|
84
87
|
[MerkleTreeId.NOTE_HASH_TREE]: wsTreeMapSizes.noteHashTreeMapSizeKb,
|
|
@@ -103,10 +106,37 @@ export class NativeWorldState implements NativeWorldStateInstance {
|
|
|
103
106
|
this.wsTreeMapSizes,
|
|
104
107
|
this.prefilledPublicData,
|
|
105
108
|
this.instrumentation,
|
|
109
|
+
this.log.getBindings(),
|
|
106
110
|
this.log,
|
|
107
111
|
);
|
|
108
112
|
}
|
|
109
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Gets the native WorldState handle from the underlying native instance.
|
|
116
|
+
* We call the getHandle() method on the native WorldState to get a NAPI External
|
|
117
|
+
* that wraps the underlying C++ WorldState pointer.
|
|
118
|
+
* @returns The NAPI External handle to the native WorldState instance,since
|
|
119
|
+
* the NAPI external type is opaque, we return any (we could also use an opaque symbol type)
|
|
120
|
+
*/
|
|
121
|
+
public getHandle(): any {
|
|
122
|
+
const worldStateWrapper = (this.instance as any).dest;
|
|
123
|
+
|
|
124
|
+
if (!worldStateWrapper) {
|
|
125
|
+
throw new Error('No WorldStateWrapper found');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (typeof worldStateWrapper.getHandle !== 'function') {
|
|
129
|
+
throw new Error('WorldStateWrapper does not have getHandle method');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Call getHandle() to get the NAPI External
|
|
133
|
+
try {
|
|
134
|
+
return worldStateWrapper.getHandle();
|
|
135
|
+
} catch (error) {
|
|
136
|
+
this.log.error('Failed to get native WorldState handle', error);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
110
140
|
/**
|
|
111
141
|
* Sends a message to the native instance and returns the response.
|
|
112
142
|
* @param messageType - The type of message to send
|