@aztec/world-state 0.69.1-devnet → 0.70.0
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/native/merkle_trees_facade.js +2 -2
- package/dest/native/message.d.ts +16 -16
- package/dest/native/message.d.ts.map +1 -1
- package/dest/native/message.js +10 -1
- package/dest/native/native_world_state.d.ts.map +1 -1
- package/dest/native/native_world_state.js +8 -3
- package/dest/native/native_world_state_instance.d.ts +4 -5
- package/dest/native/native_world_state_instance.d.ts.map +1 -1
- package/dest/native/native_world_state_instance.js +50 -11
- package/dest/native/world_state_ops_queue.d.ts +19 -0
- package/dest/native/world_state_ops_queue.d.ts.map +1 -0
- package/dest/native/world_state_ops_queue.js +154 -0
- package/package.json +8 -8
- package/src/native/merkle_trees_facade.ts +1 -1
- package/src/native/message.ts +22 -14
- package/src/native/native_world_state.ts +11 -2
- package/src/native/native_world_state_instance.ts +78 -22
- package/src/native/world_state_ops_queue.ts +187 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { promiseWithResolvers } from '@aztec/foundation/promise';
|
|
2
|
+
import { WorldStateMessageType } from './message.js';
|
|
3
|
+
// These are the set of message types that implement mutating operations
|
|
4
|
+
// Messages of these types require exclusive access to their given forks
|
|
5
|
+
export const MUTATING_MSG_TYPES = new Set([
|
|
6
|
+
WorldStateMessageType.APPEND_LEAVES,
|
|
7
|
+
WorldStateMessageType.BATCH_INSERT,
|
|
8
|
+
WorldStateMessageType.SEQUENTIAL_INSERT,
|
|
9
|
+
WorldStateMessageType.UPDATE_ARCHIVE,
|
|
10
|
+
WorldStateMessageType.COMMIT,
|
|
11
|
+
WorldStateMessageType.ROLLBACK,
|
|
12
|
+
WorldStateMessageType.SYNC_BLOCK,
|
|
13
|
+
WorldStateMessageType.CREATE_FORK,
|
|
14
|
+
WorldStateMessageType.DELETE_FORK,
|
|
15
|
+
WorldStateMessageType.FINALISE_BLOCKS,
|
|
16
|
+
WorldStateMessageType.UNWIND_BLOCKS,
|
|
17
|
+
WorldStateMessageType.REMOVE_HISTORICAL_BLOCKS,
|
|
18
|
+
]);
|
|
19
|
+
// This class implements the per-fork operation queue
|
|
20
|
+
export class WorldStateOpsQueue {
|
|
21
|
+
constructor() {
|
|
22
|
+
this.requests = [];
|
|
23
|
+
this.inFlightMutatingCount = 0;
|
|
24
|
+
this.inFlightCount = 0;
|
|
25
|
+
this.requestId = 0;
|
|
26
|
+
this.ops = new Map();
|
|
27
|
+
}
|
|
28
|
+
// The primary public api, this is where an operation is queued
|
|
29
|
+
// We return a promise that will ultimately be resolved/rejected with the response/error generated by the 'request' argument
|
|
30
|
+
execute(request, messageType, committedOnly) {
|
|
31
|
+
if (this.stopResolve !== undefined) {
|
|
32
|
+
throw new Error('Unable to send request to world state, queue already stopped');
|
|
33
|
+
}
|
|
34
|
+
const op = {
|
|
35
|
+
requestId: this.requestId++,
|
|
36
|
+
mutating: MUTATING_MSG_TYPES.has(messageType),
|
|
37
|
+
request,
|
|
38
|
+
promise: promiseWithResolvers(),
|
|
39
|
+
};
|
|
40
|
+
this.ops.set(op.requestId, op);
|
|
41
|
+
// Perform the appropriate action based upon the queueing rules
|
|
42
|
+
if (op.mutating) {
|
|
43
|
+
this.executeMutating(op);
|
|
44
|
+
}
|
|
45
|
+
else if (committedOnly === false) {
|
|
46
|
+
this.executeNonMutatingUncommitted(op);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
this.executeNonMutatingCommitted(op);
|
|
50
|
+
}
|
|
51
|
+
return op.promise.promise;
|
|
52
|
+
}
|
|
53
|
+
// Mutating requests need exclusive access
|
|
54
|
+
executeMutating(op) {
|
|
55
|
+
// If nothing is in flight then we send the request immediately
|
|
56
|
+
// Otherwise add to the queue
|
|
57
|
+
if (this.inFlightCount === 0) {
|
|
58
|
+
this.sendEnqueuedRequest(op);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
this.requests.push(op);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Non mutating requests including uncommitted state
|
|
65
|
+
executeNonMutatingUncommitted(op) {
|
|
66
|
+
// If there are no mutating requests in flight and there is nothing queued
|
|
67
|
+
// then send the request immediately
|
|
68
|
+
// If a mutating request is in flight then we must wait
|
|
69
|
+
// If a mutating request is not in flight but something is queued then it must be a mutating request
|
|
70
|
+
if (this.inFlightMutatingCount == 0 && this.requests.length == 0) {
|
|
71
|
+
this.sendEnqueuedRequest(op);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
this.requests.push(op);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
executeNonMutatingCommitted(op) {
|
|
78
|
+
// This is a non-mutating request for committed data
|
|
79
|
+
// It can always be sent
|
|
80
|
+
op.request()
|
|
81
|
+
.then(op.promise.resolve, op.promise.reject)
|
|
82
|
+
.finally(() => {
|
|
83
|
+
this.ops.delete(op.requestId);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
checkAndEnqueue(completedOp) {
|
|
87
|
+
// As request has completed
|
|
88
|
+
// First we decrements the relevant in flight counters
|
|
89
|
+
if (completedOp.mutating) {
|
|
90
|
+
--this.inFlightMutatingCount;
|
|
91
|
+
}
|
|
92
|
+
--this.inFlightCount;
|
|
93
|
+
// If there are still requests in flight then do nothing further
|
|
94
|
+
if (this.inFlightCount != 0) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
// No requests in flight, send next queued requests
|
|
98
|
+
// We loop and send:
|
|
99
|
+
// 1 mutating request if it is next in the queue
|
|
100
|
+
// As many non-mutating requests as we encounter until
|
|
101
|
+
// we exhaust the queue or we reach a mutating request
|
|
102
|
+
while (this.requests.length > 0) {
|
|
103
|
+
const next = this.requests[0];
|
|
104
|
+
if (next.mutating) {
|
|
105
|
+
if (this.inFlightCount == 0) {
|
|
106
|
+
// send the mutating request
|
|
107
|
+
this.requests.shift();
|
|
108
|
+
this.sendEnqueuedRequest(next);
|
|
109
|
+
}
|
|
110
|
+
// this request is mutating, we need to stop here
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
// not mutating, send and go round again
|
|
115
|
+
this.requests.shift();
|
|
116
|
+
this.sendEnqueuedRequest(next);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// If the queue is empty, there is nothing in flight and we have been told to stop, then resolve the stop promise
|
|
120
|
+
if (this.inFlightCount == 0 && this.stopResolve !== undefined) {
|
|
121
|
+
this.stopResolve();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
sendEnqueuedRequest(op) {
|
|
125
|
+
// Here we increment the in flight counts before sending
|
|
126
|
+
++this.inFlightCount;
|
|
127
|
+
if (op.mutating) {
|
|
128
|
+
++this.inFlightMutatingCount;
|
|
129
|
+
}
|
|
130
|
+
// Make the request and pass the response/error through to the stored promise
|
|
131
|
+
op.request()
|
|
132
|
+
.then(op.promise.resolve, op.promise.reject)
|
|
133
|
+
.finally(() => {
|
|
134
|
+
this.checkAndEnqueue(op);
|
|
135
|
+
this.ops.delete(op.requestId);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
stop() {
|
|
139
|
+
// If there is already a stop promise then return it
|
|
140
|
+
if (this.stopPromise) {
|
|
141
|
+
return this.stopPromise;
|
|
142
|
+
}
|
|
143
|
+
// Otherwise create a new one and capture the resolve method
|
|
144
|
+
this.stopPromise = new Promise(resolve => {
|
|
145
|
+
this.stopResolve = resolve;
|
|
146
|
+
});
|
|
147
|
+
// If no outstanding requests then immediately resolve the promise
|
|
148
|
+
if (this.requests.length == 0 && this.inFlightCount == 0 && this.stopResolve !== undefined) {
|
|
149
|
+
this.stopResolve();
|
|
150
|
+
}
|
|
151
|
+
return this.stopPromise;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29ybGRfc3RhdGVfb3BzX3F1ZXVlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL25hdGl2ZS93b3JsZF9zdGF0ZV9vcHNfcXVldWUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFakUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBdUJyRCx3RUFBd0U7QUFDeEUsd0VBQXdFO0FBQ3hFLE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFHLElBQUksR0FBRyxDQUFDO0lBQ3hDLHFCQUFxQixDQUFDLGFBQWE7SUFDbkMscUJBQXFCLENBQUMsWUFBWTtJQUNsQyxxQkFBcUIsQ0FBQyxpQkFBaUI7SUFDdkMscUJBQXFCLENBQUMsY0FBYztJQUNwQyxxQkFBcUIsQ0FBQyxNQUFNO0lBQzVCLHFCQUFxQixDQUFDLFFBQVE7SUFDOUIscUJBQXFCLENBQUMsVUFBVTtJQUNoQyxxQkFBcUIsQ0FBQyxXQUFXO0lBQ2pDLHFCQUFxQixDQUFDLFdBQVc7SUFDakMscUJBQXFCLENBQUMsZUFBZTtJQUNyQyxxQkFBcUIsQ0FBQyxhQUFhO0lBQ25DLHFCQUFxQixDQUFDLHdCQUF3QjtDQUMvQyxDQUFDLENBQUM7QUFFSCxxREFBcUQ7QUFDckQsTUFBTSxPQUFPLGtCQUFrQjtJQUEvQjtRQUNVLGFBQVEsR0FBbUIsRUFBRSxDQUFDO1FBQzlCLDBCQUFxQixHQUFHLENBQUMsQ0FBQztRQUMxQixrQkFBYSxHQUFHLENBQUMsQ0FBQztRQUdsQixjQUFTLEdBQUcsQ0FBQyxDQUFDO1FBQ2QsUUFBRyxHQUE4QixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBd0lyRCxDQUFDO0lBdElDLCtEQUErRDtJQUMvRCw0SEFBNEg7SUFDckgsT0FBTyxDQUFDLE9BQTJCLEVBQUUsV0FBa0MsRUFBRSxhQUFzQjtRQUNwRyxJQUFJLElBQUksQ0FBQyxXQUFXLEtBQUssU0FB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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/world-state",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.70.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -62,13 +62,13 @@
|
|
|
62
62
|
]
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@aztec/circuit-types": "0.
|
|
66
|
-
"@aztec/circuits.js": "0.
|
|
67
|
-
"@aztec/foundation": "0.
|
|
68
|
-
"@aztec/kv-store": "0.
|
|
69
|
-
"@aztec/merkle-tree": "0.
|
|
70
|
-
"@aztec/telemetry-client": "0.
|
|
71
|
-
"@aztec/types": "0.
|
|
65
|
+
"@aztec/circuit-types": "0.70.0",
|
|
66
|
+
"@aztec/circuits.js": "0.70.0",
|
|
67
|
+
"@aztec/foundation": "0.70.0",
|
|
68
|
+
"@aztec/kv-store": "0.70.0",
|
|
69
|
+
"@aztec/merkle-tree": "0.70.0",
|
|
70
|
+
"@aztec/telemetry-client": "0.70.0",
|
|
71
|
+
"@aztec/types": "0.70.0",
|
|
72
72
|
"bindings": "^1.5.0",
|
|
73
73
|
"msgpackr": "^1.10.2",
|
|
74
74
|
"tslib": "^2.4.0",
|
|
@@ -143,7 +143,7 @@ export class MerkleTreesFacade implements MerkleTreeReadOperations {
|
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
async getInitialStateReference(): Promise<StateReference> {
|
|
146
|
-
const resp = await this.instance.call(WorldStateMessageType.GET_INITIAL_STATE_REFERENCE,
|
|
146
|
+
const resp = await this.instance.call(WorldStateMessageType.GET_INITIAL_STATE_REFERENCE, { canonical: true });
|
|
147
147
|
|
|
148
148
|
return new StateReference(
|
|
149
149
|
treeStateReferenceToSnapshot(resp.state[MerkleTreeId.L1_TO_L2_MESSAGE_TREE]),
|
package/src/native/message.ts
CHANGED
|
@@ -314,6 +314,10 @@ interface WithWorldStateRevision {
|
|
|
314
314
|
revision: WorldStateRevision;
|
|
315
315
|
}
|
|
316
316
|
|
|
317
|
+
interface WithCanonicalForkId {
|
|
318
|
+
canonical: true;
|
|
319
|
+
}
|
|
320
|
+
|
|
317
321
|
interface WithLeafIndex {
|
|
318
322
|
leafIndex: bigint;
|
|
319
323
|
}
|
|
@@ -333,7 +337,7 @@ interface WithLeafValues {
|
|
|
333
337
|
leaves: SerializedLeafValue[];
|
|
334
338
|
}
|
|
335
339
|
|
|
336
|
-
interface BlockShiftRequest {
|
|
340
|
+
interface BlockShiftRequest extends WithCanonicalForkId {
|
|
337
341
|
toBlockNumber: bigint;
|
|
338
342
|
}
|
|
339
343
|
|
|
@@ -422,7 +426,7 @@ interface UpdateArchiveRequest extends WithForkId {
|
|
|
422
426
|
blockHeaderHash: Buffer;
|
|
423
427
|
}
|
|
424
428
|
|
|
425
|
-
interface SyncBlockRequest {
|
|
429
|
+
interface SyncBlockRequest extends WithCanonicalForkId {
|
|
426
430
|
blockNumber: number;
|
|
427
431
|
blockStateRef: BlockStateReference;
|
|
428
432
|
blockHeaderHash: Fr;
|
|
@@ -432,7 +436,7 @@ interface SyncBlockRequest {
|
|
|
432
436
|
publicDataWrites: readonly SerializedLeafValue[];
|
|
433
437
|
}
|
|
434
438
|
|
|
435
|
-
interface CreateForkRequest {
|
|
439
|
+
interface CreateForkRequest extends WithCanonicalForkId {
|
|
436
440
|
latest: boolean;
|
|
437
441
|
blockNumber: number;
|
|
438
442
|
}
|
|
@@ -441,22 +445,26 @@ interface CreateForkResponse {
|
|
|
441
445
|
forkId: number;
|
|
442
446
|
}
|
|
443
447
|
|
|
444
|
-
interface DeleteForkRequest {
|
|
445
|
-
|
|
448
|
+
interface DeleteForkRequest extends WithForkId {}
|
|
449
|
+
|
|
450
|
+
export type WorldStateRequestCategories = WithForkId | WithWorldStateRevision | WithCanonicalForkId;
|
|
451
|
+
|
|
452
|
+
export function isWithForkId(body: WorldStateRequestCategories): body is WithForkId {
|
|
453
|
+
return body && 'forkId' in body;
|
|
446
454
|
}
|
|
447
455
|
|
|
448
|
-
|
|
449
|
-
|
|
456
|
+
export function isWithRevision(body: WorldStateRequestCategories): body is WithWorldStateRevision {
|
|
457
|
+
return body && 'revision' in body;
|
|
450
458
|
}
|
|
451
459
|
|
|
452
|
-
|
|
453
|
-
|
|
460
|
+
export function isWithCanonical(body: WorldStateRequestCategories): body is WithCanonicalForkId {
|
|
461
|
+
return body && 'canonical' in body;
|
|
454
462
|
}
|
|
455
463
|
|
|
456
464
|
export type WorldStateRequest = {
|
|
457
465
|
[WorldStateMessageType.GET_TREE_INFO]: GetTreeInfoRequest;
|
|
458
466
|
[WorldStateMessageType.GET_STATE_REFERENCE]: GetStateReferenceRequest;
|
|
459
|
-
[WorldStateMessageType.GET_INITIAL_STATE_REFERENCE]:
|
|
467
|
+
[WorldStateMessageType.GET_INITIAL_STATE_REFERENCE]: WithCanonicalForkId;
|
|
460
468
|
|
|
461
469
|
[WorldStateMessageType.GET_LEAF_VALUE]: GetLeafRequest;
|
|
462
470
|
[WorldStateMessageType.GET_LEAF_PREIMAGE]: GetLeafPreImageRequest;
|
|
@@ -472,8 +480,8 @@ export type WorldStateRequest = {
|
|
|
472
480
|
|
|
473
481
|
[WorldStateMessageType.UPDATE_ARCHIVE]: UpdateArchiveRequest;
|
|
474
482
|
|
|
475
|
-
[WorldStateMessageType.COMMIT]:
|
|
476
|
-
[WorldStateMessageType.ROLLBACK]:
|
|
483
|
+
[WorldStateMessageType.COMMIT]: WithCanonicalForkId;
|
|
484
|
+
[WorldStateMessageType.ROLLBACK]: WithCanonicalForkId;
|
|
477
485
|
|
|
478
486
|
[WorldStateMessageType.SYNC_BLOCK]: SyncBlockRequest;
|
|
479
487
|
|
|
@@ -484,9 +492,9 @@ export type WorldStateRequest = {
|
|
|
484
492
|
[WorldStateMessageType.UNWIND_BLOCKS]: BlockShiftRequest;
|
|
485
493
|
[WorldStateMessageType.FINALISE_BLOCKS]: BlockShiftRequest;
|
|
486
494
|
|
|
487
|
-
[WorldStateMessageType.GET_STATUS]:
|
|
495
|
+
[WorldStateMessageType.GET_STATUS]: WithCanonicalForkId;
|
|
488
496
|
|
|
489
|
-
[WorldStateMessageType.CLOSE]:
|
|
497
|
+
[WorldStateMessageType.CLOSE]: WithCanonicalForkId;
|
|
490
498
|
};
|
|
491
499
|
|
|
492
500
|
export type WorldStateResponse = {
|
|
@@ -160,6 +160,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
160
160
|
const resp = await this.instance.call(WorldStateMessageType.CREATE_FORK, {
|
|
161
161
|
latest: blockNumber === undefined,
|
|
162
162
|
blockNumber: blockNumber ?? 0,
|
|
163
|
+
canonical: true,
|
|
163
164
|
});
|
|
164
165
|
return new MerkleTreesForkFacade(this.instance, this.initialHeader!, worldStateRevision(true, resp.forkId, 0));
|
|
165
166
|
}
|
|
@@ -198,6 +199,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
198
199
|
paddedNullifiers: paddedNullifiers.map(serializeLeaf),
|
|
199
200
|
publicDataWrites: publicDataWrites.map(serializeLeaf),
|
|
200
201
|
blockStateRef: blockStateReference(l2Block.header.state),
|
|
202
|
+
canonical: true,
|
|
201
203
|
},
|
|
202
204
|
this.sanitiseAndCacheSummaryFromFull.bind(this),
|
|
203
205
|
this.deleteCachedSummary.bind(this),
|
|
@@ -240,6 +242,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
240
242
|
WorldStateMessageType.FINALISE_BLOCKS,
|
|
241
243
|
{
|
|
242
244
|
toBlockNumber,
|
|
245
|
+
canonical: true,
|
|
243
246
|
},
|
|
244
247
|
this.sanitiseAndCacheSummary.bind(this),
|
|
245
248
|
this.deleteCachedSummary.bind(this),
|
|
@@ -257,6 +260,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
257
260
|
WorldStateMessageType.REMOVE_HISTORICAL_BLOCKS,
|
|
258
261
|
{
|
|
259
262
|
toBlockNumber,
|
|
263
|
+
canonical: true,
|
|
260
264
|
},
|
|
261
265
|
this.sanitiseAndCacheSummaryFromFull.bind(this),
|
|
262
266
|
this.deleteCachedSummary.bind(this),
|
|
@@ -273,6 +277,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
273
277
|
WorldStateMessageType.UNWIND_BLOCKS,
|
|
274
278
|
{
|
|
275
279
|
toBlockNumber,
|
|
280
|
+
canonical: true,
|
|
276
281
|
},
|
|
277
282
|
this.sanitiseAndCacheSummaryFromFull.bind(this),
|
|
278
283
|
this.deleteCachedSummary.bind(this),
|
|
@@ -283,7 +288,11 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
283
288
|
if (this.cachedStatusSummary !== undefined) {
|
|
284
289
|
return { ...this.cachedStatusSummary };
|
|
285
290
|
}
|
|
286
|
-
return await this.instance.call(
|
|
291
|
+
return await this.instance.call(
|
|
292
|
+
WorldStateMessageType.GET_STATUS,
|
|
293
|
+
{ canonical: true },
|
|
294
|
+
this.sanitiseAndCacheSummary.bind(this),
|
|
295
|
+
);
|
|
287
296
|
}
|
|
288
297
|
|
|
289
298
|
updateLeaf<ID extends IndexedTreeId>(
|
|
@@ -295,7 +304,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase {
|
|
|
295
304
|
}
|
|
296
305
|
|
|
297
306
|
private async getInitialStateReference(): Promise<StateReference> {
|
|
298
|
-
const resp = await this.instance.call(WorldStateMessageType.GET_INITIAL_STATE_REFERENCE,
|
|
307
|
+
const resp = await this.instance.call(WorldStateMessageType.GET_INITIAL_STATE_REFERENCE, { canonical: true });
|
|
299
308
|
|
|
300
309
|
return new StateReference(
|
|
301
310
|
treeStateReferenceToSnapshot(resp.state[MerkleTreeId.L1_TO_L2_MESSAGE_TREE]),
|
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
PUBLIC_DATA_TREE_HEIGHT,
|
|
12
12
|
} from '@aztec/circuits.js';
|
|
13
13
|
import { createLogger } from '@aztec/foundation/log';
|
|
14
|
-
import { SerialQueue } from '@aztec/foundation/queue';
|
|
15
14
|
|
|
16
15
|
import assert from 'assert';
|
|
17
16
|
import bindings from 'bindings';
|
|
@@ -25,8 +24,13 @@ import {
|
|
|
25
24
|
TypedMessage,
|
|
26
25
|
WorldStateMessageType,
|
|
27
26
|
type WorldStateRequest,
|
|
27
|
+
type WorldStateRequestCategories,
|
|
28
28
|
type WorldStateResponse,
|
|
29
|
+
isWithCanonical,
|
|
30
|
+
isWithForkId,
|
|
31
|
+
isWithRevision,
|
|
29
32
|
} from './message.js';
|
|
33
|
+
import { WorldStateOpsQueue } from './world_state_ops_queue.js';
|
|
30
34
|
|
|
31
35
|
// small extension to pack an NodeJS Fr instance to a representation that the C++ code can understand
|
|
32
36
|
// this only works for writes. Unpacking from C++ can't create Fr instances because the data is passed
|
|
@@ -49,7 +53,10 @@ const NATIVE_MODULE = bindings(NATIVE_LIBRARY_NAME);
|
|
|
49
53
|
const MAX_WORLD_STATE_THREADS = +(process.env.HARDWARE_CONCURRENCY || '16');
|
|
50
54
|
|
|
51
55
|
export interface NativeWorldStateInstance {
|
|
52
|
-
call<T extends WorldStateMessageType>(
|
|
56
|
+
call<T extends WorldStateMessageType>(
|
|
57
|
+
messageType: T,
|
|
58
|
+
body: WorldStateRequest[T] & WorldStateRequestCategories,
|
|
59
|
+
): Promise<WorldStateResponse[T]>;
|
|
53
60
|
}
|
|
54
61
|
|
|
55
62
|
/**
|
|
@@ -78,8 +85,8 @@ export class NativeWorldState implements NativeWorldStateInstance {
|
|
|
78
85
|
/** The actual native instance */
|
|
79
86
|
private instance: any;
|
|
80
87
|
|
|
81
|
-
|
|
82
|
-
private
|
|
88
|
+
// We maintain a map of queue to fork
|
|
89
|
+
private queues = new Map<number, WorldStateOpsQueue>();
|
|
83
90
|
|
|
84
91
|
/** Creates a new native WorldState instance */
|
|
85
92
|
constructor(
|
|
@@ -109,7 +116,8 @@ export class NativeWorldState implements NativeWorldStateInstance {
|
|
|
109
116
|
dbMapSizeKb,
|
|
110
117
|
threads,
|
|
111
118
|
);
|
|
112
|
-
|
|
119
|
+
// Manually create the queue for the canonical fork
|
|
120
|
+
this.queues.set(0, new WorldStateOpsQueue());
|
|
113
121
|
}
|
|
114
122
|
|
|
115
123
|
/**
|
|
@@ -120,25 +128,65 @@ export class NativeWorldState implements NativeWorldStateInstance {
|
|
|
120
128
|
* @param errorHandler - A callback called on request error, executed on the job queue
|
|
121
129
|
* @returns The response to the message
|
|
122
130
|
*/
|
|
123
|
-
public call<T extends WorldStateMessageType>(
|
|
131
|
+
public async call<T extends WorldStateMessageType>(
|
|
124
132
|
messageType: T,
|
|
125
|
-
body: WorldStateRequest[T],
|
|
133
|
+
body: WorldStateRequest[T] & WorldStateRequestCategories,
|
|
126
134
|
// allows for the pre-processing of responses on the job queue before being passed back
|
|
127
135
|
responseHandler = (response: WorldStateResponse[T]): WorldStateResponse[T] => response,
|
|
128
136
|
errorHandler = (_: string) => {},
|
|
129
137
|
): Promise<WorldStateResponse[T]> {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
})
|
|
138
|
+
// Here we determine which fork the request is being executed against and whether it requires uncommitted data
|
|
139
|
+
// We use the fork Id to select the appropriate request queue and the uncommitted data flag to pass to the queue
|
|
140
|
+
let forkId = -1;
|
|
141
|
+
// We assume it includes uncommitted unless explicitly told otherwise
|
|
142
|
+
let committedOnly = false;
|
|
143
|
+
|
|
144
|
+
// Canonical requests ALWAYS go against the canonical fork
|
|
145
|
+
// These include things like block syncs/unwinds etc
|
|
146
|
+
// These requests don't contain a fork ID
|
|
147
|
+
if (isWithCanonical(body)) {
|
|
148
|
+
forkId = 0;
|
|
149
|
+
} else if (isWithForkId(body)) {
|
|
150
|
+
forkId = body.forkId;
|
|
151
|
+
} else if (isWithRevision(body)) {
|
|
152
|
+
forkId = body.revision.forkId;
|
|
153
|
+
committedOnly = body.revision.includeUncommitted === false;
|
|
154
|
+
} else {
|
|
155
|
+
const _: never = body;
|
|
156
|
+
throw new Error(`Unable to determine forkId for message=${WorldStateMessageType[messageType]}`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Get the queue or create a new one
|
|
160
|
+
let requestQueue = this.queues.get(forkId);
|
|
161
|
+
if (requestQueue === undefined) {
|
|
162
|
+
requestQueue = new WorldStateOpsQueue();
|
|
163
|
+
this.queues.set(forkId, requestQueue);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Enqueue the request and wait for the response
|
|
167
|
+
const response = await requestQueue.execute(
|
|
168
|
+
async () => {
|
|
169
|
+
assert.notEqual(messageType, WorldStateMessageType.CLOSE, 'Use close() to close the native instance');
|
|
170
|
+
assert.equal(this.open, true, 'Native instance is closed');
|
|
171
|
+
let response: WorldStateResponse[T];
|
|
172
|
+
try {
|
|
173
|
+
response = await this._sendMessage(messageType, body);
|
|
174
|
+
} catch (error: any) {
|
|
175
|
+
errorHandler(error.message);
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
178
|
+
return responseHandler(response);
|
|
179
|
+
},
|
|
180
|
+
messageType,
|
|
181
|
+
committedOnly,
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
// If the request was to delete the fork then we clean it up here
|
|
185
|
+
if (messageType === WorldStateMessageType.DELETE_FORK) {
|
|
186
|
+
await requestQueue.stop();
|
|
187
|
+
this.queues.delete(forkId);
|
|
188
|
+
}
|
|
189
|
+
return response;
|
|
142
190
|
}
|
|
143
191
|
|
|
144
192
|
/**
|
|
@@ -149,13 +197,21 @@ export class NativeWorldState implements NativeWorldStateInstance {
|
|
|
149
197
|
return;
|
|
150
198
|
}
|
|
151
199
|
this.open = false;
|
|
152
|
-
|
|
153
|
-
|
|
200
|
+
const queue = this.queues.get(0)!;
|
|
201
|
+
|
|
202
|
+
await queue.execute(
|
|
203
|
+
async () => {
|
|
204
|
+
await this._sendMessage(WorldStateMessageType.CLOSE, { canonical: true });
|
|
205
|
+
},
|
|
206
|
+
WorldStateMessageType.CLOSE,
|
|
207
|
+
false,
|
|
208
|
+
);
|
|
209
|
+
await queue.stop();
|
|
154
210
|
}
|
|
155
211
|
|
|
156
212
|
private async _sendMessage<T extends WorldStateMessageType>(
|
|
157
213
|
messageType: T,
|
|
158
|
-
body: WorldStateRequest[T],
|
|
214
|
+
body: WorldStateRequest[T] & WorldStateRequestCategories,
|
|
159
215
|
): Promise<WorldStateResponse[T]> {
|
|
160
216
|
const messageId = this.nextMessageId++;
|
|
161
217
|
if (body) {
|