@typeberry/lib 0.8.4-9502983 → 0.8.4-faebc7a

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.
Files changed (63) hide show
  1. package/package.json +6 -4
  2. package/packages/jam/database-fjall/hybrid-states.d.ts +45 -0
  3. package/packages/jam/database-fjall/hybrid-states.d.ts.map +1 -0
  4. package/packages/jam/database-fjall/hybrid-states.js +113 -0
  5. package/packages/jam/database-fjall/hybrid-states.test.d.ts +2 -0
  6. package/packages/jam/database-fjall/hybrid-states.test.d.ts.map +1 -0
  7. package/packages/jam/database-fjall/hybrid-states.test.js +83 -0
  8. package/packages/jam/database-fjall/index.d.ts +3 -0
  9. package/packages/jam/database-fjall/index.d.ts.map +1 -0
  10. package/packages/jam/database-fjall/index.js +2 -0
  11. package/packages/jam/database-fjall/root.d.ts +52 -0
  12. package/packages/jam/database-fjall/root.d.ts.map +1 -0
  13. package/packages/jam/database-fjall/root.js +85 -0
  14. package/packages/jam/jamnp-s/tasks/ticket-distribution.d.ts +18 -10
  15. package/packages/jam/jamnp-s/tasks/ticket-distribution.d.ts.map +1 -1
  16. package/packages/jam/jamnp-s/tasks/ticket-distribution.js +44 -68
  17. package/packages/jam/jamnp-s/tasks/ticket-distribution.test.js +30 -8
  18. package/packages/jam/node/main-fuzz.d.ts.map +1 -1
  19. package/packages/jam/node/main-fuzz.js +16 -1
  20. package/packages/jam/node/main-importer.d.ts +6 -3
  21. package/packages/jam/node/main-importer.d.ts.map +1 -1
  22. package/packages/jam/node/main-importer.js +3 -2
  23. package/packages/jam/safrole/bandersnatch-vrf.d.ts +2 -2
  24. package/packages/jam/safrole/bandersnatch-vrf.d.ts.map +1 -1
  25. package/packages/jam/safrole/bandersnatch-vrf.js +9 -6
  26. package/packages/jam/safrole/bandersnatch-vrf.test.js +9 -7
  27. package/packages/jam/safrole/safrole.js +5 -5
  28. package/packages/jam/safrole/safrole.test.js +13 -13
  29. package/packages/jam/ticket-pool/index.d.ts +4 -0
  30. package/packages/jam/ticket-pool/index.d.ts.map +1 -0
  31. package/packages/jam/ticket-pool/index.js +3 -0
  32. package/packages/jam/ticket-pool/pending-ticket-pool.d.ts +30 -0
  33. package/packages/jam/ticket-pool/pending-ticket-pool.d.ts.map +1 -0
  34. package/packages/jam/ticket-pool/pending-ticket-pool.js +56 -0
  35. package/packages/jam/ticket-pool/pending-ticket-pool.test.d.ts +2 -0
  36. package/packages/jam/ticket-pool/pending-ticket-pool.test.d.ts.map +1 -0
  37. package/packages/jam/ticket-pool/pending-ticket-pool.test.js +67 -0
  38. package/packages/jam/ticket-pool/ticket-validator.d.ts +46 -0
  39. package/packages/jam/ticket-pool/ticket-validator.d.ts.map +1 -0
  40. package/packages/jam/ticket-pool/ticket-validator.js +29 -0
  41. package/packages/jam/ticket-pool/ticket-validator.test.d.ts +2 -0
  42. package/packages/jam/ticket-pool/ticket-validator.test.d.ts.map +1 -0
  43. package/packages/jam/ticket-pool/ticket-validator.test.js +34 -0
  44. package/packages/jam/ticket-pool/verified-ticket-pool.d.ts +24 -0
  45. package/packages/jam/ticket-pool/verified-ticket-pool.d.ts.map +1 -0
  46. package/packages/jam/ticket-pool/verified-ticket-pool.js +37 -0
  47. package/packages/jam/ticket-pool/verified-ticket-pool.test.d.ts +2 -0
  48. package/packages/jam/ticket-pool/verified-ticket-pool.test.d.ts.map +1 -0
  49. package/packages/jam/ticket-pool/verified-ticket-pool.test.js +54 -0
  50. package/packages/workers/api-node/config.d.ts +12 -5
  51. package/packages/workers/api-node/config.d.ts.map +1 -1
  52. package/packages/workers/api-node/config.js +20 -17
  53. package/packages/workers/api-node/config.test.js +38 -1
  54. package/packages/workers/block-authorship/main.d.ts.map +1 -1
  55. package/packages/workers/block-authorship/main.js +22 -72
  56. package/packages/workers/block-authorship/ticket-validator.d.ts +32 -0
  57. package/packages/workers/block-authorship/ticket-validator.d.ts.map +1 -0
  58. package/packages/workers/block-authorship/ticket-validator.js +56 -0
  59. package/packages/workers/comms-authorship-network/protocol.d.ts +10 -0
  60. package/packages/workers/comms-authorship-network/protocol.d.ts.map +1 -1
  61. package/packages/workers/comms-authorship-network/protocol.js +8 -1
  62. package/packages/workers/jam-network/main.d.ts.map +1 -1
  63. package/packages/workers/jam-network/main.js +20 -4
