@typeberry/lib 0.9.0-c9f9e4d → 0.10.0-3e244fa
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/package.json +1 -1
- package/packages/core/collections/sorted-array.d.ts +1 -1
- package/packages/core/collections/sorted-array.d.ts.map +1 -1
- package/packages/core/collections/sorted-array.js +4 -2
- package/packages/core/collections/sorted-array.test.js +10 -0
- package/packages/core/collections/sorted-set.d.ts +1 -1
- package/packages/core/collections/sorted-set.d.ts.map +1 -1
- package/packages/core/collections/sorted-set.js +6 -2
- package/packages/core/collections/sorted-set.test.js +24 -0
- package/packages/core/utils/index.d.ts +1 -0
- package/packages/core/utils/index.d.ts.map +1 -1
- package/packages/core/utils/index.js +1 -0
- package/packages/core/utils/shutdown.d.ts +18 -0
- package/packages/core/utils/shutdown.d.ts.map +1 -0
- package/packages/core/utils/shutdown.js +3 -0
- package/packages/core/utils/shutdown.node.d.ts +5 -0
- package/packages/core/utils/shutdown.node.d.ts.map +1 -0
- package/packages/core/utils/shutdown.node.js +76 -0
- package/packages/core/utils/shutdown.test.d.ts +2 -0
- package/packages/core/utils/shutdown.test.d.ts.map +1 -0
- package/packages/core/utils/shutdown.test.js +164 -0
- package/packages/extensions/ipc/server.d.ts.map +1 -1
- package/packages/extensions/ipc/server.js +7 -0
- package/packages/jam/config-node/node-config.d.ts +20 -2
- package/packages/jam/config-node/node-config.d.ts.map +1 -1
- package/packages/jam/config-node/node-config.js +25 -3
- package/packages/jam/config-node/node-config.test.js +8 -1
- package/packages/jam/database/index.d.ts +1 -0
- package/packages/jam/database/index.d.ts.map +1 -1
- package/packages/jam/database/index.js +1 -0
- package/packages/jam/database/leaf-db-update.d.ts +1 -0
- package/packages/jam/database/leaf-db-update.d.ts.map +1 -1
- package/packages/jam/database/leaf-db-update.js +22 -5
- package/packages/jam/database/leaf-db-update.test.d.ts +2 -0
- package/packages/jam/database/leaf-db-update.test.d.ts.map +1 -0
- package/packages/jam/database/leaf-db-update.test.js +81 -0
- package/packages/jam/database/serialized-states-db.d.ts +4 -0
- package/packages/jam/database/serialized-states-db.d.ts.map +1 -1
- package/packages/jam/database/serialized-states-db.js +18 -2
- package/packages/jam/database/serialized-states-db.test.d.ts +2 -0
- package/packages/jam/database/serialized-states-db.test.d.ts.map +1 -0
- package/packages/jam/database/serialized-states-db.test.js +109 -0
- package/packages/jam/database/states.d.ts +11 -0
- package/packages/jam/database/states.d.ts.map +1 -1
- package/packages/jam/database/states.js +3 -0
- package/packages/jam/database/value-refs.d.ts +117 -0
- package/packages/jam/database/value-refs.d.ts.map +1 -0
- package/packages/jam/database/value-refs.js +206 -0
- package/packages/jam/database/value-refs.test.d.ts +2 -0
- package/packages/jam/database/value-refs.test.d.ts.map +1 -0
- package/packages/jam/database/value-refs.test.js +165 -0
- package/packages/jam/database-fjall/blocks.d.ts +25 -0
- package/packages/jam/database-fjall/blocks.d.ts.map +1 -0
- package/packages/jam/database-fjall/blocks.js +86 -0
- package/packages/jam/database-fjall/blocks.test.d.ts +2 -0
- package/packages/jam/database-fjall/blocks.test.d.ts.map +1 -0
- package/packages/jam/database-fjall/blocks.test.js +62 -0
- package/packages/jam/database-fjall/hybrid-states.d.ts +61 -10
- package/packages/jam/database-fjall/hybrid-states.d.ts.map +1 -1
- package/packages/jam/database-fjall/hybrid-states.js +131 -26
- package/packages/jam/database-fjall/hybrid-states.test.js +125 -3
- package/packages/jam/database-fjall/index.d.ts +2 -0
- package/packages/jam/database-fjall/index.d.ts.map +1 -1
- package/packages/jam/database-fjall/index.js +2 -0
- package/packages/jam/database-fjall/root.d.ts +29 -17
- package/packages/jam/database-fjall/root.d.ts.map +1 -1
- package/packages/jam/database-fjall/root.js +33 -13
- package/packages/jam/database-fjall/states.d.ts +31 -0
- package/packages/jam/database-fjall/states.d.ts.map +1 -0
- package/packages/jam/database-fjall/states.js +99 -0
- package/packages/jam/database-fjall/states.test.d.ts +2 -0
- package/packages/jam/database-fjall/states.test.d.ts.map +1 -0
- package/packages/jam/database-fjall/states.test.js +150 -0
- package/packages/jam/database-lmdb/hybrid-states.d.ts +12 -0
- package/packages/jam/database-lmdb/hybrid-states.d.ts.map +1 -1
- package/packages/jam/database-lmdb/hybrid-states.js +45 -4
- package/packages/jam/database-lmdb/hybrid-states.test.js +94 -2
- package/packages/jam/database-lmdb/states.d.ts +1 -0
- package/packages/jam/database-lmdb/states.d.ts.map +1 -1
- package/packages/jam/database-lmdb/states.js +5 -0
- package/packages/jam/node/export.d.ts.map +1 -1
- package/packages/jam/node/export.js +18 -9
- package/packages/jam/node/main-fuzz.d.ts +4 -1
- package/packages/jam/node/main-fuzz.d.ts.map +1 -1
- package/packages/jam/node/main-fuzz.js +127 -55
- package/packages/jam/node/main-importer.d.ts +11 -2
- package/packages/jam/node/main-importer.d.ts.map +1 -1
- package/packages/jam/node/main-importer.js +27 -12
- package/packages/jam/node/main.d.ts.map +1 -1
- package/packages/jam/node/main.js +42 -15
- package/packages/jam/node/workers.d.ts +4 -4
- package/packages/jam/node/workers.d.ts.map +1 -1
- package/packages/workers/api/config.d.ts +2 -2
- package/packages/workers/api/config.d.ts.map +1 -1
- package/packages/workers/api/config.js +1 -1
- package/packages/workers/api/port.d.ts +5 -1
- package/packages/workers/api/port.d.ts.map +1 -1
- package/packages/workers/api/port.js +56 -13
- package/packages/workers/api/port.test.js +35 -0
- package/packages/workers/api-node/config.d.ts +58 -9
- package/packages/workers/api-node/config.d.ts.map +1 -1
- package/packages/workers/api-node/config.js +140 -18
- package/packages/workers/api-node/config.test.js +52 -3
- package/packages/workers/api-node/port.d.ts +3 -0
- package/packages/workers/api-node/port.d.ts.map +1 -1
- package/packages/workers/api-node/port.js +31 -2
- package/packages/workers/api-node/port.test.js +17 -0
- package/packages/workers/api-node/protocol.d.ts +3 -3
- package/packages/workers/api-node/protocol.d.ts.map +1 -1
- package/packages/workers/api-node/protocol.js +18 -12
- package/packages/workers/block-authorship/main.js +1 -1
- package/packages/workers/importer/finality.d.ts +4 -0
- package/packages/workers/importer/finality.d.ts.map +1 -1
- package/packages/workers/importer/finality.js +10 -1
- package/packages/workers/importer/finality.test.js +6 -0
- package/packages/workers/importer/importer.d.ts.map +1 -1
- package/packages/workers/importer/importer.js +3 -0
- package/packages/workers/importer/main.d.ts +1 -1
- package/packages/workers/importer/main.d.ts.map +1 -1
- package/packages/workers/importer/main.js +1 -1
- package/packages/workers/jam-network/main.js +1 -1
|
@@ -2,7 +2,6 @@ import EventEmitter from "node:events";
|
|
|
2
2
|
import { threadId } from "node:worker_threads";
|
|
3
3
|
import { Decoder, Encoder } from "#@typeberry/codec";
|
|
4
4
|
import { Logger } from "#@typeberry/logger";
|
|
5
|
-
import { check } from "#@typeberry/utils";
|
|
6
5
|
const MESSAGE_KEYS = ["eventName", "responseId", "data"];
|
|
7
6
|
const logger = Logger.new(import.meta.filename, "workers/api");
|
|
8
7
|
export class ThreadPort {
|
|
@@ -14,6 +13,7 @@ export class ThreadPort {
|
|
|
14
13
|
}
|
|
15
14
|
threadId = threadId;
|
|
16
15
|
events = new EventEmitter();
|
|
16
|
+
pendingMessages = new Map();
|
|
17
17
|
static new(spec, port) {
|
|
18
18
|
return new ThreadPort(spec, port);
|
|
19
19
|
}
|
|
@@ -26,7 +26,10 @@ export class ThreadPort {
|
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
28
28
|
const { eventName, responseId, data } = input;
|
|
29
|
-
|
|
29
|
+
if (this.events.listeners(eventName).length === 0) {
|
|
30
|
+
this.queuePending(input);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
30
33
|
this.events.emit(eventName, responseId, data);
|
|
31
34
|
});
|
|
32
35
|
}
|
|
@@ -38,6 +41,7 @@ export class ThreadPort {
|
|
|
38
41
|
}
|
|
39
42
|
close() {
|
|
40
43
|
this.port.close();
|
|
44
|
+
this.pendingMessages.clear();
|
|
41
45
|
}
|
|
42
46
|
createListener(codec, callback) {
|
|
43
47
|
return (responseId, data) => {
|
|
@@ -64,12 +68,22 @@ export class ThreadPort {
|
|
|
64
68
|
on(event, codec, callback) {
|
|
65
69
|
const listener = this.createListener(codec, callback);
|
|
66
70
|
this.events.on(event, listener);
|
|
71
|
+
this.flushPending(event, listener);
|
|
67
72
|
return () => {
|
|
68
73
|
this.events.off(event, listener);
|
|
69
74
|
};
|
|
70
75
|
}
|
|
71
76
|
once(event, codec, callback) {
|
|
72
77
|
const listener = this.createListener(codec, callback);
|
|
78
|
+
const pending = this.pendingMessages.get(event);
|
|
79
|
+
const pendingMessage = pending?.shift();
|
|
80
|
+
if (pending?.length === 0) {
|
|
81
|
+
this.pendingMessages.delete(event);
|
|
82
|
+
}
|
|
83
|
+
if (pendingMessage !== undefined) {
|
|
84
|
+
listener(pendingMessage.responseId, pendingMessage.data);
|
|
85
|
+
return () => { };
|
|
86
|
+
}
|
|
73
87
|
this.events.once(event, listener);
|
|
74
88
|
return () => {
|
|
75
89
|
this.events.off(event, listener);
|
|
@@ -86,6 +100,21 @@ export class ThreadPort {
|
|
|
86
100
|
// always returns owned uint8arrays.
|
|
87
101
|
this.port.postMessage(message, [encoded.raw.buffer]);
|
|
88
102
|
}
|
|
103
|
+
queuePending(msg) {
|
|
104
|
+
const pending = this.pendingMessages.get(msg.eventName) ?? [];
|
|
105
|
+
pending.push(msg);
|
|
106
|
+
this.pendingMessages.set(msg.eventName, pending);
|
|
107
|
+
}
|
|
108
|
+
flushPending(event, listener) {
|
|
109
|
+
const pending = this.pendingMessages.get(event);
|
|
110
|
+
if (pending === undefined) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
this.pendingMessages.delete(event);
|
|
114
|
+
for (const msg of pending) {
|
|
115
|
+
listener(msg.responseId, msg.data);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
89
118
|
}
|
|
90
119
|
function isMessage(data) {
|
|
91
120
|
const isObject = data !== null && typeof data === "object";
|
|
@@ -36,4 +36,21 @@ describe("ThreadPort", () => {
|
|
|
36
36
|
data: tryAsU32(42),
|
|
37
37
|
});
|
|
38
38
|
});
|
|
39
|
+
it("should deliver messages sent before the listener is attached", async () => {
|
|
40
|
+
const tx = ThreadPort.new(spec, channel.port1);
|
|
41
|
+
const rx = ThreadPort.new(spec, channel.port2);
|
|
42
|
+
tx.postMessage("hello", codec.varU32, {
|
|
43
|
+
responseId: "10",
|
|
44
|
+
data: tryAsU32(42),
|
|
45
|
+
});
|
|
46
|
+
await setTimeout(10);
|
|
47
|
+
let received = null;
|
|
48
|
+
rx.on("hello", codec.varU32, (msg) => {
|
|
49
|
+
received = msg;
|
|
50
|
+
});
|
|
51
|
+
assert.deepStrictEqual(received, {
|
|
52
|
+
responseId: "10",
|
|
53
|
+
data: tryAsU32(42),
|
|
54
|
+
});
|
|
55
|
+
});
|
|
39
56
|
});
|
|
@@ -2,7 +2,7 @@ import { type MessagePort, Worker } from "node:worker_threads";
|
|
|
2
2
|
import type { Decode, Encode } from "#@typeberry/codec";
|
|
3
3
|
import { Listener } from "#@typeberry/listener";
|
|
4
4
|
import type { Api, Internal, LousyProtocol } from "#@typeberry/workers-api/types.js";
|
|
5
|
-
import {
|
|
5
|
+
import { type PersistentWorkerConfig, type TransferableConfig } from "./config.js";
|
|
6
6
|
/** Type of the control plane message. */
|
|
7
7
|
export declare enum WorkerControlPlaneMsg {
|
|
8
8
|
/** Transfers a communication port to some other thread. */
|
|
@@ -31,7 +31,7 @@ export type WorkerControlPlane = ({
|
|
|
31
31
|
/**
|
|
32
32
|
* Invoked by the main thread, to spawn a worker thread and initiate communication channel.
|
|
33
33
|
*/
|
|
34
|
-
export declare function spawnWorker<To, From, Params>(protocol: LousyProtocol<To, From>, bootstrapPath: URL, config:
|
|
34
|
+
export declare function spawnWorker<To, From, Params>(protocol: LousyProtocol<To, From>, bootstrapPath: URL, config: PersistentWorkerConfig<Params>, paramsEncoder: Encode<Params>): {
|
|
35
35
|
api: Api<typeof protocol>;
|
|
36
36
|
worker: Worker;
|
|
37
37
|
workerFinished: Promise<void>;
|
|
@@ -40,7 +40,7 @@ export declare function spawnWorker<To, From, Params>(protocol: LousyProtocol<To
|
|
|
40
40
|
* Initialize worker thread by awaiting the config message.
|
|
41
41
|
*/
|
|
42
42
|
export declare function initWorker<To, From, Params>(protocol: LousyProtocol<To, From>, paramsDecoder: Decode<Params>): Promise<{
|
|
43
|
-
config:
|
|
43
|
+
config: PersistentWorkerConfig<Params>;
|
|
44
44
|
comms: Internal<typeof protocol>;
|
|
45
45
|
threadComms: Listener<ThreadComms>;
|
|
46
46
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/api-node/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,WAAW,EAAc,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC3F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAI/C,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/api-node/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,WAAW,EAAc,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC3F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAI/C,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,EAEL,KAAK,sBAAsB,EAE3B,KAAK,kBAAkB,EACxB,MAAM,aAAa,CAAC;AAMrB,yCAAyC;AACzC,oBAAY,qBAAqB;IAC/B,2DAA2D;IAC3D,iBAAiB,IAAI;IACrB,sCAAsC;IACtC,MAAM,IAAI;CACX;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,0BAA0B;IAC1B,IAAI,EAAE,WAAW,CAAC;CACnB,CAAC;AACF,yFAAyF;AACzF,MAAM,MAAM,kBAAkB,GAC1B,CAAC;IACC,wDAAwD;IACxD,IAAI,EAAE,qBAAqB,CAAC,iBAAiB,CAAC;CAC/C,GAAG,WAAW,CAAC,GAChB;IACE,8EAA8E;IAC9E,IAAI,EAAE,qBAAqB,CAAC,MAAM,CAAC;IACnC,sCAAsC;IACtC,UAAU,EAAE,WAAW,CAAC;IACxB,4BAA4B;IAC5B,MAAM,EAAE,kBAAkB,CAAC;CAC5B,CAAC;AAeN;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAC1C,QAAQ,EAAE,aAAa,CAAC,EAAE,EAAE,IAAI,CAAC,EACjC,aAAa,EAAE,GAAG,EAClB,MAAM,EAAE,sBAAsB,CAAC,MAAM,CAAC,EACtC,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,GAC5B;IACD,GAAG,EAAE,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B,CAoCA;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAC/C,QAAQ,EAAE,aAAa,CAAC,EAAE,EAAE,IAAI,CAAC,EACjC,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,GAC5B,OAAO,CAAC;IACT,MAAM,EAAE,sBAAsB,CAAC,MAAM,CAAC,CAAC;IACvC,KAAK,EAAE,QAAQ,CAAC,OAAO,QAAQ,CAAC,CAAC;IACjC,WAAW,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;CACpC,CAAC,CAwDD"}
|
|
@@ -3,7 +3,7 @@ import { Listener } from "#@typeberry/listener";
|
|
|
3
3
|
import { Level, Logger } from "#@typeberry/logger";
|
|
4
4
|
import { assertNever } from "#@typeberry/utils";
|
|
5
5
|
import { Channel } from "#@typeberry/workers-api";
|
|
6
|
-
import { configTransferList,
|
|
6
|
+
import { configTransferList, persistentConfigFromTransferable, } from "./config.js";
|
|
7
7
|
import { logHeapLimit, workerResourceLimits } from "./host-environment.js";
|
|
8
8
|
import { ThreadPort } from "./port.js";
|
|
9
9
|
const logger = Logger.new(import.meta.filename, "workers");
|
|
@@ -70,13 +70,14 @@ export async function initWorker(protocol, paramsDecoder) {
|
|
|
70
70
|
logger.trace `Worker ${protocol.name} starting.`;
|
|
71
71
|
logHeapLimit(logger, protocol.name);
|
|
72
72
|
return new Promise((resolve, reject) => {
|
|
73
|
-
|
|
73
|
+
const workerParentPort = parentPort;
|
|
74
|
+
if (workerParentPort === null) {
|
|
74
75
|
throw new Error(`Unable to start ${protocol.name} worker. Not running in a worker thread!`);
|
|
75
76
|
}
|
|
76
|
-
|
|
77
|
+
workerParentPort.once("close", () => reject(new Error(`(${protocol.name}) parent port closed too early`)));
|
|
77
78
|
let isResolved = false;
|
|
78
79
|
const threadComms = new Listener();
|
|
79
|
-
|
|
80
|
+
workerParentPort.on("message", async (msg) => {
|
|
80
81
|
if (!isControlPlane(msg)) {
|
|
81
82
|
logger.error `--> (${protocol.name}) received unexpected message: ${msg}`;
|
|
82
83
|
return;
|
|
@@ -93,14 +94,19 @@ export async function initWorker(protocol, paramsDecoder) {
|
|
|
93
94
|
}
|
|
94
95
|
logger.trace `--> (${protocol.name}) received configuration.`;
|
|
95
96
|
isResolved = true;
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
97
|
+
try {
|
|
98
|
+
const config = await persistentConfigFromTransferable(paramsDecoder, msg.config);
|
|
99
|
+
const rxPort = ThreadPort.new(config.chainSpec, msg.parentPort);
|
|
100
|
+
const comms = Channel.rx(protocol, rxPort);
|
|
101
|
+
resolve({
|
|
102
|
+
config,
|
|
103
|
+
comms,
|
|
104
|
+
threadComms,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
catch (e) {
|
|
108
|
+
reject(e);
|
|
109
|
+
}
|
|
104
110
|
return;
|
|
105
111
|
}
|
|
106
112
|
assertNever(msg.kind);
|
|
@@ -18,7 +18,7 @@ export async function main(config, comms, networkingComms) {
|
|
|
18
18
|
await initWasm();
|
|
19
19
|
logger.info `🎁 Block Authorship running`;
|
|
20
20
|
const chainSpec = config.chainSpec;
|
|
21
|
-
const db = config.openDatabase();
|
|
21
|
+
const db = await config.openDatabase();
|
|
22
22
|
const blocks = db.getBlocksDb();
|
|
23
23
|
const states = db.getStatesDb();
|
|
24
24
|
const getBestState = () => {
|
|
@@ -4,6 +4,10 @@ import type { BlocksDb } from "#@typeberry/database";
|
|
|
4
4
|
export interface FinalityResult {
|
|
5
5
|
/** The newly finalized block hash. */
|
|
6
6
|
finalizedHash: HeaderHash;
|
|
7
|
+
/** All newly finalized block hashes, ancestor-first, ending at `finalizedHash`. */
|
|
8
|
+
finalizedChain: HeaderHash[];
|
|
9
|
+
/** Blocks that became finalized in this round, ancestor-first. */
|
|
10
|
+
newlyFinalizedHeaders: HeaderHash[];
|
|
7
11
|
/** Block hashes whose states are no longer needed and can be pruned. */
|
|
8
12
|
prunableStateHashes: HeaderHash[];
|
|
9
13
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"finality.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/importer/finality.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAKpD,qDAAqD;AACrD,MAAM,WAAW,cAAc;IAC7B,sCAAsC;IACtC,aAAa,EAAE,UAAU,CAAC;IAC1B,wEAAwE;IACxE,mBAAmB,EAAE,UAAU,EAAE,CAAC;CACnC;AAED,8DAA8D;AAC9D,MAAM,WAAW,SAAS;IACxB,8FAA8F;IAC9F,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,cAAc,GAAG,IAAI,CAAC;CAChE;AAKD;;;;;;;GAOG;AACH,qBAAa,cAAe,YAAW,SAAS;IAS5C,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IATxB,OAAO,CAAC,iBAAiB,CAAa;IACtC,OAAO,CAAC,WAAW,CAAe;IAElC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc;IAI9D,OAAO;IAQP,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,cAAc,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"finality.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/importer/finality.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAKpD,qDAAqD;AACrD,MAAM,WAAW,cAAc;IAC7B,sCAAsC;IACtC,aAAa,EAAE,UAAU,CAAC;IAC1B,mFAAmF;IACnF,cAAc,EAAE,UAAU,EAAE,CAAC;IAC7B,kEAAkE;IAClE,qBAAqB,EAAE,UAAU,EAAE,CAAC;IACpC,wEAAwE;IACxE,mBAAmB,EAAE,UAAU,EAAE,CAAC;CACnC;AAED,8DAA8D;AAC9D,MAAM,WAAW,SAAS;IACxB,8FAA8F;IAC9F,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,cAAc,GAAG,IAAI,CAAC;CAChE;AAKD;;;;;;;GAOG;AACH,qBAAa,cAAe,YAAW,SAAS;IAS5C,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IATxB,OAAO,CAAC,iBAAiB,CAAa;IACtC,OAAO,CAAC,WAAW,CAAe;IAElC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc;IAI9D,OAAO;IAQP,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,cAAc,GAAG,IAAI;CAkG/D"}
|
|
@@ -71,15 +71,24 @@ export class DummyFinalizer {
|
|
|
71
71
|
// The newly finalized block sits at index (length - 1 - depth).
|
|
72
72
|
const finalizedIdx = extendedChain.length - 1 - this.depth;
|
|
73
73
|
const finalizedHash = extendedChain[finalizedIdx];
|
|
74
|
+
// Everything up to (and including) that index becomes finalized now.
|
|
75
|
+
const finalizedChain = extendedChain.slice(0, finalizedIdx + 1);
|
|
74
76
|
// Collect prunable hashes and rebuild the unfinalized set.
|
|
75
77
|
// The previously finalized block's state is no longer needed.
|
|
76
78
|
const prunable = [this.lastFinalizedHash];
|
|
79
|
+
const newlyFinalized = [];
|
|
77
80
|
const newUnfinalized = [];
|
|
78
81
|
for (const chain of this.unfinalized) {
|
|
79
82
|
// Find the finalized block in this chain.
|
|
80
83
|
const finIdx = chain.findIndex((h) => h.isEqualTo(finalizedHash));
|
|
81
84
|
if (finIdx !== -1) {
|
|
82
85
|
// Chain contains the finalized block — it's still alive.
|
|
86
|
+
// Collect newly finalized blocks only once (forks share prefixes).
|
|
87
|
+
if (newlyFinalized.length === 0) {
|
|
88
|
+
for (let i = 0; i <= finIdx; i++) {
|
|
89
|
+
newlyFinalized.push(chain[i]);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
83
92
|
// Prune states for blocks before the finalized block.
|
|
84
93
|
for (let i = 0; i < finIdx; i++) {
|
|
85
94
|
prunable.push(chain[i]);
|
|
@@ -100,6 +109,6 @@ export class DummyFinalizer {
|
|
|
100
109
|
}
|
|
101
110
|
this.lastFinalizedHash = finalizedHash;
|
|
102
111
|
this.unfinalized = newUnfinalized;
|
|
103
|
-
return { finalizedHash, prunableStateHashes: prunable };
|
|
112
|
+
return { finalizedHash, finalizedChain, newlyFinalizedHeaders: newlyFinalized, prunableStateHashes: prunable };
|
|
104
113
|
}
|
|
105
114
|
}
|
|
@@ -77,6 +77,8 @@ describe("DummyFinalizer", () => {
|
|
|
77
77
|
const result = finalizer.onBlockImported(chain[6]);
|
|
78
78
|
assertExists(result);
|
|
79
79
|
assert.strictEqual(result.finalizedHash.isEqualTo(chain[3]), true);
|
|
80
|
+
// The whole prefix becomes finalized, ancestor-first.
|
|
81
|
+
assert.deepStrictEqual(result.finalizedChain.map((h) => h.toString()), chain.slice(0, 4).map((h) => h.toString()));
|
|
80
82
|
});
|
|
81
83
|
it("should prune prev finalized and depth predecessors on first finality", async () => {
|
|
82
84
|
const db = InMemoryBlocks.new();
|
|
@@ -111,6 +113,7 @@ describe("DummyFinalizer", () => {
|
|
|
111
113
|
const r1 = finalizer.onBlockImported(chain[4]);
|
|
112
114
|
assertExists(r1);
|
|
113
115
|
assert.strictEqual(r1.finalizedHash.isEqualTo(chain[2]), true);
|
|
116
|
+
assert.deepStrictEqual(r1.finalizedChain.map((h) => h.toString()), chain.slice(0, 3).map((h) => h.toString()));
|
|
114
117
|
assert.strictEqual(r1.prunableStateHashes.length, 3);
|
|
115
118
|
assert.ok(r1.prunableStateHashes[0].isEqualTo(genesis));
|
|
116
119
|
assert.ok(r1.prunableStateHashes[1].isEqualTo(chain[0]));
|
|
@@ -122,6 +125,8 @@ describe("DummyFinalizer", () => {
|
|
|
122
125
|
const r2 = finalizer.onBlockImported(chain[7]);
|
|
123
126
|
assertExists(r2);
|
|
124
127
|
assert.strictEqual(r2.finalizedHash.isEqualTo(chain[5]), true);
|
|
128
|
+
// Only the blocks finalized in this round, not the ones from r1.
|
|
129
|
+
assert.deepStrictEqual(r2.finalizedChain.map((h) => h.toString()), chain.slice(3, 6).map((h) => h.toString()));
|
|
125
130
|
assert.strictEqual(r2.prunableStateHashes.length, 3);
|
|
126
131
|
assert.ok(r2.prunableStateHashes[0].isEqualTo(chain[2]));
|
|
127
132
|
assert.ok(r2.prunableStateHashes[1].isEqualTo(chain[3]));
|
|
@@ -204,6 +209,7 @@ describe("DummyFinalizer", () => {
|
|
|
204
209
|
const result = finalizer.onBlockImported(a5);
|
|
205
210
|
assertExists(result);
|
|
206
211
|
assert.strictEqual(result.finalizedHash.isEqualTo(a3), true);
|
|
212
|
+
assert.deepStrictEqual(result.finalizedChain.map((h) => h.toString()), [a1, a2, a3].map((h) => h.toString()));
|
|
207
213
|
// Fork B [B1, B2] is dead (doesn't contain A3). B1 and B2 should be pruned.
|
|
208
214
|
// Also: genesis (prev finalized) and A1, A2 pruned (before A3 in chain A).
|
|
209
215
|
const prunedStrings = result.prunableStateHashes.map((h) => h.toString());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"importer.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/importer/importer.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"importer.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/importer/importer.ts"],"names":[],"mappings":"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"}
|
|
@@ -177,6 +177,9 @@ export class Importer {
|
|
|
177
177
|
const pruneBlocks = this.options.pruneBlocks ?? false;
|
|
178
178
|
this.logger
|
|
179
179
|
.info `🦭 Finalized: ${finality.finalizedHash.toStringTruncated()} (${finality.prunableStateHashes.length} to prune, blocks: ${pruneBlocks})`;
|
|
180
|
+
// Commit the finalized blocks BEFORE pruning: `markUnused` treats states
|
|
181
|
+
// with a pending value delta as dead forks and releases their values.
|
|
182
|
+
this.states.commitFinalized(finality.newlyFinalizedHeaders);
|
|
180
183
|
for (const hash of finality.prunableStateHashes) {
|
|
181
184
|
this.states.markUnused(hash);
|
|
182
185
|
if (pruneBlocks) {
|
|
@@ -9,7 +9,7 @@ export type CreateImporterOptions = {
|
|
|
9
9
|
};
|
|
10
10
|
export declare function createImporter(config: Config, options?: CreateImporterOptions): Promise<{
|
|
11
11
|
importer: Importer;
|
|
12
|
-
db: ReturnType<Config["openDatabase"]
|
|
12
|
+
db: Awaited<ReturnType<Config["openDatabase"]>>;
|
|
13
13
|
}>;
|
|
14
14
|
/**
|
|
15
15
|
* The `BlockImporter` listens to `block` signals, where it expects
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/importer/main.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAGtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAMtE,MAAM,MAAM,MAAM,GAAG,YAAY,CAAC,cAAc,EAAE,QAAQ,EAAE,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAE/F,MAAM,MAAM,qBAAqB,GAAG;IAClC,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC,CAAC;AAEF,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC;IACT,QAAQ,EAAE,QAAQ,CAAC;IACnB,EAAE,EAAE,UAAU,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/importer/main.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAGtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAMtE,MAAM,MAAM,MAAM,GAAG,YAAY,CAAC,cAAc,EAAE,QAAQ,EAAE,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAE/F,MAAM,MAAM,qBAAqB,GAAG;IAClC,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC,CAAC;AAEF,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC;IACT,QAAQ,EAAE,QAAQ,CAAC;IACnB,EAAE,EAAE,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;CACjD,CAAC,CA8BD;AAED;;;;;GAKG;AACH,wBAAsB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,iBAwCjE"}
|
|
@@ -10,7 +10,7 @@ const keccakHasher = keccak.KeccakHasher.create();
|
|
|
10
10
|
const blake2b = Blake2b.createHasher();
|
|
11
11
|
export async function createImporter(config, options = {}) {
|
|
12
12
|
const chainSpec = config.chainSpec;
|
|
13
|
-
const db = config.openDatabase({ readonly: false });
|
|
13
|
+
const db = await config.openDatabase({ readonly: false });
|
|
14
14
|
const pvm = config.workerParams.pvm;
|
|
15
15
|
const blocks = db.getBlocksDb();
|
|
16
16
|
const states = db.getStatesDb();
|
|
@@ -19,7 +19,7 @@ export async function main(config, comms, authorshipComms) {
|
|
|
19
19
|
logger.trace `🛜 Network starting`;
|
|
20
20
|
// Await the configuration object
|
|
21
21
|
const chainSpec = config.chainSpec;
|
|
22
|
-
const db = config.openDatabase();
|
|
22
|
+
const db = await config.openDatabase();
|
|
23
23
|
const blocks = db.getBlocksDb();
|
|
24
24
|
const params = config.workerParams;
|
|
25
25
|
const key = await ed25519.privateKey(params.key);
|