@typeberry/lib 0.8.4 → 0.9.0-4a9f363
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 +6 -4
- package/packages/configs/index.d.ts +30 -1
- package/packages/configs/index.d.ts.map +1 -1
- package/packages/configs/index.js +4 -2
- package/packages/configs/typeberry-dev-full.json +29 -0
- package/packages/core/bytes/bytes.d.ts +1 -0
- package/packages/core/bytes/bytes.d.ts.map +1 -1
- package/packages/core/bytes/bytes.js +8 -0
- 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/debug.d.ts +4 -2
- package/packages/core/utils/debug.d.ts.map +1 -1
- package/packages/core/utils/debug.js +18 -13
- package/packages/core/utils/debug.test.js +12 -6
- 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 +22 -3
- package/packages/jam/config-node/node-config.d.ts.map +1 -1
- package/packages/jam/config-node/node-config.js +33 -6
- package/packages/jam/config-node/node-config.test.js +11 -4
- 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 +1 -0
- package/packages/jam/database/serialized-states-db.d.ts.map +1 -1
- package/packages/jam/database/serialized-states-db.js +4 -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 +96 -0
- package/packages/jam/database-fjall/hybrid-states.d.ts.map +1 -0
- package/packages/jam/database-fjall/hybrid-states.js +218 -0
- package/packages/jam/database-fjall/hybrid-states.test.d.ts +2 -0
- package/packages/jam/database-fjall/hybrid-states.test.d.ts.map +1 -0
- package/packages/jam/database-fjall/hybrid-states.test.js +113 -0
- package/packages/jam/database-fjall/index.d.ts +5 -0
- package/packages/jam/database-fjall/index.d.ts.map +1 -0
- package/packages/jam/database-fjall/index.js +4 -0
- package/packages/jam/database-fjall/root.d.ts +64 -0
- package/packages/jam/database-fjall/root.d.ts.map +1 -0
- package/packages/jam/database-fjall/root.js +105 -0
- 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/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/jamnp-s/tasks/ticket-distribution.d.ts +18 -10
- package/packages/jam/jamnp-s/tasks/ticket-distribution.d.ts.map +1 -1
- package/packages/jam/jamnp-s/tasks/ticket-distribution.js +44 -68
- package/packages/jam/jamnp-s/tasks/ticket-distribution.test.js +30 -8
- 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 +142 -55
- package/packages/jam/node/main-importer.d.ts +15 -3
- package/packages/jam/node/main-importer.d.ts.map +1 -1
- package/packages/jam/node/main-importer.js +30 -14
- 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/jam/safrole/bandersnatch-vrf.d.ts +24 -4
- package/packages/jam/safrole/bandersnatch-vrf.d.ts.map +1 -1
- package/packages/jam/safrole/bandersnatch-vrf.js +63 -26
- package/packages/jam/safrole/bandersnatch-vrf.test.js +12 -9
- package/packages/jam/safrole/bandersnatch-wasm.d.ts +10 -0
- package/packages/jam/safrole/bandersnatch-wasm.d.ts.map +1 -1
- package/packages/jam/safrole/bandersnatch-wasm.js +12 -0
- package/packages/jam/safrole/safrole.js +5 -5
- package/packages/jam/safrole/safrole.test.js +13 -13
- package/packages/jam/ticket-pool/index.d.ts +4 -0
- package/packages/jam/ticket-pool/index.d.ts.map +1 -0
- package/packages/jam/ticket-pool/index.js +3 -0
- package/packages/jam/ticket-pool/pending-ticket-pool.d.ts +30 -0
- package/packages/jam/ticket-pool/pending-ticket-pool.d.ts.map +1 -0
- package/packages/jam/ticket-pool/pending-ticket-pool.js +56 -0
- package/packages/jam/ticket-pool/pending-ticket-pool.test.d.ts +2 -0
- package/packages/jam/ticket-pool/pending-ticket-pool.test.d.ts.map +1 -0
- package/packages/jam/ticket-pool/pending-ticket-pool.test.js +67 -0
- package/packages/jam/ticket-pool/ticket-validator.d.ts +47 -0
- package/packages/jam/ticket-pool/ticket-validator.d.ts.map +1 -0
- package/packages/jam/ticket-pool/ticket-validator.js +34 -0
- package/packages/jam/ticket-pool/ticket-validator.test.d.ts +2 -0
- package/packages/jam/ticket-pool/ticket-validator.test.d.ts.map +1 -0
- package/packages/jam/ticket-pool/ticket-validator.test.js +35 -0
- package/packages/jam/ticket-pool/verified-ticket-pool.d.ts +26 -0
- package/packages/jam/ticket-pool/verified-ticket-pool.d.ts.map +1 -0
- package/packages/jam/ticket-pool/verified-ticket-pool.js +41 -0
- package/packages/jam/ticket-pool/verified-ticket-pool.test.d.ts +2 -0
- package/packages/jam/ticket-pool/verified-ticket-pool.test.d.ts.map +1 -0
- package/packages/jam/ticket-pool/verified-ticket-pool.test.js +54 -0
- 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 +65 -9
- package/packages/workers/api-node/config.d.ts.map +1 -1
- package/packages/workers/api-node/config.js +151 -26
- package/packages/workers/api-node/config.test.js +88 -2
- 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/{generator.d.ts → block-generator.d.ts} +5 -5
- package/packages/workers/block-authorship/block-generator.d.ts.map +1 -0
- package/packages/workers/block-authorship/{generator.js → block-generator.js} +3 -3
- package/packages/workers/block-authorship/block-generator.test.d.ts +2 -0
- package/packages/workers/block-authorship/block-generator.test.d.ts.map +1 -0
- package/packages/workers/block-authorship/{generator.test.js → block-generator.test.js} +8 -8
- package/packages/workers/block-authorship/epoch-authoring-slots.d.ts +35 -0
- package/packages/workers/block-authorship/epoch-authoring-slots.d.ts.map +1 -0
- package/packages/workers/block-authorship/epoch-authoring-slots.js +86 -0
- package/packages/workers/block-authorship/epoch-tracker.d.ts +29 -0
- package/packages/workers/block-authorship/epoch-tracker.d.ts.map +1 -0
- package/packages/workers/block-authorship/epoch-tracker.js +80 -0
- package/packages/workers/block-authorship/index.d.ts.map +1 -1
- package/packages/workers/block-authorship/index.js +1 -1
- package/packages/workers/block-authorship/main.d.ts +3 -0
- package/packages/workers/block-authorship/main.d.ts.map +1 -1
- package/packages/workers/block-authorship/main.js +198 -316
- package/packages/workers/block-authorship/ticket-generator/bootstrap-main.d.ts +2 -0
- package/packages/workers/block-authorship/ticket-generator/bootstrap-main.d.ts.map +1 -0
- package/packages/workers/block-authorship/ticket-generator/bootstrap-main.js +23 -0
- package/packages/workers/block-authorship/ticket-generator/index.d.ts +16 -0
- package/packages/workers/block-authorship/ticket-generator/index.d.ts.map +1 -0
- package/packages/workers/block-authorship/ticket-generator/index.js +62 -0
- package/packages/workers/block-authorship/ticket-generator/protocol.d.ts +50 -0
- package/packages/workers/block-authorship/ticket-generator/protocol.d.ts.map +1 -0
- package/packages/workers/block-authorship/ticket-generator/protocol.js +54 -0
- package/packages/workers/block-authorship/{ticket-generator.d.ts → ticket-generator/ticket-generator.d.ts} +4 -0
- package/packages/workers/block-authorship/ticket-generator/ticket-generator.d.ts.map +1 -0
- package/packages/workers/block-authorship/{ticket-generator.js → ticket-generator/ticket-generator.js} +19 -9
- package/packages/workers/block-authorship/ticket-generator/ticket-generator.test.d.ts.map +1 -0
- package/packages/workers/block-authorship/{ticket-generator.test.js → ticket-generator/ticket-generator.test.js} +13 -9
- package/packages/workers/block-authorship/ticket-generator/worker-pool.d.ts +36 -0
- package/packages/workers/block-authorship/ticket-generator/worker-pool.d.ts.map +1 -0
- package/packages/workers/block-authorship/ticket-generator/worker-pool.js +111 -0
- package/packages/workers/block-authorship/ticket-validator.d.ts +31 -0
- package/packages/workers/block-authorship/ticket-validator.d.ts.map +1 -0
- package/packages/workers/block-authorship/ticket-validator.js +59 -0
- package/packages/workers/comms-authorship-network/protocol.d.ts +14 -4
- package/packages/workers/comms-authorship-network/protocol.d.ts.map +1 -1
- package/packages/workers/comms-authorship-network/protocol.js +12 -6
- package/packages/workers/comms-authorship-network/tickets-message.d.ts +0 -14
- package/packages/workers/comms-authorship-network/tickets-message.d.ts.map +1 -1
- package/packages/workers/comms-authorship-network/tickets-message.js +0 -17
- package/packages/workers/importer/importer.d.ts +2 -2
- package/packages/workers/importer/importer.d.ts.map +1 -1
- package/packages/workers/importer/importer.js +5 -5
- 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/importer/stats.d.ts +1 -3
- package/packages/workers/importer/stats.d.ts.map +1 -1
- package/packages/workers/importer/stats.js +12 -12
- package/packages/workers/jam-network/main.d.ts.map +1 -1
- package/packages/workers/jam-network/main.js +26 -5
- package/packages/workers/block-authorship/generator.d.ts.map +0 -1
- package/packages/workers/block-authorship/generator.test.d.ts +0 -2
- package/packages/workers/block-authorship/generator.test.d.ts.map +0 -1
- package/packages/workers/block-authorship/ticket-generator.d.ts.map +0 -1
- package/packages/workers/block-authorship/ticket-generator.test.d.ts.map +0 -1
- /package/packages/configs/{typeberry-dev.json → typeberry-dev-tiny.json} +0 -0
- /package/packages/workers/block-authorship/{ticket-generator.test.d.ts → ticket-generator/ticket-generator.test.d.ts} +0 -0
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import { Decoder, Encoder } from "#@typeberry/codec";
|
|
2
2
|
import { ChainSpec } from "#@typeberry/config";
|
|
3
3
|
import { InMemoryBlocks, InMemorySerializedStates, } from "#@typeberry/database";
|
|
4
|
-
import { HybridSerializedStates,
|
|
4
|
+
import { FjallBlocks, HybridSerializedStates as FjallHybridSerializedStates, FjallRoot, FjallStates, FjallValuesSession, } from "#@typeberry/database-fjall";
|
|
5
|
+
import { LmdbBlocks, HybridSerializedStates as LmdbHybridSerializedStates, LmdbRoot, LmdbStates, } from "#@typeberry/database-lmdb";
|
|
5
6
|
import { Blake2b } from "#@typeberry/hash";
|
|
6
7
|
import { ThreadPort } from "./port.js";
|
|
7
|
-
|
|
8
|
+
// Re-exported so the fuzz target can open one values session per run and reuse
|
|
9
|
+
// it across resets (see `HybridWorkerConfig` / `mainFuzz`).
|
|
10
|
+
export { FjallValuesSession };
|
|
11
|
+
/**
|
|
12
|
+
* Worker config for node.js, backed by the LMDB database.
|
|
13
|
+
*
|
|
14
|
+
* @deprecated lmdb is retained as an explicit fallback. Use `FjallWorkerConfig` for regular nodes.
|
|
15
|
+
*/
|
|
8
16
|
export class LmdbWorkerConfig {
|
|
9
17
|
nodeName;
|
|
10
18
|
chainSpec;
|
|
@@ -18,10 +26,10 @@ export class LmdbWorkerConfig {
|
|
|
18
26
|
}
|
|
19
27
|
/** Restore node config from a transferable config object. */
|
|
20
28
|
static async fromTransferable(decodeParams, config) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const
|
|
29
|
+
if (config.databaseBackend !== "lmdb") {
|
|
30
|
+
throw new Error(`Expected lmdb worker config, got ${config.databaseBackend}.`);
|
|
31
|
+
}
|
|
32
|
+
const { blake2b, chainSpec, workerParams, ports } = await decodeTransferableConfig(decodeParams, config);
|
|
25
33
|
return LmdbWorkerConfig.new({
|
|
26
34
|
nodeName: config.nodeName,
|
|
27
35
|
chainSpec,
|
|
@@ -32,7 +40,7 @@ export class LmdbWorkerConfig {
|
|
|
32
40
|
});
|
|
33
41
|
}
|
|
34
42
|
constructor(nodeName, chainSpec, workerParams, dbPath, blake2b, ports,
|
|
35
|
-
// When set, the underlying
|
|
43
|
+
// When set, the underlying database skips fsync. Only safe for throwaway
|
|
36
44
|
// databases (the fuzz target wipes on reset). Not transferred to worker
|
|
37
45
|
// threads, so the durable main node path always gets the default.
|
|
38
46
|
ephemeral = false) {
|
|
@@ -44,7 +52,7 @@ export class LmdbWorkerConfig {
|
|
|
44
52
|
this.ports = ports;
|
|
45
53
|
this.ephemeral = ephemeral;
|
|
46
54
|
}
|
|
47
|
-
openDatabase(options = { readonly: true }) {
|
|
55
|
+
async openDatabase(options = { readonly: true }) {
|
|
48
56
|
const lmdb = LmdbRoot.new(this.dbPath, {
|
|
49
57
|
readOnly: options.readonly,
|
|
50
58
|
ephemeral: this.ephemeral,
|
|
@@ -58,14 +66,128 @@ export class LmdbWorkerConfig {
|
|
|
58
66
|
/** Convert this config into a thread-transferable object. */
|
|
59
67
|
intoTransferable(paramsCodec) {
|
|
60
68
|
return {
|
|
69
|
+
databaseBackend: "lmdb",
|
|
70
|
+
nodeName: this.nodeName,
|
|
71
|
+
chainSpec: this.chainSpec,
|
|
72
|
+
workerParams: Encoder.encodeObject(paramsCodec, this.workerParams, this.chainSpec).raw,
|
|
73
|
+
dbPath: this.dbPath,
|
|
74
|
+
workerPorts: Array.from(this.ports.entries()).map(([name, port]) => [name, port.intoTransferable()]),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/** Worker config for node.js, backed by a shared fjall engine. */
|
|
79
|
+
export class FjallWorkerConfig {
|
|
80
|
+
nodeName;
|
|
81
|
+
chainSpec;
|
|
82
|
+
workerParams;
|
|
83
|
+
dbPath;
|
|
84
|
+
blake2b;
|
|
85
|
+
ports;
|
|
86
|
+
ephemeral;
|
|
87
|
+
cacheSizeBytes;
|
|
88
|
+
static new({ nodeName, chainSpec, workerParams, dbPath, blake2b, ports = new Map(), ephemeral = false, cacheSizeBytes, }) {
|
|
89
|
+
return new FjallWorkerConfig(nodeName, chainSpec, workerParams, dbPath, blake2b, ports, ephemeral, cacheSizeBytes);
|
|
90
|
+
}
|
|
91
|
+
/** Restore node config from a transferable config object. */
|
|
92
|
+
static async fromTransferable(decodeParams, config) {
|
|
93
|
+
if (config.databaseBackend !== "fjall") {
|
|
94
|
+
throw new Error(`Expected fjall worker config, got ${config.databaseBackend}.`);
|
|
95
|
+
}
|
|
96
|
+
const { blake2b, chainSpec, workerParams, ports } = await decodeTransferableConfig(decodeParams, config);
|
|
97
|
+
return FjallWorkerConfig.new({
|
|
98
|
+
nodeName: config.nodeName,
|
|
99
|
+
chainSpec,
|
|
100
|
+
workerParams,
|
|
101
|
+
dbPath: config.dbPath,
|
|
102
|
+
blake2b,
|
|
103
|
+
ports,
|
|
104
|
+
cacheSizeBytes: config.cacheSizeBytes,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
constructor(nodeName, chainSpec, workerParams, dbPath, blake2b, ports,
|
|
108
|
+
// Kept for the fuzz/importer path. When set, persist() is skipped.
|
|
109
|
+
ephemeral = false, cacheSizeBytes = undefined) {
|
|
110
|
+
this.nodeName = nodeName;
|
|
111
|
+
this.chainSpec = chainSpec;
|
|
112
|
+
this.workerParams = workerParams;
|
|
113
|
+
this.dbPath = dbPath;
|
|
114
|
+
this.blake2b = blake2b;
|
|
115
|
+
this.ports = ports;
|
|
116
|
+
this.ephemeral = ephemeral;
|
|
117
|
+
this.cacheSizeBytes = cacheSizeBytes;
|
|
118
|
+
}
|
|
119
|
+
async openDatabase(options = { readonly: true }) {
|
|
120
|
+
const fjall = await FjallRoot.open(this.dbPath, {
|
|
121
|
+
readOnly: options.readonly,
|
|
122
|
+
ephemeral: this.ephemeral,
|
|
123
|
+
cacheSizeBytes: this.cacheSizeBytes,
|
|
124
|
+
});
|
|
125
|
+
let blocks = null;
|
|
126
|
+
let states = null;
|
|
127
|
+
try {
|
|
128
|
+
[blocks, states] = await Promise.all([
|
|
129
|
+
FjallBlocks.open(this.chainSpec, fjall),
|
|
130
|
+
FjallStates.open(this.chainSpec, this.blake2b, fjall),
|
|
131
|
+
]);
|
|
132
|
+
}
|
|
133
|
+
catch (e) {
|
|
134
|
+
await fjall.close();
|
|
135
|
+
throw e;
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
getBlocksDb: () => {
|
|
139
|
+
if (blocks === null) {
|
|
140
|
+
throw new Error("Fjall database is closed.");
|
|
141
|
+
}
|
|
142
|
+
return blocks;
|
|
143
|
+
},
|
|
144
|
+
getStatesDb: () => {
|
|
145
|
+
if (states === null) {
|
|
146
|
+
throw new Error("Fjall database is closed.");
|
|
147
|
+
}
|
|
148
|
+
return states;
|
|
149
|
+
},
|
|
150
|
+
close: async () => {
|
|
151
|
+
blocks = null;
|
|
152
|
+
states = null;
|
|
153
|
+
await fjall.close();
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/** Convert this config into a thread-transferable object. */
|
|
158
|
+
intoTransferable(paramsCodec) {
|
|
159
|
+
return {
|
|
160
|
+
databaseBackend: "fjall",
|
|
61
161
|
nodeName: this.nodeName,
|
|
62
162
|
chainSpec: this.chainSpec,
|
|
63
163
|
workerParams: Encoder.encodeObject(paramsCodec, this.workerParams, this.chainSpec).raw,
|
|
64
164
|
dbPath: this.dbPath,
|
|
65
165
|
workerPorts: Array.from(this.ports.entries()).map(([name, port]) => [name, port.intoTransferable()]),
|
|
166
|
+
cacheSizeBytes: this.cacheSizeBytes,
|
|
66
167
|
};
|
|
67
168
|
}
|
|
68
169
|
}
|
|
170
|
+
async function decodeTransferableConfig(decodeParams, config) {
|
|
171
|
+
const blake2b = await Blake2b.createHasher();
|
|
172
|
+
const chainSpec = ChainSpec.new(config.chainSpec);
|
|
173
|
+
const workerParams = Decoder.decodeObject(decodeParams, config.workerParams, chainSpec);
|
|
174
|
+
const ports = new Map(config.workerPorts.map(([name, port]) => [name, ThreadPort.fromTransferable(chainSpec, port)]));
|
|
175
|
+
return {
|
|
176
|
+
blake2b,
|
|
177
|
+
chainSpec,
|
|
178
|
+
workerParams,
|
|
179
|
+
ports,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/** Restore a persistent worker config from its transferable form. */
|
|
183
|
+
export async function persistentConfigFromTransferable(decodeParams, config) {
|
|
184
|
+
switch (config.databaseBackend) {
|
|
185
|
+
case "lmdb":
|
|
186
|
+
return LmdbWorkerConfig.fromTransferable(decodeParams, config);
|
|
187
|
+
case "fjall":
|
|
188
|
+
return FjallWorkerConfig.fromTransferable(decodeParams, config);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
69
191
|
/**
|
|
70
192
|
* Collect the transferable objects (communication ports) embedded in a config.
|
|
71
193
|
*
|
|
@@ -99,7 +221,7 @@ export class InMemWorkerConfig {
|
|
|
99
221
|
this.blocks = InMemoryBlocks.new();
|
|
100
222
|
this.states = InMemorySerializedStates.withHasher({ chainSpec, blake2b });
|
|
101
223
|
}
|
|
102
|
-
openDatabase(_options = { readonly: true }) {
|
|
224
|
+
async openDatabase(_options = { readonly: true }) {
|
|
103
225
|
// opening/closing db doesn't do anything, we persist the state.
|
|
104
226
|
return {
|
|
105
227
|
getBlocksDb: () => this.blocks,
|
|
@@ -110,11 +232,14 @@ export class InMemWorkerConfig {
|
|
|
110
232
|
}
|
|
111
233
|
/**
|
|
112
234
|
* Hybrid worker config for the fuzz target: in-memory blocks and leaf sets,
|
|
113
|
-
* but large values persisted to
|
|
235
|
+
* but large values persisted to disk. The `backend` picks where the values go
|
|
236
|
+
* (lmdb or fjall).
|
|
237
|
+
*
|
|
238
|
+
* fjall opens its keyspace asynchronously, that is why `new` here is async.
|
|
114
239
|
*
|
|
115
240
|
* Like `InMemWorkerConfig`, the blocks and leaf sets are shared across the
|
|
116
241
|
* open/close/reopen dance that genesis init performs, so `openDatabase`
|
|
117
|
-
* returns the same instances and a no-op close. The
|
|
242
|
+
* returns the same instances and a no-op close. The values store is opened once
|
|
118
243
|
* here and closed by `HybridSerializedStates.close()` at importer teardown.
|
|
119
244
|
*
|
|
120
245
|
* In-process only: it holds shared mutable state (the in-memory leaf
|
|
@@ -129,12 +254,19 @@ export class HybridWorkerConfig {
|
|
|
129
254
|
dbPath;
|
|
130
255
|
ephemeral;
|
|
131
256
|
compression;
|
|
132
|
-
|
|
133
|
-
|
|
257
|
+
states;
|
|
258
|
+
static async new({ nodeName, chainSpec, workerParams, blake2b, dbPath, ephemeral = false, compression = true, backend = "lmdb", sharedFjallSession, }) {
|
|
259
|
+
// The values store is created once here and shared across reopen. When a
|
|
260
|
+
// session is given (fuzz reset reuse) we wrap it instead of opening a new one.
|
|
261
|
+
const states = backend === "fjall"
|
|
262
|
+
? sharedFjallSession !== undefined
|
|
263
|
+
? FjallHybridSerializedStates.fromSession(chainSpec, blake2b, sharedFjallSession)
|
|
264
|
+
: await FjallHybridSerializedStates.new({ spec: chainSpec, blake2b, dbPath, ephemeral })
|
|
265
|
+
: LmdbHybridSerializedStates.new({ spec: chainSpec, blake2b, dbPath, ephemeral, compression, readOnly: false });
|
|
266
|
+
return new HybridWorkerConfig(nodeName, chainSpec, workerParams, blake2b, dbPath, ephemeral, compression, states);
|
|
134
267
|
}
|
|
135
268
|
blocks;
|
|
136
|
-
states
|
|
137
|
-
constructor(nodeName, chainSpec, workerParams, blake2b, dbPath, ephemeral, compression = true) {
|
|
269
|
+
constructor(nodeName, chainSpec, workerParams, blake2b, dbPath, ephemeral, compression, states) {
|
|
138
270
|
this.nodeName = nodeName;
|
|
139
271
|
this.chainSpec = chainSpec;
|
|
140
272
|
this.workerParams = workerParams;
|
|
@@ -142,22 +274,15 @@ export class HybridWorkerConfig {
|
|
|
142
274
|
this.dbPath = dbPath;
|
|
143
275
|
this.ephemeral = ephemeral;
|
|
144
276
|
this.compression = compression;
|
|
277
|
+
this.states = states;
|
|
145
278
|
this.blocks = InMemoryBlocks.new();
|
|
146
|
-
this.states = HybridSerializedStates.new({
|
|
147
|
-
spec: this.chainSpec,
|
|
148
|
-
blake2b: this.blake2b,
|
|
149
|
-
dbPath: this.dbPath,
|
|
150
|
-
ephemeral: this.ephemeral,
|
|
151
|
-
compression: this.compression,
|
|
152
|
-
readOnly: false,
|
|
153
|
-
});
|
|
154
279
|
}
|
|
155
|
-
openDatabase(_options = { readonly: true }) {
|
|
280
|
+
async openDatabase(_options = { readonly: true }) {
|
|
156
281
|
return {
|
|
157
282
|
getBlocksDb: () => this.blocks,
|
|
158
283
|
getStatesDb: () => this.states,
|
|
159
|
-
// Leaf sets and blocks live in memory; the
|
|
160
|
-
//
|
|
284
|
+
// Leaf sets and blocks live in memory; the values store is closed via
|
|
285
|
+
// states.close() at importer teardown, so this is a no-op.
|
|
161
286
|
close: async () => { },
|
|
162
287
|
};
|
|
163
288
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
|
+
import * as fs from "node:fs";
|
|
2
3
|
import { describe, it } from "node:test";
|
|
3
4
|
import { MessageChannel } from "node:worker_threads";
|
|
5
|
+
import { Bytes } from "#@typeberry/bytes";
|
|
4
6
|
import { codec } from "#@typeberry/codec";
|
|
5
7
|
import { tinyChainSpec } from "#@typeberry/config";
|
|
6
|
-
import { Blake2b } from "#@typeberry/hash";
|
|
8
|
+
import { Blake2b, HASH_SIZE } from "#@typeberry/hash";
|
|
7
9
|
import { tryAsU32 } from "#@typeberry/numbers";
|
|
8
|
-
import { configTransferList, LmdbWorkerConfig } from "./config.js";
|
|
10
|
+
import { configTransferList, FjallWorkerConfig, HybridWorkerConfig, LmdbWorkerConfig } from "./config.js";
|
|
9
11
|
import { ThreadPort } from "./port.js";
|
|
10
12
|
const spec = tinyChainSpec;
|
|
11
13
|
describe("LmdbWorkerConfig transfer list", () => {
|
|
@@ -39,3 +41,87 @@ describe("LmdbWorkerConfig transfer list", () => {
|
|
|
39
41
|
}
|
|
40
42
|
});
|
|
41
43
|
});
|
|
44
|
+
describe("FjallWorkerConfig transfer list", () => {
|
|
45
|
+
it("surfaces embedded worker ports and marks the backend", async () => {
|
|
46
|
+
const blake2b = await Blake2b.createHasher();
|
|
47
|
+
const [portA, portB] = ThreadPort.pair(spec);
|
|
48
|
+
const config = FjallWorkerConfig.new({
|
|
49
|
+
nodeName: "node",
|
|
50
|
+
chainSpec: spec,
|
|
51
|
+
workerParams: tryAsU32(7),
|
|
52
|
+
dbPath: "db",
|
|
53
|
+
blake2b,
|
|
54
|
+
ports: new Map([["authorship-network", portA]]),
|
|
55
|
+
});
|
|
56
|
+
try {
|
|
57
|
+
const transferable = config.intoTransferable(codec.varU32);
|
|
58
|
+
assert.strictEqual(transferable.databaseBackend, "fjall");
|
|
59
|
+
assert.strictEqual(configTransferList(transferable).length, 1);
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
portA.close();
|
|
63
|
+
portB.close();
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
it("opens writable and read-only handles over one shared fjall path", async () => {
|
|
67
|
+
const blake2b = await Blake2b.createHasher();
|
|
68
|
+
const dbPath = fs.mkdtempSync("typeberry-fjall-worker-");
|
|
69
|
+
const config = FjallWorkerConfig.new({
|
|
70
|
+
nodeName: "node",
|
|
71
|
+
chainSpec: spec,
|
|
72
|
+
workerParams: undefined,
|
|
73
|
+
dbPath,
|
|
74
|
+
blake2b,
|
|
75
|
+
});
|
|
76
|
+
let writer = null;
|
|
77
|
+
let reader = null;
|
|
78
|
+
try {
|
|
79
|
+
writer = await config.openDatabase({ readonly: false });
|
|
80
|
+
reader = await config.openDatabase({ readonly: true });
|
|
81
|
+
const best = Bytes.fill(HASH_SIZE, 9).asOpaque();
|
|
82
|
+
await writer.getBlocksDb().setBestHeaderHash(best);
|
|
83
|
+
assert.strictEqual(reader.getBlocksDb().getBestHeaderHash().toString(), best.toString());
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
await reader?.close();
|
|
87
|
+
await writer?.close();
|
|
88
|
+
fs.rmSync(dbPath, { recursive: true, force: true });
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
describe("HybridWorkerConfig", () => {
|
|
93
|
+
// Both persistent backends must construct asynchronously and hand out a
|
|
94
|
+
// working db. fjall is the experimental backend we want to benchmark.
|
|
95
|
+
for (const backend of ["lmdb", "fjall"]) {
|
|
96
|
+
it(`constructs and opens a ${backend}-backed hybrid db`, async () => {
|
|
97
|
+
const blake2b = await Blake2b.createHasher();
|
|
98
|
+
const dbPath = fs.mkdtempSync(`typeberry-hybrid-${backend}-`);
|
|
99
|
+
try {
|
|
100
|
+
const config = await HybridWorkerConfig.new({
|
|
101
|
+
nodeName: "node",
|
|
102
|
+
chainSpec: spec,
|
|
103
|
+
workerParams: undefined,
|
|
104
|
+
blake2b,
|
|
105
|
+
dbPath,
|
|
106
|
+
ephemeral: true,
|
|
107
|
+
backend,
|
|
108
|
+
});
|
|
109
|
+
const db = await config.openDatabase({ readonly: false });
|
|
110
|
+
const states = db.getStatesDb();
|
|
111
|
+
try {
|
|
112
|
+
assert.notStrictEqual(db.getBlocksDb(), undefined);
|
|
113
|
+
assert.notStrictEqual(states, undefined);
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
// The values store owns the on-disk resources (the no-op db.close()
|
|
117
|
+
// does not), so close it explicitly to release the fjall keyspace.
|
|
118
|
+
await states.close();
|
|
119
|
+
await db.close();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
fs.rmSync(dbPath, { recursive: true, force: true });
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
});
|
|
@@ -18,6 +18,7 @@ export declare class ThreadPort implements Port {
|
|
|
18
18
|
static pair(spec: ChainSpec): [ThreadPort, ThreadPort];
|
|
19
19
|
readonly threadId: number;
|
|
20
20
|
private readonly events;
|
|
21
|
+
private readonly pendingMessages;
|
|
21
22
|
static new(spec: ChainSpec, port: MessagePort): ThreadPort;
|
|
22
23
|
private constructor();
|
|
23
24
|
static fromTransferable(spec: ChainSpec, { port }: TransferablePort): ThreadPort;
|
|
@@ -28,5 +29,7 @@ export declare class ThreadPort implements Port {
|
|
|
28
29
|
on<T>(event: string, codec: Codec<T>, callback: (msg: Envelope<T>) => void): () => void;
|
|
29
30
|
once<T>(event: string, codec: Codec<T>, callback: (msg: Envelope<T>) => void): () => void;
|
|
30
31
|
postMessage<T>(event: string, codec: Codec<T>, msg: Envelope<T>): void;
|
|
32
|
+
private queuePending;
|
|
33
|
+
private flushPending;
|
|
31
34
|
}
|
|
32
35
|
//# sourceMappingURL=port.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"port.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/api-node/port.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,WAAW,EAA+B,MAAM,qBAAqB,CAAC;AACpF,OAAO,EAAE,KAAK,KAAK,EAAoB,MAAM,kBAAkB,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"port.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/api-node/port.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,WAAW,EAA+B,MAAM,qBAAqB,CAAC;AACpF,OAAO,EAAE,KAAK,KAAK,EAAoB,MAAM,kBAAkB,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AAErE,MAAM,MAAM,OAAO,GAAG;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,UAAU,CAAC;CAClB,CAAC;AAIF,qDAAqD;AACrD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,WAAW,CAAC;CACnB,CAAC;AACF,qBAAa,UAAW,YAAW,IAAI;IAgBnC,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAhBvB,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,GAAG,CAAC,UAAU,EAAE,UAAU,CAAC;IAMtD,SAAgB,QAAQ,SAAY;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAC7C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgC;IAEhE,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW;IAI7C,OAAO;IAmBP,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,EAAE,gBAAgB;IAInE,gBAAgB,IAAI,gBAAgB;IAIpC,KAAK,IAAI,IAAI;IAKb,OAAO,CAAC,cAAc;IAkBtB,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAI3C,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI;IAUvF,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI;IAoBzF,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI;IAYtE,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,YAAY;CAUrB"}
|
|
@@ -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 @@ import { type Opaque } from "#@typeberry/utils";
|
|
|
18
18
|
*
|
|
19
19
|
*/
|
|
20
20
|
export type BlockSealInput = Opaque<BytesBlob, "Seal">;
|
|
21
|
-
/** Construction arguments for
|
|
21
|
+
/** Construction arguments for `BlockGenerator`. */
|
|
22
22
|
export type GeneratorArgs = {
|
|
23
23
|
chainSpec: ChainSpec;
|
|
24
24
|
bandersnatch: BandernsatchWasm;
|
|
@@ -27,7 +27,7 @@ export type GeneratorArgs = {
|
|
|
27
27
|
blocks: BlocksDb;
|
|
28
28
|
states: StatesDb;
|
|
29
29
|
};
|
|
30
|
-
export declare class
|
|
30
|
+
export declare class BlockGenerator {
|
|
31
31
|
private readonly metrics;
|
|
32
32
|
readonly chainSpec: ChainSpec;
|
|
33
33
|
readonly bandersnatch: BandernsatchWasm;
|
|
@@ -35,8 +35,8 @@ export declare class Generator {
|
|
|
35
35
|
readonly blake2b: Blake2b;
|
|
36
36
|
private readonly blocks;
|
|
37
37
|
private readonly states;
|
|
38
|
-
/** Build a
|
|
39
|
-
static new(args: GeneratorArgs):
|
|
38
|
+
/** Build a block generator from its collaborators. */
|
|
39
|
+
static new(args: GeneratorArgs): BlockGenerator;
|
|
40
40
|
private constructor();
|
|
41
41
|
private getLastHeaderAndState;
|
|
42
42
|
nextBlockView(validatorIndex: ValidatorIndex, bandersnatchSecret: BandersnatchSecretSeed, sealPayload: BlockSealInput, timeSlot: TimeSlot, pendingTickets?: {
|
|
@@ -71,4 +71,4 @@ export declare class Generator {
|
|
|
71
71
|
id: EntropyHash;
|
|
72
72
|
}[]): Promise<Block>;
|
|
73
73
|
}
|
|
74
|
-
//# sourceMappingURL=generator.d.ts.map
|
|
74
|
+
//# sourceMappingURL=block-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block-generator.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/block-authorship/block-generator.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,KAAK,WAAW,EAIhB,KAAK,QAAQ,EACb,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,SAAS,EAAa,MAAM,2BAA2B,CAAC;AAEtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAS,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAoC,KAAK,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAClG,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAIvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAGhF,OAAO,EAAqB,KAAK,MAAM,EAAU,MAAM,kBAAkB,CAAC;AAM1E;;;;;;;;GAQG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AAEvD,mDAAmD;AACnD,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,gBAAgB,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC,YAAY,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,QAAQ,CAAC;IACjB,MAAM,EAAE,QAAQ,CAAC;CAClB,CAAC;AAEF,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2C;IAEnE,SAAgB,SAAS,EAAE,SAAS,CAAC;IACrC,SAAgB,YAAY,EAAE,gBAAgB,CAAC;IAC/C,SAAgB,YAAY,EAAE,MAAM,CAAC,YAAY,CAAC;IAClD,SAAgB,OAAO,EAAE,OAAO,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAW;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAW;IAElC,sDAAsD;IACtD,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,aAAa;IAI9B,OAAO;IAUP,OAAO,CAAC,qBAAqB;IAYvB,aAAa,CACjB,cAAc,EAAE,cAAc,EAC9B,kBAAkB,EAAE,sBAAsB,EAC1C,WAAW,EAAE,cAAc,EAC3B,QAAQ,EAAE,QAAQ,EAClB,cAAc,GAAE;QAAE,MAAM,EAAE,YAAY,CAAC;QAAC,EAAE,EAAE,WAAW,CAAA;KAAE,EAAO,GAC/D,OAAO,CAAC,SAAS,CAAC;IAKrB;;;;;;;;;OASG;YACW,cAAc;IAiB5B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,uBAAuB;IA4BzB,SAAS,CACb,cAAc,EAAE,cAAc,EAC9B,kBAAkB,EAAE,sBAAsB,EAC1C,WAAW,EAAE,cAAc,EAC3B,QAAQ,EAAE,QAAQ,EAClB,cAAc,GAAE;QAAE,MAAM,EAAE,YAAY,CAAC;QAAC,EAAE,EAAE,WAAW,CAAA;KAAE,EAAO;CAqGnE"}
|
|
@@ -13,7 +13,7 @@ import { asOpaqueType, now, Result } from "#@typeberry/utils";
|
|
|
13
13
|
import * as metrics from "./metrics.js";
|
|
14
14
|
const EMPTY_AUX_DATA = BytesBlob.empty();
|
|
15
15
|
const logger = Logger.new(import.meta.filename, "author");
|
|
16
|
-
export class
|
|
16
|
+
export class BlockGenerator {
|
|
17
17
|
metrics;
|
|
18
18
|
chainSpec;
|
|
19
19
|
bandersnatch;
|
|
@@ -21,9 +21,9 @@ export class Generator {
|
|
|
21
21
|
blake2b;
|
|
22
22
|
blocks;
|
|
23
23
|
states;
|
|
24
|
-
/** Build a
|
|
24
|
+
/** Build a block generator from its collaborators. */
|
|
25
25
|
static new(args) {
|
|
26
|
-
return new
|
|
26
|
+
return new BlockGenerator(args);
|
|
27
27
|
}
|
|
28
28
|
constructor(args) {
|
|
29
29
|
this.chainSpec = args.chainSpec;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block-generator.test.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/block-authorship/block-generator.test.ts"],"names":[],"mappings":""}
|