@@ -0,0 +1,67 @@
1
+ import assert from "node:assert";
2
+ import { describe, it } from "node:test";
3
+ import { tryAsEpoch } from "#@typeberry/block";
4
+ import { SignedTicket, tryAsTicketAttempt } from "#@typeberry/block/tickets.js";
5
+ import { Bytes } from "#@typeberry/bytes";
6
+ import { BANDERSNATCH_PROOF_BYTES } from "#@typeberry/crypto";
7
+ import { PendingTicketPool } from "./pending-ticket-pool.js";
8
+ const E1 = tryAsEpoch(1);
9
+ const E2 = tryAsEpoch(2);
10
+ function makeTicket(seed, attempt = 0) {
11
+ const sig = Bytes.zero(BANDERSNATCH_PROOF_BYTES);
12
+ sig.raw[0] = seed;
13
+ return SignedTicket.create({
14
+ attempt: tryAsTicketAttempt(attempt),
15
+ signature: sig.asOpaque(),
16
+ });
17
+ }
18
+ describe("PendingTicketPool", () => {
19
+ it("starts empty with no current epoch", () => {
20
+ const pool = new PendingTicketPool();
21
+ assert.strictEqual(pool.currentEpoch, null);
22
+ assert.deepStrictEqual(pool.getTickets(), []);
23
+ });
24
+ it("adds a ticket and tracks the epoch", () => {
25
+ const pool = new PendingTicketPool();
26
+ const t = makeTicket(1);
27
+ assert.strictEqual(pool.addTicket(E1, t), true);
28
+ assert.strictEqual(pool.currentEpoch, E1);
29
+ assert.strictEqual(pool.getTickets().length, 1);
30
+ });
31
+ it("dedups by signature within an epoch", () => {
32
+ const pool = new PendingTicketPool();
33
+ const t = makeTicket(1);
34
+ pool.addTicket(E1, t);
35
+ assert.strictEqual(pool.addTicket(E1, t), false);
36
+ assert.strictEqual(pool.getTickets().length, 1);
37
+ });
38
+ it("clears tickets when a newer epoch arrives", () => {
39
+ const pool = new PendingTicketPool();
40
+ pool.addTicket(E1, makeTicket(1));
41
+ pool.addTicket(E1, makeTicket(2));
42
+ pool.addTicket(E2, makeTicket(3));
43
+ const tickets = pool.getTickets();
44
+ assert.strictEqual(tickets.length, 1);
45
+ assert.strictEqual(tickets[0].epochIndex, E2);
46
+ assert.strictEqual(pool.currentEpoch, E2);
47
+ });
48
+ it("drops late tickets for older epochs", () => {
49
+ const pool = new PendingTicketPool();
50
+ pool.addTicket(E2, makeTicket(1));
51
+ assert.strictEqual(pool.addTicket(E1, makeTicket(2)), false);
52
+ assert.strictEqual(pool.getTickets().length, 1);
53
+ assert.strictEqual(pool.currentEpoch, E2);
54
+ });
55
+ it("replace clears existing tickets and dedups the new set", () => {
56
+ const pool = new PendingTicketPool();
57
+ pool.addTicket(E1, makeTicket(1));
58
+ pool.addTicket(E1, makeTicket(2));
59
+ const dump = [makeTicket(3), makeTicket(4), makeTicket(3)];
60
+ pool.replace(E2, dump);
61
+ const tickets = pool.getTickets();
62
+ assert.strictEqual(tickets.length, 2);
63
+ assert.strictEqual(pool.currentEpoch, E2);
64
+ assert.strictEqual(tickets[0].ticket.signature.raw[0], 3);
65
+ assert.strictEqual(tickets[1].ticket.signature.raw[0], 4);
66
+ });
67
+ });
@@ -0,0 +1,46 @@
1
+ import type { EntropyHash, Epoch } from "#@typeberry/block";
2
+ import type { SignedTicket } from "#@typeberry/block/tickets.js";
3
+ import { Result } from "#@typeberry/utils";
4
+ /**
5
+ * Outcome of a successful validation.
6
+ *
7
+ * `id` is the entropy hash the validator computed for this ticket. It is `null` when the
8
+ * concrete validator doesn't actually verify (e.g. {@link AcceptTicketsValidator}) or when
9
+ * it delegates to another process that doesn't bother to send the id back over the wire.
10
+ */
11
+ export type ValidatedTicket = {
12
+ id: EntropyHash | null;
13
+ };
14
+ /** Reasons a ticket may fail validation. */
15
+ export declare enum ValidationError {
16
+ /** Verifier rejected the signature / proof. */
17
+ InvalidProof = "invalid_proof",
18
+ /** Validator could not run (e.g. state unavailable, transient internal failure). */
19
+ ValidatorUnavailable = "validator_unavailable",
20
+ /** Ticket is for an epoch outside the validator's window of interest. */
21
+ WrongEpoch = "wrong_epoch"
22
+ }
23
+ /**
24
+ * Strategy for verifying tickets arriving from peers.
25
+ *
26
+ * The concrete implementation may call into the bandersnatch verifier, defer to another
27
+ * worker via IPC, or short-circuit (Accept/Deny defaults for tests).
28
+ */
29
+ export interface TicketValidator {
30
+ validate(epochIndex: Epoch, ticket: SignedTicket): Promise<Result<ValidatedTicket, ValidationError>>;
31
+ }
32
+ /**
33
+ * Accepts every ticket without inspection. Useful for unit tests where the validator
34
+ * isn't the subject under test. Must never be used in production.
35
+ */
36
+ export declare class AcceptTicketsValidator implements TicketValidator {
37
+ validate(_epochIndex: Epoch, _ticket: SignedTicket): Promise<Result<ValidatedTicket, ValidationError>>;
38
+ }
39
+ /**
40
+ * Rejects every ticket. Used as the default for any task that needs an explicit, real
41
+ * validator wired in before it will accept anything from the network.
42
+ */
43
+ export declare class DenyTicketsValidator implements TicketValidator {
44
+ validate(_epochIndex: Epoch, _ticket: SignedTicket): Promise<Result<ValidatedTicket, ValidationError>>;
45
+ }
46
+ //# sourceMappingURL=ticket-validator.d.ts.map
@@ -0,0 +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;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,WAAW,GAAG,IAAI,CAAC;CACxB,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,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC,CAAC;CACtG;AAED;;;GAGG;AACH,qBAAa,sBAAuB,YAAW,eAAe;IACtD,QAAQ,CAAC,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;CAG7G;AAED;;;GAGG;AACH,qBAAa,oBAAqB,YAAW,eAAe;IACpD,QAAQ,CAAC,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;CAG7G"}
@@ -0,0 +1,29 @@
1
+ import { Result } from "#@typeberry/utils";
2
+ /** Reasons a ticket may fail validation. */
3
+ export var ValidationError;
4
+ (function (ValidationError) {
5
+ /** Verifier rejected the signature / proof. */
6
+ ValidationError["InvalidProof"] = "invalid_proof";
7
+ /** Validator could not run (e.g. state unavailable, transient internal failure). */
8
+ ValidationError["ValidatorUnavailable"] = "validator_unavailable";
9
+ /** Ticket is for an epoch outside the validator's window of interest. */
10
+ ValidationError["WrongEpoch"] = "wrong_epoch";
11
+ })(ValidationError || (ValidationError = {}));
12
+ /**
13
+ * Accepts every ticket without inspection. Useful for unit tests where the validator
14
+ * isn't the subject under test. Must never be used in production.
15
+ */
16
+ export class AcceptTicketsValidator {
17
+ async validate(_epochIndex, _ticket) {
18
+ return Result.ok({ id: null });
19
+ }
20
+ }
21
+ /**
22
+ * Rejects every ticket. Used as the default for any task that needs an explicit, real
23
+ * validator wired in before it will accept anything from the network.
24
+ */
25
+ export class DenyTicketsValidator {
26
+ async validate(_epochIndex, _ticket) {
27
+ return Result.error(ValidationError.ValidatorUnavailable, () => "no ticket validator wired");
28
+ }
29
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ticket-validator.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ticket-validator.test.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/ticket-pool/ticket-validator.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,34 @@
1
+ import assert from "node:assert";
2
+ import { describe, it } from "node:test";
3
+ import { tryAsEpoch } from "#@typeberry/block";
4
+ import { SignedTicket, tryAsTicketAttempt } from "#@typeberry/block/tickets.js";
5
+ import { Bytes } from "#@typeberry/bytes";
6
+ import { BANDERSNATCH_PROOF_BYTES } from "#@typeberry/crypto";
7
+ import { AcceptTicketsValidator, DenyTicketsValidator, ValidationError } from "./ticket-validator.js";
8
+ const E1 = tryAsEpoch(1);
9
+ function makeTicket() {
10
+ return SignedTicket.create({
11
+ attempt: tryAsTicketAttempt(0),
12
+ signature: Bytes.zero(BANDERSNATCH_PROOF_BYTES).asOpaque(),
13
+ });
14
+ }
15
+ describe("AcceptTicketsValidator", () => {
16
+ it("returns ok with null id", async () => {
17
+ const v = new AcceptTicketsValidator();
18
+ const res = await v.validate(E1, makeTicket());
19
+ assert.strictEqual(res.isOk, true);
20
+ if (res.isOk) {
21
+ assert.strictEqual(res.ok.id, null);
22
+ }
23
+ });
24
+ });
25
+ describe("DenyTicketsValidator", () => {
26
+ it("returns ValidatorUnavailable", async () => {
27
+ const v = new DenyTicketsValidator();
28
+ const res = await v.validate(E1, makeTicket());
29
+ assert.strictEqual(res.isError, true);
30
+ if (res.isError) {
31
+ assert.strictEqual(res.error, ValidationError.ValidatorUnavailable);
32
+ }
33
+ });
34
+ });
@@ -0,0 +1,24 @@
1
+ import type { EntropyHash, Epoch } from "#@typeberry/block";
2
+ import type { SignedTicket } from "#@typeberry/block/tickets.js";
3
+ /** A ticket the validator already verified, paired with the entropy hash (ticket id). */
4
+ export type VerifiedTicket = {
5
+ ticket: SignedTicket;
6
+ id: EntropyHash;
7
+ };
8
+ /**
9
+ * In-memory pool of verified tickets for the current epoch, keyed by ticket id.
10
+ *
11
+ * Used on the authorship side. Tickets are stored per epoch and deduplicated by their
12
+ * computed entropy hash (so duplicates arriving via different peers / paths are coalesced
13
+ * cheaply). The pool only ever needs to hold tickets for one epoch at a time; switching
14
+ * to a new epoch clears everything older.
15
+ */
16
+ export declare class VerifiedTicketPool {
17
+ private readonly perEpoch;
18
+ private readonly idSets;
19
+ /** Add pre-verified tickets to the pool, deduping by id. */
20
+ add(epochIndex: Epoch, verifiedTickets: readonly VerifiedTicket[]): void;
21
+ /** Returns the verified tickets for the given epoch, or an empty array if none. */
22
+ getForEpoch(epochIndex: Epoch): readonly VerifiedTicket[];
23
+ }
24
+ //# sourceMappingURL=verified-ticket-pool.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,37 @@
1
+ import { HashSet } from "#@typeberry/collections/hash-set.js";
2
+ /**
3
+ * In-memory pool of verified tickets for the current epoch, keyed by ticket id.
4
+ *
5
+ * Used on the authorship side. Tickets are stored per epoch and deduplicated by their
6
+ * computed entropy hash (so duplicates arriving via different peers / paths are coalesced
7
+ * cheaply). The pool only ever needs to hold tickets for one epoch at a time; switching
8
+ * to a new epoch clears everything older.
9
+ */
10
+ export class VerifiedTicketPool {
11
+ perEpoch = new Map();
12
+ idSets = new Map();
13
+ /** Add pre-verified tickets to the pool, deduping by id. */
14
+ add(epochIndex, verifiedTickets) {
15
+ if (this.perEpoch.size > 0 && !this.perEpoch.has(epochIndex)) {
16
+ this.perEpoch.clear();
17
+ this.idSets.clear();
18
+ }
19
+ const existing = this.perEpoch.get(epochIndex) ?? [];
20
+ let idSet = this.idSets.get(epochIndex) ?? null;
21
+ if (idSet === null) {
22
+ idSet = HashSet.new();
23
+ this.idSets.set(epochIndex, idSet);
24
+ }
25
+ for (const entry of verifiedTickets) {
26
+ if (!idSet.has(entry.id)) {
27
+ existing.push(entry);
28
+ idSet.insert(entry.id);
29
+ }
30
+ }
31
+ this.perEpoch.set(epochIndex, existing);
32
+ }
33
+ /** Returns the verified tickets for the given epoch, or an empty array if none. */
34
+ getForEpoch(epochIndex) {
35
+ return this.perEpoch.get(epochIndex) ?? [];
36
+ }
37
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=verified-ticket-pool.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verified-ticket-pool.test.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/ticket-pool/verified-ticket-pool.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,54 @@
1
+ import assert from "node:assert";
2
+ import { describe, it } from "node:test";
3
+ import { tryAsEpoch } from "#@typeberry/block";
4
+ import { SignedTicket, tryAsTicketAttempt } from "#@typeberry/block/tickets.js";
5
+ import { Bytes } from "#@typeberry/bytes";
6
+ import { BANDERSNATCH_PROOF_BYTES } from "#@typeberry/crypto";
7
+ import { HASH_SIZE } from "#@typeberry/hash";
8
+ import { VerifiedTicketPool } from "./verified-ticket-pool.js";
9
+ const E1 = tryAsEpoch(1);
10
+ const E2 = tryAsEpoch(2);
11
+ function makeTicket(seed) {
12
+ const sig = Bytes.zero(BANDERSNATCH_PROOF_BYTES);
13
+ sig.raw[0] = seed;
14
+ return SignedTicket.create({
15
+ attempt: tryAsTicketAttempt(0),
16
+ signature: sig.asOpaque(),
17
+ });
18
+ }
19
+ function makeId(byte) {
20
+ return Bytes.fill(HASH_SIZE, byte).asOpaque();
21
+ }
22
+ describe("VerifiedTicketPool", () => {
23
+ it("starts empty", () => {
24
+ const pool = new VerifiedTicketPool();
25
+ assert.deepStrictEqual(pool.getForEpoch(E1), []);
26
+ });
27
+ it("adds and retrieves tickets per epoch", () => {
28
+ const pool = new VerifiedTicketPool();
29
+ pool.add(E1, [{ ticket: makeTicket(1), id: makeId(0xaa) }]);
30
+ assert.strictEqual(pool.getForEpoch(E1).length, 1);
31
+ assert.deepStrictEqual(pool.getForEpoch(E2), []);
32
+ });
33
+ it("dedups by id", () => {
34
+ const pool = new VerifiedTicketPool();
35
+ const id = makeId(0x01);
36
+ pool.add(E1, [{ ticket: makeTicket(1), id }]);
37
+ pool.add(E1, [{ ticket: makeTicket(2), id }]);
38
+ assert.strictEqual(pool.getForEpoch(E1).length, 1);
39
+ assert.strictEqual(pool.getForEpoch(E1)[0].ticket.signature.raw[0], 1);
40
+ });
41
+ it("clears previous epochs when a new epoch is added", () => {
42
+ const pool = new VerifiedTicketPool();
43
+ pool.add(E1, [{ ticket: makeTicket(1), id: makeId(1) }]);
44
+ pool.add(E2, [{ ticket: makeTicket(2), id: makeId(2) }]);
45
+ assert.deepStrictEqual(pool.getForEpoch(E1), []);
46
+ assert.strictEqual(pool.getForEpoch(E2).length, 1);
47
+ });
48
+ it("appends across multiple add() calls for the same epoch", () => {
49
+ const pool = new VerifiedTicketPool();
50
+ pool.add(E1, [{ ticket: makeTicket(1), id: makeId(1) }]);
51
+ pool.add(E1, [{ ticket: makeTicket(2), id: makeId(2) }]);
52
+ assert.strictEqual(pool.getForEpoch(E1).length, 2);
53
+ });
54
+ });
@@ -71,13 +71,19 @@ export declare class InMemWorkerConfig<T = undefined> implements WorkerConfig<T,
71
71
  readonly: boolean;
72
72
  }): RootDb<BlocksDb, SerializedStatesDb>;
