@typeberry/lib 0.8.4-faebc7a → 0.9.0-1c3f157
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/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 +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 +31 -1
- 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/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.js +1 -1
- 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/jam/safrole/bandersnatch-vrf.d.ts +22 -2
- package/packages/jam/safrole/bandersnatch-vrf.d.ts.map +1 -1
- package/packages/jam/safrole/bandersnatch-vrf.js +54 -20
- package/packages/jam/safrole/bandersnatch-vrf.test.js +3 -2
- 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/ticket-pool/ticket-validator.d.ts +5 -4
- package/packages/jam/ticket-pool/ticket-validator.d.ts.map +1 -1
- package/packages/jam/ticket-pool/ticket-validator.js +8 -3
- package/packages/jam/ticket-pool/ticket-validator.test.js +5 -4
- package/packages/jam/ticket-pool/verified-ticket-pool.d.ts +2 -0
- package/packages/jam/ticket-pool/verified-ticket-pool.d.ts.map +1 -1
- package/packages/jam/ticket-pool/verified-ticket-pool.js +4 -0
- package/packages/jam/ticket-pool/verified-ticket-pool.test.js +5 -5
- 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/{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 +194 -262
- 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 +7 -8
- package/packages/workers/block-authorship/ticket-validator.d.ts.map +1 -1
- package/packages/workers/block-authorship/ticket-validator.js +26 -23
- package/packages/workers/comms-authorship-network/protocol.d.ts +4 -4
- package/packages/workers/comms-authorship-network/protocol.d.ts.map +1 -1
- package/packages/workers/comms-authorship-network/protocol.js +4 -5
- 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/finality.d.ts +2 -0
- package/packages/workers/importer/finality.d.ts.map +1 -1
- package/packages/workers/importer/finality.js +8 -1
- 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 +6 -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 +9 -4
- 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,6 +1,7 @@
|
|
|
1
|
+
import { type FjallValuesSession } from "#@typeberry/workers-api-node";
|
|
1
2
|
import type { JamConfig } from "./jam-config.js";
|
|
2
3
|
import type { NodeApi } from "./main.js";
|
|
3
|
-
export type StateBackend = "lmdb" | "lmdb-hybrid" | "fjall-hybrid";
|
|
4
|
+
export type StateBackend = "lmdb" | "fjall" | "lmdb-hybrid" | "fjall-hybrid";
|
|
4
5
|
export type ImporterOptions = {
|
|
5
6
|
initGenesisFromAncestry?: boolean;
|
|
6
7
|
dummyFinalityDepth?: number;
|
|
@@ -8,9 +9,17 @@ export type ImporterOptions = {
|
|
|
8
9
|
/** Open the database without fsync/compression. Only safe for throwaway dbs (e.g. fuzzing). */
|
|
9
10
|
ephemeral?: boolean;
|
|
10
11
|
/**
|
|
11
|
-
* Persistent backend
|
|
12
|
+
* Persistent backend used when `databaseBasePath` is set. Defaults to config's backend (fjall unless overridden).
|
|
13
|
+
*
|
|
14
|
+
* lmdb and lmdb-hybrid are deprecated and retained as explicit fallbacks.
|
|
12
15
|
*/
|
|
13
16
|
stateBackend?: StateBackend;
|
|
17
|
+
/**
|
|
18
|
+
* Reuse an already-open fjall values session instead of opening a fresh
|
|
19
|
+
* keyspace. Only used when `stateBackend === "fjall-hybrid"`. The fuzz target
|
|
20
|
+
* opens one per run and reuses it across resets.
|
|
21
|
+
*/
|
|
22
|
+
sharedFjallSession?: FjallValuesSession;
|
|
14
23
|
};
|
|
15
24
|
export declare function mainImporter(config: JamConfig, withRelPath: (v: string) => string, options?: ImporterOptions): Promise<NodeApi>;
|
|
16
25
|
//# sourceMappingURL=main-importer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main-importer.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/main-importer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"main-importer.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/main-importer.ts"],"names":[],"mappings":"AASA,OAAO,EACL,KAAK,kBAAkB,EAKxB,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,aAAa,GAAG,cAAc,CAAC;AAE7E,MAAM,MAAM,eAAe,GAAG;IAC5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+FAA+F;IAC/F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC,CAAC;AAEF,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAClC,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,OAAO,CAAC,CAqHlB"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Bytes } from "#@typeberry/bytes";
|
|
2
2
|
import { PvmBackend } from "#@typeberry/config";
|
|
3
|
-
import { KnownChainSpec } from "#@typeberry/config-node";
|
|
3
|
+
import { KnownChainSpec, RegularStateBackend } from "#@typeberry/config-node";
|
|
4
4
|
import { bandersnatch, initWasm } from "#@typeberry/crypto";
|
|
5
5
|
import { Blake2b, HASH_SIZE } from "#@typeberry/hash";
|
|
6
6
|
import { createImporter, ImporterConfig } from "#@typeberry/importer";
|
|
7
7
|
import { tryAsU16 } from "#@typeberry/numbers";
|
|
8
8
|
import { CURRENT_SUITE, CURRENT_VERSION, Result, resultToString, version } from "#@typeberry/utils";
|
|
9
|
-
import { HybridWorkerConfig, InMemWorkerConfig, LmdbWorkerConfig } from "#@typeberry/workers-api-node";
|
|
9
|
+
import { FjallWorkerConfig, HybridWorkerConfig, InMemWorkerConfig, LmdbWorkerConfig, } from "#@typeberry/workers-api-node";
|
|
10
10
|
import { getChainSpec, getDatabasePath, initializeDatabase, logger } from "./common.js";
|
|
11
11
|
const zeroHash = Bytes.zero(HASH_SIZE).asOpaque();
|
|
12
12
|
export async function mainImporter(config, withRelPath, options = {}) {
|
|
@@ -18,8 +18,13 @@ export async function mainImporter(config, withRelPath, options = {}) {
|
|
|
18
18
|
logger.info `🐇 Bandersnatch ${bandesnatchNative.isOk ? "native 🚀" : `using wasm: ${bandesnatchNative.error}`}`;
|
|
19
19
|
// Single source of truth for the states db backend: drives both the log line
|
|
20
20
|
// below and the worker config picked further down.
|
|
21
|
-
const dbBackend = config.node.databaseBasePath === undefined
|
|
21
|
+
const dbBackend = config.node.databaseBasePath === undefined
|
|
22
|
+
? "in-memory"
|
|
23
|
+
: (options.stateBackend ?? config.node.stateBackend ?? RegularStateBackend.Fjall);
|
|
22
24
|
logger.info `🗄️ States DB: ${dbBackend}.`;
|
|
25
|
+
if (dbBackend === "lmdb" || dbBackend === "lmdb-hybrid") {
|
|
26
|
+
logger.warn `🗄️ The ${dbBackend} state backend is deprecated. Use fjall unless you need a temporary fallback.`;
|
|
27
|
+
}
|
|
23
28
|
const chainSpec = getChainSpec(config.node.flavor);
|
|
24
29
|
const blake2b = await Blake2b.createHasher();
|
|
25
30
|
const nodeName = config.nodeName;
|
|
@@ -49,18 +54,28 @@ export async function mainImporter(config, withRelPath, options = {}) {
|
|
|
49
54
|
ephemeral,
|
|
50
55
|
compression,
|
|
51
56
|
backend: dbBackend === "lmdb-hybrid" ? "lmdb" : "fjall",
|
|
57
|
+
sharedFjallSession: options.sharedFjallSession,
|
|
52
58
|
})
|
|
53
|
-
:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
: dbBackend === "fjall"
|
|
60
|
+
? FjallWorkerConfig.new({
|
|
61
|
+
nodeName,
|
|
62
|
+
chainSpec,
|
|
63
|
+
blake2b,
|
|
64
|
+
dbPath,
|
|
65
|
+
workerParams,
|
|
66
|
+
ephemeral,
|
|
67
|
+
})
|
|
68
|
+
: LmdbWorkerConfig.new({
|
|
69
|
+
nodeName,
|
|
70
|
+
chainSpec,
|
|
71
|
+
blake2b,
|
|
72
|
+
dbPath,
|
|
73
|
+
workerParams,
|
|
74
|
+
ephemeral,
|
|
75
|
+
});
|
|
61
76
|
// Initialize the database with genesis state and block if there isn't one.
|
|
62
77
|
logger.info `🛢️ Opening database at ${dbPath}`;
|
|
63
|
-
const rootDb = workerConfig.openDatabase({ readonly: false });
|
|
78
|
+
const rootDb = await workerConfig.openDatabase({ readonly: false });
|
|
64
79
|
await initializeDatabase(chainSpec, blake2b, genesisHeaderHash, rootDb, config.node.chainSpec, config.ancestry, {
|
|
65
80
|
initGenesisFromAncestry: options.initGenesisFromAncestry,
|
|
66
81
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/main.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAc,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEzF,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/main.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAc,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEzF,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,mBAAmB,CAAC;AAgB/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAkC,MAAM,EAAW,MAAM,kBAAkB,CAAC;AAYnF,OAAO,KAAK,EAAE,SAAS,EAAiB,MAAM,iBAAiB,CAAC;AAWhE,MAAM,MAAM,OAAO,GAAG;IACpB,SAAS,EAAE,SAAS,CAAC;IACrB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAChE,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC;IACtE,oBAAoB,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;IAC/C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;AAEF,wBAAsB,IAAI,CACxB,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAClC,SAAS,EAAE,SAAS,GAAG,IAAI,GAC1B,OAAO,CAAC,OAAO,CAAC,CA2LlB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isMainThread } from "node:worker_threads";
|
|
2
2
|
import { AUTHORSHIP_NETWORK_PORT } from "#@typeberry/comms-authorship-network";
|
|
3
3
|
import { PvmBackend } from "#@typeberry/config";
|
|
4
|
+
import { RegularStateBackend } from "#@typeberry/config-node";
|
|
4
5
|
import { initWasm } from "#@typeberry/crypto";
|
|
5
6
|
import { deriveBandersnatchSecretKey, deriveEd25519SecretKey, trivialSeed, } from "#@typeberry/crypto/key-derivation.js";
|
|
6
7
|
import { Blake2b } from "#@typeberry/hash";
|
|
@@ -10,7 +11,7 @@ import { Listener } from "#@typeberry/listener";
|
|
|
10
11
|
import { tryAsU16, tryAsU32 } from "#@typeberry/numbers";
|
|
11
12
|
import { CURRENT_SUITE, CURRENT_VERSION, Result, version } from "#@typeberry/utils";
|
|
12
13
|
import { DirectPort, DirectWorkerConfig } from "#@typeberry/workers-api";
|
|
13
|
-
import { InMemWorkerConfig, LmdbWorkerConfig, logHostEnvironment, ThreadPort } from "#@typeberry/workers-api-node";
|
|
14
|
+
import { FjallWorkerConfig, InMemWorkerConfig, LmdbWorkerConfig, logHostEnvironment, ThreadPort, } from "#@typeberry/workers-api-node";
|
|
14
15
|
import { getChainSpec, getDatabasePath, initializeDatabase, logger } from "./common.js";
|
|
15
16
|
import { initializeExtensions } from "./extensions.js";
|
|
16
17
|
import * as metrics from "./metrics.js";
|
|
@@ -29,9 +30,12 @@ export async function main(config, withRelPath, telemetry) {
|
|
|
29
30
|
const blake2b = await Blake2b.createHasher();
|
|
30
31
|
const nodeName = config.nodeName;
|
|
31
32
|
const isInMemory = config.node.databaseBasePath === undefined;
|
|
32
|
-
logger.info `🗄️ States DB: ${isInMemory ? "in-memory" :
|
|
33
|
+
logger.info `🗄️ States DB: ${isInMemory ? "in-memory" : config.node.stateBackend}.`;
|
|
34
|
+
if (!isInMemory && config.node.stateBackend === RegularStateBackend.Lmdb) {
|
|
35
|
+
logger.warn `🗄️ The lmdb state backend is deprecated. Use state_backend="fjall" unless you need a temporary fallback.`;
|
|
36
|
+
}
|
|
33
37
|
const { dbPath, genesisHeaderHash } = getDatabasePath(blake2b, nodeName, config.node.chainSpec.genesisHeader, withRelPath(config.node.databaseBasePath ?? "<in-memory>"));
|
|
34
|
-
const baseConfig = { nodeName, chainSpec, blake2b, dbPath };
|
|
38
|
+
const baseConfig = { nodeName, chainSpec, blake2b, dbPath, stateBackend: config.node.stateBackend };
|
|
35
39
|
const importerParams = {
|
|
36
40
|
...baseConfig,
|
|
37
41
|
workerParams: ImporterConfig.create({
|
|
@@ -42,16 +46,29 @@ export async function main(config, withRelPath, telemetry) {
|
|
|
42
46
|
};
|
|
43
47
|
const importerConfig = isInMemory
|
|
44
48
|
? { isInMemory, config: InMemWorkerConfig.new(importerParams) }
|
|
45
|
-
: { isInMemory, config:
|
|
49
|
+
: { isInMemory, config: createPersistentWorkerConfig(importerParams) };
|
|
46
50
|
// Initialize the database with genesis state and block if there isn't one.
|
|
47
51
|
logger.info `🛢️ Opening database at ${dbPath}`;
|
|
48
|
-
const rootDb = importerConfig.config.openDatabase({ readonly: false });
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
const rootDb = await importerConfig.config.openDatabase({ readonly: false });
|
|
53
|
+
try {
|
|
54
|
+
await initializeDatabase(chainSpec, blake2b, genesisHeaderHash, rootDb, config.node.chainSpec, config.ancestry);
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
try {
|
|
58
|
+
await rootDb.close();
|
|
59
|
+
}
|
|
60
|
+
catch (closeError) {
|
|
61
|
+
logger.warn `Failed to close database after initialization error: ${closeError}`;
|
|
62
|
+
}
|
|
63
|
+
throw e;
|
|
64
|
+
}
|
|
65
|
+
// fjall-js shares the engine explicitly and requires every handle to close.
|
|
66
|
+
// Keep lmdb's historical main-thread handle open until shutdown.
|
|
67
|
+
let mainRootDb = rootDb;
|
|
68
|
+
if (!importerConfig.isInMemory && config.node.stateBackend === RegularStateBackend.Fjall) {
|
|
69
|
+
await rootDb.close();
|
|
70
|
+
mainRootDb = null;
|
|
71
|
+
}
|
|
55
72
|
// Start block importer
|
|
56
73
|
let importer;
|
|
57
74
|
let closeImporter;
|
|
@@ -138,8 +155,10 @@ export async function main(config, withRelPath, telemetry) {
|
|
|
138
155
|
await closeImporter();
|
|
139
156
|
logger.log `[main] ☠️ Closing the extensions`;
|
|
140
157
|
closeExtensions();
|
|
141
|
-
|
|
142
|
-
|
|
158
|
+
if (mainRootDb !== null) {
|
|
159
|
+
logger.log `[main] 🛢️ Closing the database`;
|
|
160
|
+
await mainRootDb.close();
|
|
161
|
+
}
|
|
143
162
|
logger.log `[main] 📳 Closing telemetry`;
|
|
144
163
|
await telemetry?.close();
|
|
145
164
|
logger.info `[main] ✅ Done.`;
|
|
@@ -167,7 +186,7 @@ const initAuthorship = async (importer, isAuthoring, isFastForward, params, base
|
|
|
167
186
|
statesDb: params.rootDb.getStatesDb(),
|
|
168
187
|
workerParams,
|
|
169
188
|
}), params.networkingPort)
|
|
170
|
-
: await spawnBlockGeneratorWorker(
|
|
189
|
+
: await spawnBlockGeneratorWorker(createPersistentWorkerConfig({
|
|
171
190
|
...baseConfig,
|
|
172
191
|
workerParams,
|
|
173
192
|
ports: new Map([[AUTHORSHIP_NETWORK_PORT, params.networkingPort]]),
|
|
@@ -205,7 +224,7 @@ const initNetwork = async (importer, params, baseConfig, genesisHeaderHash, netw
|
|
|
205
224
|
statesDb: params.rootDb.getStatesDb(),
|
|
206
225
|
workerParams: networkingConfig,
|
|
207
226
|
}), params.authorshipPort)
|
|
208
|
-
: await spawnNetworkWorker(
|
|
227
|
+
: await spawnNetworkWorker(createPersistentWorkerConfig({
|
|
209
228
|
...baseConfig,
|
|
210
229
|
workerParams: networkingConfig,
|
|
211
230
|
ports: new Map([[AUTHORSHIP_NETWORK_PORT, params.authorshipPort]]),
|
|
@@ -222,3 +241,11 @@ const initNetwork = async (importer, params, baseConfig, genesisHeaderHash, netw
|
|
|
222
241
|
});
|
|
223
242
|
return { closeNetwork: finish, networkApi: network, networkWorker: worker };
|
|
224
243
|
};
|
|
244
|
+
function createPersistentWorkerConfig({ stateBackend, ...params }) {
|
|
245
|
+
switch (stateBackend) {
|
|
246
|
+
case RegularStateBackend.Fjall:
|
|
247
|
+
return FjallWorkerConfig.new(params);
|
|
248
|
+
case RegularStateBackend.Lmdb:
|
|
249
|
+
return LmdbWorkerConfig.new(params);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
@@ -5,8 +5,8 @@ import * as importer from "#@typeberry/importer";
|
|
|
5
5
|
import * as jamNetwork from "#@typeberry/jam-network";
|
|
6
6
|
import type { SerializedState } from "#@typeberry/state-merkleization";
|
|
7
7
|
import { type DirectPort, type DirectWorkerConfig } from "#@typeberry/workers-api";
|
|
8
|
-
import { type
|
|
9
|
-
export declare function spawnImporterWorker(config:
|
|
8
|
+
import { type PersistentWorkerConfig } from "#@typeberry/workers-api-node";
|
|
9
|
+
export declare function spawnImporterWorker(config: PersistentWorkerConfig<importer.ImporterConfig>): Promise<{
|
|
10
10
|
importer: import("@typeberry/workers-api").Tx<{
|
|
11
11
|
getStateEntries: {
|
|
12
12
|
request: import("@typeberry/codec").Descriptor<import("@typeberry/bytes").Bytes<32> & import("@typeberry/utils").WithOpaque<"HeaderHash">, import("@typeberry/bytes").Bytes<32>>;
|
|
@@ -376,7 +376,7 @@ export declare function spawnImporterWorker(config: LmdbWorkerConfig<importer.Im
|
|
|
376
376
|
finish: () => Promise<void>;
|
|
377
377
|
}>;
|
|
378
378
|
export declare function startImporterDirect(config: DirectWorkerConfig<importer.ImporterConfig, BlocksDb, StatesDb<SerializedState<LeafDb>>>): ReturnType<typeof spawnImporterWorker>;
|
|
379
|
-
export declare function spawnNetworkWorker(config:
|
|
379
|
+
export declare function spawnNetworkWorker(config: PersistentWorkerConfig<jamNetwork.NetworkingConfig>): Promise<{
|
|
380
380
|
network: import("@typeberry/workers-api").Tx<{
|
|
381
381
|
newHeader: {
|
|
382
382
|
request: import("@typeberry/codec").Descriptor<import("@typeberry/hash").WithHash<import("@typeberry/hash").OpaqueHash & import("@typeberry/utils").WithOpaque<"HeaderHash">, import("@typeberry/codec").ViewOf<import("@typeberry/block").Header & import("@typeberry/codec").CodecRecord<import("@typeberry/block").Header>, {
|
|
@@ -865,7 +865,7 @@ export declare function spawnNetworkWorker(config: LmdbWorkerConfig<jamNetwork.N
|
|
|
865
865
|
export declare function startNetwork(config: DirectWorkerConfig<jamNetwork.NetworkingConfig>, authorshipPort: DirectPort): Promise<Omit<Awaited<ReturnType<typeof spawnNetworkWorker>>, "worker"> & {
|
|
866
866
|
worker: Worker | null;
|
|
867
867
|
}>;
|
|
868
|
-
export declare function spawnBlockGeneratorWorker(config:
|
|
868
|
+
export declare function spawnBlockGeneratorWorker(config: PersistentWorkerConfig<blockAuthorship.BlockAuthorshipConfig>): Promise<{
|
|
869
869
|
generator: import("@typeberry/workers-api").Tx<{
|
|
870
870
|
finish: {
|
|
871
871
|
request: import("@typeberry/codec").Descriptor<void, void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workers.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/workers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,eAAe,MAAM,6BAA6B,CAAC;AAE/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,QAAQ,MAAM,qBAAqB,CAAC;AAChD,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAW,KAAK,UAAU,EAAE,KAAK,kBAAkB,EAAmB,MAAM,wBAAwB,CAAC;AAC5G,OAAO,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"workers.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/workers.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,7 +27,27 @@ declare function generateSeal(bandersnatch: BandernsatchWasm, authorKey: Banders
|
|
|
27
27
|
export type VrfOutputHash = Opaque<OpaqueHash, "VRF Output Hash">;
|
|
28
28
|
declare function getVrfOutputHash(bandersnatch: BandernsatchWasm, authorKey: BandersnatchSecretSeed, input: BytesBlob): Promise<Result<VrfOutputHash, null>>;
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
30
|
+
* Batch-generate signed tickets for multiple validators in a single native call,
|
|
31
|
+
* reusing the ring prover setup across all of them. Returns one ticket list per
|
|
32
|
+
* validator, in the same order as `proverKeyIndices`/`secrets`.
|
|
31
33
|
*/
|
|
32
|
-
declare function generateTickets(bandersnatch: BandernsatchWasm, ringKeys: BandersnatchKey[],
|
|
34
|
+
declare function generateTickets(bandersnatch: BandernsatchWasm, ringKeys: BandersnatchKey[], proverKeyIndices: readonly number[], secrets: readonly BandersnatchSecretSeed[], entropy: EntropyHash, ticketsPerValidator: number): Promise<Result<SignedTicket[][], null>>;
|
|
35
|
+
/**
|
|
36
|
+
* Build the concatenated ring-VRF inputs for ticket generation: one
|
|
37
|
+
* `JAM_TICKET_SEAL || entropy || attempt_byte` input per attempt.
|
|
38
|
+
*
|
|
39
|
+
* Exposed so the worker-pool path can build the same inputs to hand off to a
|
|
40
|
+
* worker thread without re-deriving the layout.
|
|
41
|
+
*/
|
|
42
|
+
export declare function buildTicketVrfInputs(entropy: EntropyHash, ticketsPerValidator: number): {
|
|
43
|
+
inputsData: Uint8Array;
|
|
44
|
+
vrfInputDataLen: number;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Parse the raw output of `batchGenerateRingVrfForValidators` into per-validator
|
|
48
|
+
* ticket lists. Records are ordered validator-major, then attempt-major; each
|
|
49
|
+
* record is `status byte || signature`. A malformed batch yields a single error
|
|
50
|
+
* byte. Exposed so the worker-pool path can parse a worker's raw result.
|
|
51
|
+
*/
|
|
52
|
+
export declare function parseTicketsBatchOutput(result: Uint8Array, numValidators: number, ticketsPerValidator: number): Result<SignedTicket[][], null>;
|
|
33
53
|
//# sourceMappingURL=bandersnatch-vrf.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bandersnatch-vrf.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/safrole/bandersnatch-vrf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAsB,MAAM,6BAA6B,CAAC;AAC/E,OAAO,EAAS,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"bandersnatch-vrf.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/safrole/bandersnatch-vrf.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SignedTicket, tryAsTicketAttempt } from "#@typeberry/block/tickets.js";
|
|
2
2
|
import { Bytes, BytesBlob } from "#@typeberry/bytes";
|
|
3
|
+
import { SEED_SIZE } from "#@typeberry/crypto";
|
|
3
4
|
import { BANDERSNATCH_PROOF_BYTES, BANDERSNATCH_RING_ROOT_BYTES, BANDERSNATCH_VRF_SIGNATURE_BYTES, } from "#@typeberry/crypto/bandersnatch.js";
|
|
4
5
|
import { HASH_SIZE } from "#@typeberry/hash";
|
|
5
6
|
import { Result } from "#@typeberry/utils";
|
|
@@ -33,6 +34,10 @@ const ringCommitmentCache = [
|
|
|
33
34
|
keys: BytesBlob.empty(),
|
|
34
35
|
value: Promise.resolve(Result.error(null, () => "")),
|
|
35
36
|
},
|
|
37
|
+
{
|
|
38
|
+
keys: BytesBlob.empty(),
|
|
39
|
+
value: Promise.resolve(Result.error(null, () => "")),
|
|
40
|
+
},
|
|
36
41
|
];
|
|
37
42
|
const FUNCTIONS = {
|
|
38
43
|
verifySeal,
|
|
@@ -122,31 +127,60 @@ async function getVrfOutputHash(bandersnatch, authorKey, input) {
|
|
|
122
127
|
// One byte for result discriminator and the rest is the ring VRF signature.
|
|
123
128
|
const GENERATE_RESULT_ENTRY_LENGTH = 1 + BANDERSNATCH_PROOF_BYTES;
|
|
124
129
|
/**
|
|
125
|
-
*
|
|
130
|
+
* Batch-generate signed tickets for multiple validators in a single native call,
|
|
131
|
+
* reusing the ring prover setup across all of them. Returns one ticket list per
|
|
132
|
+
* validator, in the same order as `proverKeyIndices`/`secrets`.
|
|
126
133
|
*/
|
|
127
|
-
async function generateTickets(bandersnatch, ringKeys,
|
|
128
|
-
|
|
134
|
+
async function generateTickets(bandersnatch, ringKeys, proverKeyIndices, secrets, entropy, ticketsPerValidator) {
|
|
135
|
+
if (proverKeyIndices.length !== secrets.length) {
|
|
136
|
+
return Result.error(null, () => "proverKeyIndices and secrets must have the same length");
|
|
137
|
+
}
|
|
138
|
+
if (proverKeyIndices.length === 0) {
|
|
139
|
+
return Result.ok([]);
|
|
140
|
+
}
|
|
141
|
+
const { inputsData, vrfInputDataLen } = buildTicketVrfInputs(entropy, ticketsPerValidator);
|
|
142
|
+
const ringKeysData = BytesBlob.blobFromParts(ringKeys.map((k) => k.raw)).raw;
|
|
143
|
+
const secretSeedsData = BytesBlob.blobFromParts(secrets.map((s) => s.raw)).raw;
|
|
144
|
+
const result = await bandersnatch.batchGenerateRingVrfForValidators(ringKeysData, Uint32Array.from(proverKeyIndices), secretSeedsData, SEED_SIZE, inputsData, vrfInputDataLen);
|
|
145
|
+
return parseTicketsBatchOutput(result, proverKeyIndices.length, ticketsPerValidator);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Build the concatenated ring-VRF inputs for ticket generation: one
|
|
149
|
+
* `JAM_TICKET_SEAL || entropy || attempt_byte` input per attempt.
|
|
150
|
+
*
|
|
151
|
+
* Exposed so the worker-pool path can build the same inputs to hand off to a
|
|
152
|
+
* worker thread without re-deriving the layout.
|
|
153
|
+
*/
|
|
154
|
+
export function buildTicketVrfInputs(entropy, ticketsPerValidator) {
|
|
129
155
|
const vrfInputParts = [];
|
|
130
156
|
for (let attempt = 0; attempt < ticketsPerValidator; attempt++) {
|
|
131
157
|
vrfInputParts.push(BytesBlob.blobFromParts([JAM_TICKET_SEAL, entropy.raw, Uint8Array.of(attempt)]).raw);
|
|
132
158
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
159
|
+
return {
|
|
160
|
+
inputsData: BytesBlob.blobFromParts(vrfInputParts).raw,
|
|
161
|
+
vrfInputDataLen: JAM_TICKET_SEAL.length + entropy.length + 1,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Parse the raw output of `batchGenerateRingVrfForValidators` into per-validator
|
|
166
|
+
* ticket lists. Records are ordered validator-major, then attempt-major; each
|
|
167
|
+
* record is `status byte || signature`. A malformed batch yields a single error
|
|
168
|
+
* byte. Exposed so the worker-pool path can parse a worker's raw result.
|
|
169
|
+
*/
|
|
170
|
+
export function parseTicketsBatchOutput(result, numValidators, ticketsPerValidator) {
|
|
171
|
+
const perValidator = [];
|
|
172
|
+
let offset = 0;
|
|
173
|
+
for (let v = 0; v < numValidators; v++) {
|
|
174
|
+
const tickets = [];
|
|
175
|
+
for (let attempt = 0; attempt < ticketsPerValidator; attempt++) {
|
|
176
|
+
if (result[offset] === ResultValues.Error) {
|
|
177
|
+
return Result.error(null, () => `Ring VRF proof generation failed for validator ${v}, attempt ${attempt}`);
|
|
178
|
+
}
|
|
179
|
+
const signature = Bytes.fromBlob(result.subarray(offset + 1, offset + GENERATE_RESULT_ENTRY_LENGTH), BANDERSNATCH_PROOF_BYTES).asOpaque();
|
|
180
|
+
tickets.push(SignedTicket.create({ attempt: tryAsTicketAttempt(attempt), signature }));
|
|
181
|
+
offset += GENERATE_RESULT_ENTRY_LENGTH;
|
|
144
182
|
}
|
|
145
|
-
|
|
146
|
-
tickets.push(SignedTicket.create({
|
|
147
|
-
attempt: tryAsTicketAttempt(attempt),
|
|
148
|
-
signature,
|
|
149
|
-
}));
|
|
183
|
+
perValidator.push(tickets);
|
|
150
184
|
}
|
|
151
|
-
return Result.ok(
|
|
185
|
+
return Result.ok(perValidator);
|
|
152
186
|
}
|
|
@@ -165,11 +165,12 @@ describe("Bandersnatch verification", () => {
|
|
|
165
165
|
const ringKeys = secrets.map((secret) => deriveBandersnatchPublicKey(secret));
|
|
166
166
|
const proverIndex = 0;
|
|
167
167
|
const entropy = Bytes.fill(HASH_SIZE, 123).asOpaque();
|
|
168
|
-
const genResult = await bandersnatchVrf.generateTickets(await bandersnatchWasm, ringKeys, proverIndex, secrets[proverIndex], entropy, 2);
|
|
168
|
+
const genResult = await bandersnatchVrf.generateTickets(await bandersnatchWasm, ringKeys, [proverIndex], [secrets[proverIndex]], entropy, 2);
|
|
169
169
|
assert.ok(genResult.isOk);
|
|
170
170
|
const commitment = await bandersnatchVrf.getRingCommitment(await bandersnatchWasm, ringKeys);
|
|
171
171
|
assert.ok(commitment.isOk);
|
|
172
|
-
|
|
172
|
+
assert.strictEqual(genResult.ok.length, 1);
|
|
173
|
+
const verifyResult = await bandersnatchVrf.verifyTickets(await bandersnatchWasm, ringKeys.length, commitment.ok, genResult.ok[0], entropy);
|
|
173
174
|
assert.ok(verifyResult.isValid, "Generated tickets should pass verification");
|
|
174
175
|
});
|
|
175
176
|
});
|
|
@@ -8,5 +8,15 @@ export declare class BandernsatchWasm {
|
|
|
8
8
|
generateSeal(authorKey: Uint8Array, input: Uint8Array, auxData: Uint8Array): Promise<Uint8Array<ArrayBufferLike>>;
|
|
9
9
|
getVrfOutputHash(authorKey: Uint8Array, input: Uint8Array): Promise<Uint8Array<ArrayBufferLike>>;
|
|
10
10
|
batchGenerateRingVrf(ringKeys: Uint8Array, proverKeyIndex: number, secretSeed: Uint8Array, inputsData: Uint8Array, vrfInputDataLen: number): Promise<Uint8Array<ArrayBufferLike>>;
|
|
11
|
+
/**
|
|
12
|
+
* Batch-generate ring VRF tickets for multiple validators in a single call,
|
|
13
|
+
* reusing the ring prover setup across all of them.
|
|
14
|
+
*
|
|
15
|
+
* `secretSeedsData` is the fixed-width concatenation of the validators' secret
|
|
16
|
+
* seeds (each `secretSeedDataLen` bytes); `proverKeyIndices` are their indices
|
|
17
|
+
* within the ring and must have the same count. Output records are ordered
|
|
18
|
+
* validator-major then input-major, each `status byte || signature`.
|
|
19
|
+
*/
|
|
20
|
+
batchGenerateRingVrfForValidators(ringKeys: Uint8Array, proverKeyIndices: Uint32Array, secretSeedsData: Uint8Array, secretSeedDataLen: number, inputsData: Uint8Array, vrfInputDataLen: number): Promise<Uint8Array<ArrayBufferLike>>;
|
|
11
21
|
}
|
|
12
22
|
//# sourceMappingURL=bandersnatch-wasm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bandersnatch-wasm.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/safrole/bandersnatch-wasm.ts"],"names":[],"mappings":"AAEA,qBAAa,gBAAgB;IAC3B,OAAO;WAEM,GAAG;IAKV,UAAU,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU;IAIjG,iBAAiB,CACrB,SAAS,EAAE,UAAU,EACrB,UAAU,EAAE,UAAU,EACtB,iBAAiB,EAAE,UAAU,EAC7B,cAAc,EAAE,UAAU,EAC1B,WAAW,EAAE,UAAU,EACvB,oBAAoB,EAAE,UAAU;IAY5B,iBAAiB,CAAC,IAAI,EAAE,UAAU;IAIlC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM;IAI1G,YAAY,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU;IAI1E,gBAAgB,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU;IAIzD,oBAAoB,CACxB,QAAQ,EAAE,UAAU,EACpB,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,UAAU,EACtB,UAAU,EAAE,UAAU,EACtB,eAAe,EAAE,MAAM;
|
|
1
|
+
{"version":3,"file":"bandersnatch-wasm.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/safrole/bandersnatch-wasm.ts"],"names":[],"mappings":"AAEA,qBAAa,gBAAgB;IAC3B,OAAO;WAEM,GAAG;IAKV,UAAU,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU;IAIjG,iBAAiB,CACrB,SAAS,EAAE,UAAU,EACrB,UAAU,EAAE,UAAU,EACtB,iBAAiB,EAAE,UAAU,EAC7B,cAAc,EAAE,UAAU,EAC1B,WAAW,EAAE,UAAU,EACvB,oBAAoB,EAAE,UAAU;IAY5B,iBAAiB,CAAC,IAAI,EAAE,UAAU;IAIlC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM;IAI1G,YAAY,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU;IAI1E,gBAAgB,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU;IAIzD,oBAAoB,CACxB,QAAQ,EAAE,UAAU,EACpB,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,UAAU,EACtB,UAAU,EAAE,UAAU,EACtB,eAAe,EAAE,MAAM;IAKzB;;;;;;;;OAQG;IACG,iCAAiC,CACrC,QAAQ,EAAE,UAAU,EACpB,gBAAgB,EAAE,WAAW,EAC7B,eAAe,EAAE,UAAU,EAC3B,iBAAiB,EAAE,MAAM,EACzB,UAAU,EAAE,UAAU,EACtB,eAAe,EAAE,MAAM;CAW1B"}
|
|
@@ -26,4 +26,16 @@ export class BandernsatchWasm {
|
|
|
26
26
|
async batchGenerateRingVrf(ringKeys, proverKeyIndex, secretSeed, inputsData, vrfInputDataLen) {
|
|
27
27
|
return bandersnatchWasm.batchGenerateRingVrf(ringKeys, proverKeyIndex, secretSeed, inputsData, vrfInputDataLen);
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Batch-generate ring VRF tickets for multiple validators in a single call,
|
|
31
|
+
* reusing the ring prover setup across all of them.
|
|
32
|
+
*
|
|
33
|
+
* `secretSeedsData` is the fixed-width concatenation of the validators' secret
|
|
34
|
+
* seeds (each `secretSeedDataLen` bytes); `proverKeyIndices` are their indices
|
|
35
|
+
* within the ring and must have the same count. Output records are ordered
|
|
36
|
+
* validator-major then input-major, each `status byte || signature`.
|
|
37
|
+
*/
|
|
38
|
+
async batchGenerateRingVrfForValidators(ringKeys, proverKeyIndices, secretSeedsData, secretSeedDataLen, inputsData, vrfInputDataLen) {
|
|
39
|
+
return bandersnatchWasm.batchGenerateRingVrfForValidators(ringKeys, proverKeyIndices, secretSeedsData, secretSeedDataLen, inputsData, vrfInputDataLen);
|
|
40
|
+
}
|
|
29
41
|
}
|
|
@@ -9,7 +9,8 @@ import { Result } from "#@typeberry/utils";
|
|
|
9
9
|
* it delegates to another process that doesn't bother to send the id back over the wire.
|
|
10
10
|
*/
|
|
11
11
|
export type ValidatedTicket = {
|
|
12
|
-
|
|
12
|
+
ticket: SignedTicket;
|
|
13
|
+
id: EntropyHash;
|
|
13
14
|
};
|
|
14
15
|
/** Reasons a ticket may fail validation. */
|
|
15
16
|
export declare enum ValidationError {
|
|
@@ -27,20 +28,20 @@ export declare enum ValidationError {
|
|
|
27
28
|
* worker via IPC, or short-circuit (Accept/Deny defaults for tests).
|
|
28
29
|
*/
|
|
29
30
|
export interface TicketValidator {
|
|
30
|
-
validate(epochIndex: Epoch,
|
|
31
|
+
validate(epochIndex: Epoch, tickets: SignedTicket[]): Promise<Result<ValidatedTicket[], ValidationError>>;
|
|
31
32
|
}
|
|
32
33
|
/**
|
|
33
34
|
* Accepts every ticket without inspection. Useful for unit tests where the validator
|
|
34
35
|
* isn't the subject under test. Must never be used in production.
|
|
35
36
|
*/
|
|
36
37
|
export declare class AcceptTicketsValidator implements TicketValidator {
|
|
37
|
-
validate(_epochIndex: Epoch,
|
|
38
|
+
validate(_epochIndex: Epoch, ticket: SignedTicket[]): Promise<Result<ValidatedTicket[], ValidationError>>;
|
|
38
39
|
}
|
|
39
40
|
/**
|
|
40
41
|
* Rejects every ticket. Used as the default for any task that needs an explicit, real
|
|
41
42
|
* validator wired in before it will accept anything from the network.
|
|
42
43
|
*/
|
|
43
44
|
export declare class DenyTicketsValidator implements TicketValidator {
|
|
44
|
-
validate(_epochIndex: Epoch,
|
|
45
|
+
validate(_epochIndex: Epoch, _tickets: SignedTicket[]): Promise<Result<ValidatedTicket[], ValidationError>>;
|
|
45
46
|
}
|
|
46
47
|
//# sourceMappingURL=ticket-validator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ticket-validator.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/ticket-pool/ticket-validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"ticket-validator.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/ticket-pool/ticket-validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAGhE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,YAAY,CAAC;IACrB,EAAE,EAAE,WAAW,CAAC;CACjB,CAAC;AAEF,4CAA4C;AAC5C,oBAAY,eAAe;IACzB,+CAA+C;IAC/C,YAAY,kBAAkB;IAC9B,oFAAoF;IACpF,oBAAoB,0BAA0B;IAC9C,yEAAyE;IACzE,UAAU,gBAAgB;CAC3B;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;CAC3G;AAED;;;GAGG;AACH,qBAAa,sBAAuB,YAAW,eAAe;IACtD,QAAQ,CAAC,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,EAAE,eAAe,CAAC,CAAC;CAQhH;AAED;;;GAGG;AACH,qBAAa,oBAAqB,YAAW,eAAe;IACpD,QAAQ,CAAC,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,EAAE,eAAe,CAAC,CAAC;CAGlH"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Bytes } from "#@typeberry/bytes";
|
|
2
|
+
import { HASH_SIZE } from "#@typeberry/hash";
|
|
1
3
|
import { Result } from "#@typeberry/utils";
|
|
2
4
|
/** Reasons a ticket may fail validation. */
|
|
3
5
|
export var ValidationError;
|
|
@@ -14,8 +16,11 @@ export var ValidationError;
|
|
|
14
16
|
* isn't the subject under test. Must never be used in production.
|
|
15
17
|
*/
|
|
16
18
|
export class AcceptTicketsValidator {
|
|
17
|
-
async validate(_epochIndex,
|
|
18
|
-
return Result.ok(
|
|
19
|
+
async validate(_epochIndex, ticket) {
|
|
20
|
+
return Result.ok(ticket.map((ticket) => ({
|
|
21
|
+
ticket,
|
|
22
|
+
id: Bytes.zero(HASH_SIZE).asOpaque(),
|
|
23
|
+
})));
|
|
19
24
|
}
|
|
20
25
|
}
|
|
21
26
|
/**
|
|
@@ -23,7 +28,7 @@ export class AcceptTicketsValidator {
|
|
|
23
28
|
* validator wired in before it will accept anything from the network.
|
|
24
29
|
*/
|
|
25
30
|
export class DenyTicketsValidator {
|
|
26
|
-
async validate(_epochIndex,
|
|
31
|
+
async validate(_epochIndex, _tickets) {
|
|
27
32
|
return Result.error(ValidationError.ValidatorUnavailable, () => "no ticket validator wired");
|
|
28
33
|
}
|
|
29
34
|
}
|
|
@@ -4,6 +4,7 @@ import { tryAsEpoch } from "#@typeberry/block";
|
|
|
4
4
|
import { SignedTicket, tryAsTicketAttempt } from "#@typeberry/block/tickets.js";
|
|
5
5
|
import { Bytes } from "#@typeberry/bytes";
|
|
6
6
|
import { BANDERSNATCH_PROOF_BYTES } from "#@typeberry/crypto";
|
|
7
|
+
import { HASH_SIZE } from "#@typeberry/hash";
|
|
7
8
|
import { AcceptTicketsValidator, DenyTicketsValidator, ValidationError } from "./ticket-validator.js";
|
|
8
9
|
const E1 = tryAsEpoch(1);
|
|
9
10
|
function makeTicket() {
|
|
@@ -13,19 +14,19 @@ function makeTicket() {
|
|
|
13
14
|
});
|
|
14
15
|
}
|
|
15
16
|
describe("AcceptTicketsValidator", () => {
|
|
16
|
-
it("returns ok with
|
|
17
|
+
it("returns ok with zero id", async () => {
|
|
17
18
|
const v = new AcceptTicketsValidator();
|
|
18
|
-
const res = await v.validate(E1, makeTicket());
|
|
19
|
+
const res = await v.validate(E1, [makeTicket()]);
|
|
19
20
|
assert.strictEqual(res.isOk, true);
|
|
20
21
|
if (res.isOk) {
|
|
21
|
-
assert.strictEqual(res.ok.id,
|
|
22
|
+
assert.strictEqual(res.ok[0].id.toString(), Bytes.zero(HASH_SIZE).toString());
|
|
22
23
|
}
|
|
23
24
|
});
|
|
24
25
|
});
|
|
25
26
|
describe("DenyTicketsValidator", () => {
|
|
26
27
|
it("returns ValidatorUnavailable", async () => {
|
|
27
28
|
const v = new DenyTicketsValidator();
|
|
28
|
-
const res = await v.validate(E1, makeTicket());
|
|
29
|
+
const res = await v.validate(E1, [makeTicket()]);
|
|
29
30
|
assert.strictEqual(res.isError, true);
|
|
30
31
|
if (res.isError) {
|
|
31
32
|
assert.strictEqual(res.error, ValidationError.ValidatorUnavailable);
|
|
@@ -16,6 +16,8 @@ export type VerifiedTicket = {
|
|
|
16
16
|
export declare class VerifiedTicketPool {
|
|
17
17
|
private readonly perEpoch;
|
|
18
18
|
private readonly idSets;
|
|
19
|
+
static new(): VerifiedTicketPool;
|
|
20
|
+
private constructor();
|
|
19
21
|
/** Add pre-verified tickets to the pool, deduping by id. */
|
|
20
22
|
add(epochIndex: Epoch, verifiedTickets: readonly VerifiedTicket[]): void;
|
|
21
23
|
/** Returns the verified tickets for the given epoch, or an empty array if none. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verified-ticket-pool.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/ticket-pool/verified-ticket-pool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAGhE,yFAAyF;AACzF,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,EAAE,EAAE,WAAW,CAAC;CACjB,CAAC;AAEF;;;;;;;GAOG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsC;IAC/D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IAEjE,4DAA4D;IAC5D,GAAG,CAAC,UAAU,EAAE,KAAK,EAAE,eAAe,EAAE,SAAS,cAAc,EAAE,GAAG,IAAI;IAoBxE,mFAAmF;IACnF,WAAW,CAAC,UAAU,EAAE,KAAK,GAAG,SAAS,cAAc,EAAE;CAG1D"}
|
|
1
|
+
{"version":3,"file":"verified-ticket-pool.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/ticket-pool/verified-ticket-pool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAGhE,yFAAyF;AACzF,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,EAAE,EAAE,WAAW,CAAC;CACjB,CAAC;AAEF;;;;;;;GAOG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsC;IAC/D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IAEjE,MAAM,CAAC,GAAG;IAIV,OAAO;IAEP,4DAA4D;IAC5D,GAAG,CAAC,UAAU,EAAE,KAAK,EAAE,eAAe,EAAE,SAAS,cAAc,EAAE,GAAG,IAAI;IAoBxE,mFAAmF;IACnF,WAAW,CAAC,UAAU,EAAE,KAAK,GAAG,SAAS,cAAc,EAAE;CAG1D"}
|
|
@@ -10,6 +10,10 @@ import { HashSet } from "#@typeberry/collections/hash-set.js";
|
|
|
10
10
|
export class VerifiedTicketPool {
|
|
11
11
|
perEpoch = new Map();
|
|
12
12
|
idSets = new Map();
|
|
13
|
+
static new() {
|
|
14
|
+
return new VerifiedTicketPool();
|
|
15
|
+
}
|
|
16
|
+
constructor() { }
|
|
13
17
|
/** Add pre-verified tickets to the pool, deduping by id. */
|
|
14
18
|
add(epochIndex, verifiedTickets) {
|
|
15
19
|
if (this.perEpoch.size > 0 && !this.perEpoch.has(epochIndex)) {
|