73
73
  }
74
+ /** Persistent values store backing the hybrid config. */
75
+ export type HybridBackend = "lmdb" | "fjall";
74
76
  /**
75
77
  * Hybrid worker config for the fuzz target: in-memory blocks and leaf sets,
76
- * but large values persisted to LMDB.
78
+ * but large values persisted to disk (LMDB or fjall, selected by `backend`).
79
+ *
80
+ * The fjall backend is opt-in so its performance can be compared against LMDB
81
+ * before committing to it. fjall opens its keyspace asynchronously, hence the
82
+ * async `new`.
77
83
  *
78
84
  * Like `InMemWorkerConfig`, the blocks and leaf sets are shared across the
79
85
  * open/close/reopen dance that genesis init performs, so `openDatabase`
80
- * returns the same instances and a no-op close. The LMDB root is opened once
86
+ * returns the same instances and a no-op close. The values store is opened once
81
87
  * here and closed by `HybridSerializedStates.close()` at importer teardown.
82
88
  *
83
89
  * In-process only: it holds shared mutable state (the in-memory leaf
@@ -92,7 +98,8 @@ export declare class HybridWorkerConfig<T = undefined> implements WorkerConfig<T
92
98
  readonly dbPath: string;
93
99
  readonly ephemeral: boolean;
94
100
  readonly compression: boolean;
95
- static new<T>({ nodeName, chainSpec, workerParams, blake2b, dbPath, ephemeral, compression, }: {
101
+ private readonly states;
102
+ static new<T>({ nodeName, chainSpec, workerParams, blake2b, dbPath, ephemeral, compression, backend, }: {
96
103
  nodeName: string;
97
104
  chainSpec: ChainSpec;
98
105
  workerParams: T;
@@ -100,9 +107,9 @@ export declare class HybridWorkerConfig<T = undefined> implements WorkerConfig<T
100
107
  dbPath: string;
101
108
  ephemeral?: boolean;
102
109
  compression?: boolean;
103
- }): HybridWorkerConfig<T>;
110
+ backend?: HybridBackend;
111
+ }): Promise<HybridWorkerConfig<T>>;
104
112
  private readonly blocks;
105
- private readonly states;
106
113
  private constructor();
107
114
  openDatabase(_options?: {
108
115
  readonly: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/api-node/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,KAAK,MAAM,EAAW,KAAK,MAAM,EAAW,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EACL,KAAK,QAAQ,EAGb,KAAK,MAAM,EACX,KAAK,kBAAkB,EACxB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE9D,+EAA+E;AAC/E,qBAAa,gBAAgB,CAAC,CAAC,GAAG,IAAI,CAAE,YAAW,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,kBAAkB,CAAC;aAyC5E,QAAQ,EAAE,MAAM;aAChB,SAAS,EAAE,SAAS;aACpB,YAAY,EAAE,CAAC;aACf,MAAM,EAAE,MAAM;aACd,OAAO,EAAE,OAAO;aAChB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC;aAI9B,SAAS,EAAE,OAAO;IAjDpC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EACZ,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,MAAM,EACN,OAAO,EACP,KAAiB,EACjB,SAAiB,GAClB,EAAE;QACD,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,SAAS,CAAC;QACrB,YAAY,EAAE,CAAC,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,OAAO,CAAC;QACjB,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAChC,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB;IAID,6DAA6D;WAChD,gBAAgB,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,kBAAkB;IAkBpF,OAAO;IAaP,YAAY,CAAC,OAAO,GAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAuB,GAAG,MAAM,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IAavG,6DAA6D;IAC7D,gBAAgB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,kBAAkB;CAS7D;AAED,6DAA6D;AAC7D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,UAAU,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAAE,CAAC;CAC3C,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,WAAW,EAAE,CAE5E;AAED;;;;GAIG;AACH,qBAAa,iBAAiB,CAAC,CAAC,GAAG,SAAS,CAAE,YAAW,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,kBAAkB,CAAC;aAmBlF,QAAQ,EAAE,MAAM;aAChB,SAAS,EAAE,SAAS;aACpB,YAAY,EAAE,CAAC;aACf,OAAO,EAAE,OAAO;IArBlC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EACZ,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,OAAO,GACR,EAAE;QACD,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,SAAS,CAAC;QACrB,YAAY,EAAE,CAAC,CAAC;QAChB,OAAO,EAAE,OAAO,CAAC;KAClB;IAID,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2B;IAElD,OAAO;IAUP,YAAY,CAAC,QAAQ,GAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAuB,GAAG,MAAM,CAAC,QAAQ,EAAE,kBAAkB,CAAC;CAQzG;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,kBAAkB,CAAC,CAAC,GAAG,SAAS,CAAE,YAAW,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,kBAAkB,CAAC;aAyBnF,QAAQ,EAAE,MAAM;aAChB,SAAS,EAAE,SAAS;aACpB,YAAY,EAAE,CAAC;aACf,OAAO,EAAE,OAAO;aAChB,MAAM,EAAE,MAAM;aACd,SAAS,EAAE,OAAO;aAClB,WAAW,EAAE,OAAO;IA9BtC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EACZ,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,OAAO,EACP,MAAM,EACN,SAAiB,EACjB,WAAkB,GACnB,EAAE;QACD,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,SAAS,CAAC;QACrB,YAAY,EAAE,CAAC,CAAC;QAChB,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,WAAW,CAAC,EAAE,OAAO,CAAC;KACvB;IAID,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAEhD,OAAO;IAoBP,YAAY,CAAC,QAAQ,GAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAuB,GAAG,MAAM,CAAC,QAAQ,EAAE,kBAAkB,CAAC;CASzG"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/api-node/config.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,8 @@
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, LmdbBlocks, LmdbRoot, LmdbStates } from "#@typeberry/database-lmdb";
4
+ import { HybridSerializedStates as FjallHybridSerializedStates } 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
  /** A worker config that's usable in node.js and uses LMDB database backend. */
@@ -110,11 +111,15 @@ export class InMemWorkerConfig {
110
111
  }
111
112
  /**
112
113
  * Hybrid worker config for the fuzz target: in-memory blocks and leaf sets,
113
- * but large values persisted to LMDB.
114
+ * but large values persisted to disk (LMDB or fjall, selected by `backend`).
115
+ *
116
+ * The fjall backend is opt-in so its performance can be compared against LMDB
117
+ * before committing to it. fjall opens its keyspace asynchronously, hence the
118
+ * async `new`.
114
119
  *
115
120
  * Like `InMemWorkerConfig`, the blocks and leaf sets are shared across the
116
121
  * open/close/reopen dance that genesis init performs, so `openDatabase`
117
- * returns the same instances and a no-op close. The LMDB root is opened once
122
+ * returns the same instances and a no-op close. The values store is opened once
118
123
  * here and closed by `HybridSerializedStates.close()` at importer teardown.
119
124
  *
120
125
  * In-process only: it holds shared mutable state (the in-memory leaf
@@ -129,12 +134,17 @@ export class HybridWorkerConfig {
129
134
  dbPath;
130
135
  ephemeral;
131
136
  compression;
132
- static new({ nodeName, chainSpec, workerParams, blake2b, dbPath, ephemeral = false, compression = true, }) {
133
- return new HybridWorkerConfig(nodeName, chainSpec, workerParams, blake2b, dbPath, ephemeral, compression);
137
+ states;
138
+ static async new({ nodeName, chainSpec, workerParams, blake2b, dbPath, ephemeral = false, compression = true, backend = "lmdb", }) {
139
+ // fjall opens its keyspace asynchronously; LMDB is synchronous. Either way
140
+ // the values store is created once here and shared across reopen.
141
+ const states = backend === "fjall"
142
+ ? await FjallHybridSerializedStates.new({ spec: chainSpec, blake2b, dbPath, ephemeral })
143
+ : LmdbHybridSerializedStates.new({ spec: chainSpec, blake2b, dbPath, ephemeral, compression, readOnly: false });
144
+ return new HybridWorkerConfig(nodeName, chainSpec, workerParams, blake2b, dbPath, ephemeral, compression, states);
134
145
  }
135
146
  blocks;
136
- states;
137
- constructor(nodeName, chainSpec, workerParams, blake2b, dbPath, ephemeral, compression = true) {
147
+ constructor(nodeName, chainSpec, workerParams, blake2b, dbPath, ephemeral, compression, states) {
138
148
  this.nodeName = nodeName;
139
149
  this.chainSpec = chainSpec;
140
150
  this.workerParams = workerParams;
@@ -142,22 +152,15 @@ export class HybridWorkerConfig {
142
152
  this.dbPath = dbPath;
143
153
  this.ephemeral = ephemeral;
144
154
  this.compression = compression;
155
+ this.states = states;
145
156
  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
157
  }
155
158
  openDatabase(_options = { readonly: true }) {
156
159
  return {
157
160
  getBlocksDb: () => this.blocks,
158
161
  getStatesDb: () => this.states,
159
- // Leaf sets and blocks live in memory; the LMDB values store is closed
160
- // via states.close() at importer teardown, so this is a no-op.
162
+ // Leaf sets and blocks live in memory; the values store is closed via
163
+ // states.close() at importer teardown, so this is a no-op.
161
164
  close: async () => { },
162
165
  };
163
166
  }
@@ -1,11 +1,12 @@
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";
4
5
  import { codec } from "#@typeberry/codec";
5
6
  import { tinyChainSpec } from "#@typeberry/config";
6
7
  import { Blake2b } from "#@typeberry/hash";
7
8
  import { tryAsU32 } from "#@typeberry/numbers";
8
- import { configTransferList, LmdbWorkerConfig } from "./config.js";
9
+ import { configTransferList, HybridWorkerConfig, LmdbWorkerConfig } from "./config.js";
9
10
  import { ThreadPort } from "./port.js";
10
11
  const spec = tinyChainSpec;
11
12
  describe("LmdbWorkerConfig transfer list", () => {
@@ -39,3 +40,39 @@ describe("LmdbWorkerConfig transfer list", () => {
39
40
  }
40
41
  });
41
42
  });
43
+ describe("HybridWorkerConfig", () => {
44
+ // Both persistent backends must construct asynchronously and hand out a
45
+ // working db. fjall is the experimental backend we want to benchmark.
46
+ for (const backend of ["lmdb", "fjall"]) {
47
+ it(`constructs and opens a ${backend}-backed hybrid db`, async () => {
48
+ const blake2b = await Blake2b.createHasher();
49
+ const dbPath = fs.mkdtempSync(`typeberry-hybrid-${backend}-`);
50
+ try {
51
+ const config = await HybridWorkerConfig.new({
52
+ nodeName: "node",
53
+ chainSpec: spec,
54
+ workerParams: undefined,
55
+ blake2b,
56
+ dbPath,
57
+ ephemeral: true,
58
+ backend,
59
+ });
60
+ const db = config.openDatabase({ readonly: false });
61
+ const states = db.getStatesDb();
62
+ try {
63
+ assert.notStrictEqual(db.getBlocksDb(), undefined);
64
+ assert.notStrictEqual(states, undefined);
65
+ }
66
+ finally {
67
+ // The values store owns the on-disk resources (the no-op db.close()
68
+ // does not), so close it explicitly to release the fjall keyspace.
69
+ await states.close();
70
+ await db.close();
71
+ }
72
+ }
73
+ finally {
74
+ fs.rmSync(dbPath, { recursive: true, force: true });
75
+ }
76
+ });
77
+ }
78
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/block-authorship/main.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAiB3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,KAAK,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAK9E,KAAK,MAAM,GAAG,YAAY,CAAC,qBAAqB,CAAC,CAAC;AAwBlD,wBAAsB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,iBAiapG"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/block-authorship/main.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAkB3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,KAAK,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAM9E,KAAK,MAAM,GAAG,YAAY,CAAC,qBAAqB,CAAC,CAAC;AAwBlD,wBAAsB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,iBAuWpG"}