@typeberry/lib 0.5.7 → 0.5.8-2073cb2

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 (88) hide show
  1. package/package.json +3 -1
  2. package/packages/core/utils/debug.d.ts.map +1 -1
  3. package/packages/core/utils/debug.js +14 -3
  4. package/packages/jam/block/block.d.ts +3 -3
  5. package/packages/jam/block/header.d.ts +6 -6
  6. package/packages/jam/block/test-helpers.d.ts +2 -2
  7. package/packages/jam/block/tickets.d.ts +5 -4
  8. package/packages/jam/block/tickets.d.ts.map +1 -1
  9. package/packages/jam/block/tickets.js +13 -6
  10. package/packages/jam/block-json/block.d.ts +2 -2
  11. package/packages/jam/block-json/block.js +1 -1
  12. package/packages/jam/block-json/common.d.ts +2 -1
  13. package/packages/jam/block-json/common.d.ts.map +1 -1
  14. package/packages/jam/block-json/common.js +2 -5
  15. package/packages/jam/block-json/extrinsic.js +1 -1
  16. package/packages/jam/block-json/header.d.ts +2 -1
  17. package/packages/jam/block-json/header.d.ts.map +1 -1
  18. package/packages/jam/block-json/header.js +34 -32
  19. package/packages/jam/block-json/tickets-extrinsic.d.ts +2 -1
  20. package/packages/jam/block-json/tickets-extrinsic.d.ts.map +1 -1
  21. package/packages/jam/block-json/tickets-extrinsic.js +7 -5
  22. package/packages/jam/fuzz-proto/v1/types.d.ts +1 -1
  23. package/packages/jam/jamnp-s/network.d.ts +2 -0
  24. package/packages/jam/jamnp-s/network.d.ts.map +1 -1
  25. package/packages/jam/jamnp-s/network.js +4 -0
  26. package/packages/jam/jamnp-s/protocol/ce-131-ce-132-safrole-ticket-distribution.d.ts +10 -3
  27. package/packages/jam/jamnp-s/protocol/ce-131-ce-132-safrole-ticket-distribution.d.ts.map +1 -1
  28. package/packages/jam/jamnp-s/protocol/ce-131-ce-132-safrole-ticket-distribution.js +12 -4
  29. package/packages/jam/jamnp-s/protocol/ce-131-ce-132-safrole-ticket-distribution.test.js +4 -3
  30. package/packages/jam/jamnp-s/protocol/up-0-block-announcement.d.ts +1 -1
  31. package/packages/jam/jamnp-s/tasks/ticket-distribution.d.ts +34 -0
  32. package/packages/jam/jamnp-s/tasks/ticket-distribution.d.ts.map +1 -0
  33. package/packages/jam/jamnp-s/tasks/ticket-distribution.js +115 -0
  34. package/packages/jam/jamnp-s/tasks/ticket-distribution.test.d.ts +2 -0
  35. package/packages/jam/jamnp-s/tasks/ticket-distribution.test.d.ts.map +1 -0
  36. package/packages/jam/jamnp-s/tasks/ticket-distribution.test.js +220 -0
  37. package/packages/jam/node/main.d.ts.map +1 -1
  38. package/packages/jam/node/main.js +56 -26
  39. package/packages/jam/node/reader.d.ts +2 -2
  40. package/packages/jam/node/workers.d.ts +32 -25
  41. package/packages/jam/node/workers.d.ts.map +1 -1
  42. package/packages/jam/node/workers.js +16 -7
  43. package/packages/jam/safrole/bandersnatch-vrf.d.ts +3 -2
  44. package/packages/jam/safrole/bandersnatch-vrf.d.ts.map +1 -1
  45. package/packages/jam/safrole/bandersnatch-vrf.js +2 -2
  46. package/packages/jam/safrole/bandersnatch-vrf.test.js +3 -2
  47. package/packages/jam/safrole/safrole.test.js +80 -72
  48. package/packages/jam/state/safrole-data.d.ts +1 -1
  49. package/packages/jam/state/test.utils.js +1 -1
  50. package/packages/jam/state-json/dump.js +2 -2
  51. package/packages/jam/state-json/safrole.d.ts +2 -2
  52. package/packages/jam/state-json/safrole.d.ts.map +1 -1
  53. package/packages/jam/state-json/safrole.js +8 -6
  54. package/packages/jam/state-merkleization/in-memory-state-codec.d.ts +1 -1
  55. package/packages/jam/state-vectors/index.d.ts +8 -7
  56. package/packages/jam/state-vectors/index.d.ts.map +1 -1
  57. package/packages/jam/state-vectors/index.js +6 -4
  58. package/packages/jam/transition/hasher.test.js +1 -1
  59. package/packages/workers/api-node/config.d.ts +5 -1
  60. package/packages/workers/api-node/config.d.ts.map +1 -1
  61. package/packages/workers/api-node/config.js +9 -3
  62. package/packages/workers/api-node/port.d.ts +8 -0
  63. package/packages/workers/api-node/port.d.ts.map +1 -1
  64. package/packages/workers/api-node/port.js +10 -0
  65. package/packages/workers/block-authorship/bootstrap-main.js +10 -3
  66. package/packages/workers/block-authorship/main.d.ts +2 -1
  67. package/packages/workers/block-authorship/main.d.ts.map +1 -1
  68. package/packages/workers/block-authorship/main.js +31 -4
  69. package/packages/workers/block-authorship/protocol.d.ts +4 -4
  70. package/packages/workers/block-authorship/ticket-generator.d.ts +3 -2
  71. package/packages/workers/block-authorship/ticket-generator.d.ts.map +1 -1
  72. package/packages/workers/block-authorship/ticket-generator.js +2 -3
  73. package/packages/workers/block-authorship/ticket-generator.test.js +11 -10
  74. package/packages/workers/comms-authorship-network/index.d.ts +3 -0
  75. package/packages/workers/comms-authorship-network/index.d.ts.map +1 -0
  76. package/packages/workers/comms-authorship-network/index.js +2 -0
  77. package/packages/workers/comms-authorship-network/protocol.d.ts +27 -0
  78. package/packages/workers/comms-authorship-network/protocol.d.ts.map +1 -0
  79. package/packages/workers/comms-authorship-network/protocol.js +24 -0
  80. package/packages/workers/comms-authorship-network/tickets-message.d.ts +18 -0
  81. package/packages/workers/comms-authorship-network/tickets-message.d.ts.map +1 -0
  82. package/packages/workers/comms-authorship-network/tickets-message.js +19 -0
  83. package/packages/workers/importer/protocol.d.ts +8 -8
  84. package/packages/workers/jam-network/bootstrap-main.js +10 -3
  85. package/packages/workers/jam-network/main.d.ts +2 -1
  86. package/packages/workers/jam-network/main.d.ts.map +1 -1
  87. package/packages/workers/jam-network/main.js +8 -1
  88. package/packages/workers/jam-network/protocol.d.ts +10 -10
@@ -3,6 +3,7 @@ import { ChainSpec } from "#@typeberry/config";
3
3
  import { type BlocksDb, type RootDb, type SerializedStatesDb } from "#@typeberry/database";
4
4
  import { Blake2b } from "#@typeberry/hash";
5
5
  import type { WorkerConfig } from "#@typeberry/workers-api";
6
+ import { ThreadPort, type TransferablePort } from "./port.js";
6
7
  /** A worker config that's usable in node.js and uses LMDB database backend. */
7
8
  export declare class LmdbWorkerConfig<T = void> implements WorkerConfig<T, BlocksDb, SerializedStatesDb> {
8
9
  readonly nodeName: string;
@@ -10,12 +11,14 @@ export declare class LmdbWorkerConfig<T = void> implements WorkerConfig<T, Block
10
11
  readonly workerParams: T;
11
12
  readonly dbPath: string;
12
13
  readonly blake2b: Blake2b;
13
- static new<T>({ nodeName, chainSpec, workerParams, dbPath, blake2b, }: {
14
+ readonly ports: Map<string, ThreadPort>;
15
+ static new<T>({ nodeName, chainSpec, workerParams, dbPath, blake2b, ports, }: {
14
16
  nodeName: string;
15
17
  chainSpec: ChainSpec;
16
18
  workerParams: T;
17
19
  dbPath: string;
18
20
  blake2b: Blake2b;
21
+ ports?: Map<string, ThreadPort>;
19
22
  }): LmdbWorkerConfig<T>;
20
23
  /** Restore node config from a transferable config object. */
21
24
  static fromTransferable<T>(decodeParams: Decode<T>, config: TransferableConfig): Promise<LmdbWorkerConfig<T>>;
@@ -32,6 +35,7 @@ export type TransferableConfig = {
32
35
  chainSpec: ChainSpec;
33
36
  workerParams: Uint8Array;
34
37
  dbPath: string;
38
+ workerPorts: [string, TransferablePort][];
35
39
  };
36
40
  /**
37
41
  * In-memory (direct) worker using serialized state database.
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/api-node/config.ts"],"names":[],"mappings":"AAAA,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;AAE3D,+EAA+E;AAC/E,qBAAa,gBAAgB,CAAC,CAAC,GAAG,IAAI,CAAE,YAAW,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,kBAAkB,CAAC;aAiC5E,QAAQ,EAAE,MAAM;aAChB,SAAS,EAAE,SAAS;aACpB,YAAY,EAAE,CAAC;aACf,MAAM,EAAE,MAAM;aACd,OAAO,EAAE,OAAO;IApClC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EACZ,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,MAAM,EACN,OAAO,GACR,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;KAClB;IAID,6DAA6D;WAChD,gBAAgB,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,kBAAkB;IAcpF,OAAO;IAQP,YAAY,CAAC,OAAO,GAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAuB,GAAG,MAAM,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IAUvG,6DAA6D;IAC7D,gBAAgB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,kBAAkB;CAQ7D;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;CAChB,CAAC;AAEF;;;;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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/api-node/config.ts"],"names":[],"mappings":"AAAA,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;aAuC5E,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;IA3ChD,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EACZ,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,MAAM,EACN,OAAO,EACP,KAAiB,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;KACjC;IAID,6DAA6D;WAChD,gBAAgB,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,kBAAkB;IAkBpF,OAAO;IASP,YAAY,CAAC,OAAO,GAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAuB,GAAG,MAAM,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IAUvG,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;;;;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"}
@@ -3,6 +3,7 @@ import { ChainSpec } from "#@typeberry/config";
3
3
  import { InMemoryBlocks, InMemorySerializedStates, } from "#@typeberry/database";
4
4
  import { LmdbBlocks, LmdbRoot, LmdbStates } from "#@typeberry/database-lmdb";
5
5
  import { Blake2b } from "#@typeberry/hash";
6
+ import { ThreadPort } from "./port.js";
6
7
  /** A worker config that's usable in node.js and uses LMDB database backend. */
7
8
  export class LmdbWorkerConfig {
8
9
  nodeName;
@@ -10,28 +11,32 @@ export class LmdbWorkerConfig {
10
11
  workerParams;
11
12
  dbPath;
12
13
  blake2b;
13
- static new({ nodeName, chainSpec, workerParams, dbPath, blake2b, }) {
14
- return new LmdbWorkerConfig(nodeName, chainSpec, workerParams, dbPath, blake2b);
14
+ ports;
15
+ static new({ nodeName, chainSpec, workerParams, dbPath, blake2b, ports = new Map(), }) {
16
+ return new LmdbWorkerConfig(nodeName, chainSpec, workerParams, dbPath, blake2b, ports);
15
17
  }
16
18
  /** Restore node config from a transferable config object. */
17
19
  static async fromTransferable(decodeParams, config) {
18
20
  const blake2b = await Blake2b.createHasher();
19
21
  const chainSpec = new ChainSpec(config.chainSpec);
20
22
  const workerParams = Decoder.decodeObject(decodeParams, config.workerParams, chainSpec);
23
+ const ports = new Map(config.workerPorts.map(([name, port]) => [name, ThreadPort.fromTransferable(chainSpec, port)]));
21
24
  return LmdbWorkerConfig.new({
22
25
  nodeName: config.nodeName,
23
26
  chainSpec,
24
27
  workerParams,
25
28
  dbPath: config.dbPath,
26
29
  blake2b,
30
+ ports,
27
31
  });
28
32
  }
29
- constructor(nodeName, chainSpec, workerParams, dbPath, blake2b) {
33
+ constructor(nodeName, chainSpec, workerParams, dbPath, blake2b, ports) {
30
34
  this.nodeName = nodeName;
31
35
  this.chainSpec = chainSpec;
32
36
  this.workerParams = workerParams;
33
37
  this.dbPath = dbPath;
34
38
  this.blake2b = blake2b;
39
+ this.ports = ports;
35
40
  }
36
41
  openDatabase(options = { readonly: true }) {
37
42
  const lmdb = new LmdbRoot(this.dbPath, options.readonly);
@@ -48,6 +53,7 @@ export class LmdbWorkerConfig {
48
53
  chainSpec: this.chainSpec,
49
54
  workerParams: Encoder.encodeObject(paramsCodec, this.workerParams, this.chainSpec).raw,
50
55
  dbPath: this.dbPath,
56
+ workerPorts: Array.from(this.ports.entries()).map(([name, port]) => [name, port.intoTransferable()]),
51
57
  };
52
58
  }
53
59
  }
@@ -7,12 +7,20 @@ export type Message = {
7
7
  responseId: string;
8
8
  data: Uint8Array;
9
9
  };
10
+ /** Transferable representation of a `ThreadPort`. */
11
+ export type TransferablePort = {
12
+ threadId: number;
13
+ port: MessagePort;
14
+ };
10
15
  export declare class ThreadPort implements Port {
11
16
  private readonly spec;
12
17
  private readonly port;
18
+ static pair(spec: ChainSpec): [ThreadPort, ThreadPort];
13
19
  readonly threadId: number;
14
20
  private readonly events;
15
21
  constructor(spec: ChainSpec, port: MessagePort);
22
+ static fromTransferable(spec: ChainSpec, { port }: TransferablePort): ThreadPort;
23
+ intoTransferable(): TransferablePort;
16
24
  close(): void;
17
25
  private createListener;
18
26
  onClose(callback: (e: Error) => void): void;
@@ -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;AAGnD,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;AAKF,qBAAa,UAAW,YAAW,IAAI;IAKnC,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI;IALvB,SAAgB,QAAQ,SAAY;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;gBAG1B,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,WAAW;IAcpC,KAAK,IAAI,IAAI;IAIb,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;IASvF,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;IASzF,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI;CAWvE"}
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;AAGnD,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;IAWnC,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAXvB,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,GAAG,CAAC,UAAU,EAAE,UAAU,CAAC;IAMtD,SAAgB,QAAQ,SAAY;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;gBAG1B,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,WAAW;IAcpC,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,EAAE,gBAAgB;IAInE,gBAAgB,IAAI,gBAAgB;IAIpC,KAAK,IAAI,IAAI;IAIb,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;IASvF,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;IASzF,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI;CAWvE"}
@@ -8,6 +8,10 @@ const logger = Logger.new(import.meta.filename, "workers/api");
8
8
  export class ThreadPort {
9
9
  spec;
10
10
  port;
11
+ static pair(spec) {
12
+ const { port1, port2 } = new MessageChannel();
13
+ return [new ThreadPort(spec, port1), new ThreadPort(spec, port2)];
14
+ }
11
15
  threadId = threadId;
12
16
  events = new EventEmitter();
13
17
  constructor(spec, port) {
@@ -23,6 +27,12 @@ export class ThreadPort {
23
27
  this.events.emit(eventName, responseId, data);
24
28
  });
25
29
  }
30
+ static fromTransferable(spec, { port }) {
31
+ return new ThreadPort(spec, port);
32
+ }
33
+ intoTransferable() {
34
+ return { threadId: this.threadId, port: this.port };
35
+ }
26
36
  close() {
27
37
  this.port.close();
28
38
  }
@@ -1,12 +1,19 @@
1
+ import { AUTHORSHIP_NETWORK_PORT, protocol as networkProtocol } from "#@typeberry/comms-authorship-network";
1
2
  import { Telemetry } from "#@typeberry/telemetry";
3
+ import { Channel } from "#@typeberry/workers-api";
2
4
  import { initWorker } from "#@typeberry/workers-api-node";
3
5
  import { main } from "./main.js";
4
- import { BlockAuthorshipConfig, protocol } from "./protocol.js";
5
- const { config, comms } = await initWorker(protocol, BlockAuthorshipConfig.Codec);
6
+ import { BlockAuthorshipConfig, protocol as mainProtocol } from "./protocol.js";
7
+ const { config, comms } = await initWorker(mainProtocol, BlockAuthorshipConfig.Codec);
6
8
  // Initialize OpenTelemetry for this worker
7
9
  const tele = Telemetry.initialize({
8
10
  worker: "generator",
9
11
  nodeName: config.nodeName,
10
12
  });
11
- await main(config, comms);
13
+ const port = config.ports.get(AUTHORSHIP_NETWORK_PORT);
14
+ if (port === undefined) {
15
+ throw new Error("Network port not found in config");
16
+ }
17
+ const networkingComms = Channel.tx(networkProtocol, port);
18
+ await main(config, comms, networkingComms);
12
19
  await tele?.close();
@@ -1,6 +1,7 @@
1
+ import type { NetworkingComms } from "#@typeberry/comms-authorship-network";
1
2
  import type { WorkerConfig } from "#@typeberry/workers-api";
2
3
  import type { BlockAuthorshipConfig, GeneratorInternal } from "./protocol.js";
3
4
  type Config = WorkerConfig<BlockAuthorshipConfig>;
4
- export declare function main(config: Config, comms: GeneratorInternal): Promise<void>;
5
+ export declare function main(config: Config, comms: GeneratorInternal, networkingComms: NetworkingComms): Promise<void>;
5
6
  export {};
6
7
  //# sourceMappingURL=main.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/block-authorship/main.ts"],"names":[],"mappings":"AA2BA,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;AAkBlD,wBAAsB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,iBAyMlE"}
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;AAgB3E,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;AAkBlD,wBAAsB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,iBAgPpG"}
@@ -15,7 +15,7 @@ import { asOpaqueType, assertNever, Result } from "#@typeberry/utils";
15
15
  import { Generator } from "./generator.js";
16
16
  import { generateTickets } from "./ticket-generator.js";
17
17
  const logger = Logger.new(import.meta.filename, "author");
18
- export async function main(config, comms) {
18
+ export async function main(config, comms, networkingComms) {
19
19
  await initWasm();
20
20
  logger.info `🎁 Block Authorship running`;
21
21
  const chainSpec = config.chainSpec;
@@ -41,7 +41,15 @@ export async function main(config, comms) {
41
41
  ed25519Secret: secrets.ed25519,
42
42
  ed25519Public: await deriveEd25519PublicKey(secrets.ed25519),
43
43
  })));
44
+ const initialHash = blocks.getBestHeaderHash();
45
+ const initialState = states.getState(initialHash);
44
46
  logger.info `Block authorship validator keys: ${keys.map(({ bandersnatchPublic }, index) => `\n ${index}: ${bandersnatchPublic.toString()}`)}`;
47
+ if (initialState !== null) {
48
+ const initialKeys = await getSealingKeySeries(startTimeSlot % chainSpec.epochLength === 0, startTimeSlot, initialState);
49
+ if (initialKeys.isOk) {
50
+ logEpochBlockCreation(tryAsEpoch(Math.floor(startTimeSlot / chainSpec.epochLength)), initialKeys.ok);
51
+ }
52
+ }
45
53
  function getTime() {
46
54
  const currentTime = process.hrtime.bigint() / 1000000n;
47
55
  const timeFromStart = currentTime - startTime;
@@ -77,6 +85,21 @@ export async function main(config, comms) {
77
85
  const currentEpoch = Math.floor(currentTimeslot / chainSpec.epochLength);
78
86
  return currentEpoch > lastEpoch;
79
87
  }
88
+ function logEpochBlockCreation(epoch, sealingKeySeries) {
89
+ let isCreating = false;
90
+ const epochStart = epoch * chainSpec.epochLength;
91
+ const epochEnd = epochStart + chainSpec.epochLength;
92
+ for (let slot = epochStart; slot < epochEnd; slot++) {
93
+ const key = getKeyForCurrentSlot(sealingKeySeries, keys, tryAsTimeSlot(slot));
94
+ if (key !== null) {
95
+ isCreating = true;
96
+ logger.info `[EPOCH ${epoch}] Validator ${key.bandersnatchPublic.toString()} will author block at slot ${slot}`;
97
+ }
98
+ }
99
+ if (isCreating === false) {
100
+ logger.info `[EPOCH ${epoch}] No blocks to author for this epoch.`;
101
+ }
102
+ }
80
103
  async function getSealingKeySeries(isNewEpoch, timeSlot, state) {
81
104
  if (isNewEpoch) {
82
105
  const safrole = new Safrole(chainSpec, blake2bHasher, state);
@@ -129,13 +152,14 @@ export async function main(config, comms) {
129
152
  // After epoch change, it has been shifted to index 2.
130
153
  const ticketEntropy = isNewEpoch ? state.entropy[1] : state.entropy[2];
131
154
  logger.info `Epoch ${epoch}, slot ${slotInEpoch}/${chainSpec.contestLength}. Generating tickets for ${validatorKeys.length} validators...`;
132
- const ticketsResult = await generateTickets(bandersnatch, ringKeys, validatorKeys, ticketEntropy, chainSpec.ticketsPerValidator);
155
+ const ticketsResult = await generateTickets(bandersnatch, ringKeys, validatorKeys, ticketEntropy, chainSpec.ticketsPerValidator, chainSpec);
133
156
  if (ticketsResult.isError) {
134
157
  logger.warn `Failed to generate tickets for epoch ${epoch}: ${ticketsResult.error}`;
135
158
  }
136
159
  else {
137
- logger.log `Generated ${ticketsResult.ok.length} tickets for epoch ${epoch}.`;
138
- // TODO [MaSi]: Sending out tickets
160
+ logger.log `Generated ${ticketsResult.ok.length} tickets for epoch ${epoch}. Distributing...`;
161
+ // Send directly to network worker (bypasses main thread)
162
+ await networkingComms.sendTickets({ epochIndex: epoch, tickets: ticketsResult.ok });
139
163
  }
140
164
  }
141
165
  ticketsGeneratedForEpoch = epoch;
@@ -144,6 +168,9 @@ export async function main(config, comms) {
144
168
  if (selingKeySeriesResult.isError) {
145
169
  continue;
146
170
  }
171
+ if (isNewEpoch) {
172
+ logEpochBlockCreation(epoch, selingKeySeriesResult.ok);
173
+ }
147
174
  const key = getKeyForCurrentSlot(selingKeySeriesResult.ok, keys, timeSlot);
148
175
  if (key !== null && currentValidatorData !== undefined) {
149
176
  const validatorIndex = getValidatorIndex(key, currentValidatorData);
@@ -28,7 +28,7 @@ export declare const protocol: import("@typeberry/workers-api").LousyProtocol<{
28
28
  ticketsMarker: import("@typeberry/codec").Descriptor<import("@typeberry/block").TicketsMarker | null, import("@typeberry/codec").ViewOf<import("@typeberry/block").TicketsMarker, {
29
29
  tickets: import("@typeberry/codec").Descriptor<readonly import("@typeberry/block").Ticket[] & import("@typeberry/utils").WithOpaque<"EpochLength">, import("@typeberry/codec").SequenceView<import("@typeberry/block").Ticket, import("@typeberry/codec").ViewOf<import("@typeberry/block").Ticket, {
30
30
  id: import("@typeberry/codec").Descriptor<import("@typeberry/bytes").Bytes<32>, import("@typeberry/bytes").Bytes<32>>;
31
- attempt: import("@typeberry/codec").Descriptor<number & import("@typeberry/numbers").WithBytesRepresentation<1> & import("@typeberry/utils").WithOpaque<"TicketAttempt[0|1|2]">, import("@typeberry/numbers").U8>;
31
+ attempt: import("@typeberry/codec").Descriptor<number & import("@typeberry/numbers").WithBytesRepresentation<1> & import("@typeberry/utils").WithOpaque<"TicketAttempt[0|1|2]">, import("@typeberry/numbers").U32>;
32
32
  }>>>;
33
33
  }> | null>;
34
34
  bandersnatchBlockAuthorIndex: import("@typeberry/codec").Descriptor<number & import("@typeberry/numbers").WithBytesRepresentation<2> & import("@typeberry/utils").WithOpaque<"ValidatorIndex[u16]">, import("@typeberry/bytes").Bytes<2>>;
@@ -38,7 +38,7 @@ export declare const protocol: import("@typeberry/workers-api").LousyProtocol<{
38
38
  }>>;
39
39
  extrinsic: import("@typeberry/codec").Descriptor<import("@typeberry/block").Extrinsic, import("@typeberry/codec").ViewOf<import("@typeberry/block").Extrinsic, {
40
40
  tickets: import("@typeberry/codec").Descriptor<readonly import("@typeberry/block").SignedTicket[] & import("@typeberry/utils").WithOpaque<"Size: [0..chainSpec.maxTicketsPerExtrinsic)">, import("@typeberry/codec").SequenceView<import("@typeberry/block").SignedTicket, import("@typeberry/codec").ViewOf<import("@typeberry/block").SignedTicket, {
41
- attempt: import("@typeberry/codec").Descriptor<number & import("@typeberry/numbers").WithBytesRepresentation<1> & import("@typeberry/utils").WithOpaque<"TicketAttempt[0|1|2]">, import("@typeberry/numbers").U8>;
41
+ attempt: import("@typeberry/codec").Descriptor<number & import("@typeberry/numbers").WithBytesRepresentation<1> & import("@typeberry/utils").WithOpaque<"TicketAttempt[0|1|2]">, import("@typeberry/numbers").U32>;
42
42
  signature: import("@typeberry/codec").Descriptor<import("@typeberry/bytes").Bytes<784> & import("@typeberry/utils").WithOpaque<"BandersnatchRingSignature">, import("@typeberry/bytes").Bytes<784>>;
43
43
  }>>>;
44
44
  preimages: import("@typeberry/codec").Descriptor<import("@typeberry/block").Preimage[], import("@typeberry/codec").SequenceView<import("@typeberry/block").Preimage, import("@typeberry/codec").ViewOf<import("@typeberry/block").Preimage, {
@@ -152,7 +152,7 @@ export declare const protocol: import("@typeberry/workers-api").LousyProtocol<{
152
152
  ticketsMarker: import("@typeberry/codec").Descriptor<import("@typeberry/block").TicketsMarker | null, import("@typeberry/codec").ViewOf<import("@typeberry/block").TicketsMarker, {
153
153
  tickets: import("@typeberry/codec").Descriptor<readonly import("@typeberry/block").Ticket[] & import("@typeberry/utils").WithOpaque<"EpochLength">, import("@typeberry/codec").SequenceView<import("@typeberry/block").Ticket, import("@typeberry/codec").ViewOf<import("@typeberry/block").Ticket, {
154
154
  id: import("@typeberry/codec").Descriptor<import("@typeberry/bytes").Bytes<32>, import("@typeberry/bytes").Bytes<32>>;
155
- attempt: import("@typeberry/codec").Descriptor<number & import("@typeberry/numbers").WithBytesRepresentation<1> & import("@typeberry/utils").WithOpaque<"TicketAttempt[0|1|2]">, import("@typeberry/numbers").U8>;
155
+ attempt: import("@typeberry/codec").Descriptor<number & import("@typeberry/numbers").WithBytesRepresentation<1> & import("@typeberry/utils").WithOpaque<"TicketAttempt[0|1|2]">, import("@typeberry/numbers").U32>;
156
156
  }>>>;
157
157
  }> | null>;
158
158
  bandersnatchBlockAuthorIndex: import("@typeberry/codec").Descriptor<number & import("@typeberry/numbers").WithBytesRepresentation<2> & import("@typeberry/utils").WithOpaque<"ValidatorIndex[u16]">, import("@typeberry/bytes").Bytes<2>>;
@@ -162,7 +162,7 @@ export declare const protocol: import("@typeberry/workers-api").LousyProtocol<{
162
162
  }>>;
163
163
  extrinsic: import("@typeberry/codec").Descriptor<import("@typeberry/block").Extrinsic, import("@typeberry/codec").ViewOf<import("@typeberry/block").Extrinsic, {
164
164
  tickets: import("@typeberry/codec").Descriptor<readonly import("@typeberry/block").SignedTicket[] & import("@typeberry/utils").WithOpaque<"Size: [0..chainSpec.maxTicketsPerExtrinsic)">, import("@typeberry/codec").SequenceView<import("@typeberry/block").SignedTicket, import("@typeberry/codec").ViewOf<import("@typeberry/block").SignedTicket, {
165
- attempt: import("@typeberry/codec").Descriptor<number & import("@typeberry/numbers").WithBytesRepresentation<1> & import("@typeberry/utils").WithOpaque<"TicketAttempt[0|1|2]">, import("@typeberry/numbers").U8>;
165
+ attempt: import("@typeberry/codec").Descriptor<number & import("@typeberry/numbers").WithBytesRepresentation<1> & import("@typeberry/utils").WithOpaque<"TicketAttempt[0|1|2]">, import("@typeberry/numbers").U32>;
166
166
  signature: import("@typeberry/codec").Descriptor<import("@typeberry/bytes").Bytes<784> & import("@typeberry/utils").WithOpaque<"BandersnatchRingSignature">, import("@typeberry/bytes").Bytes<784>>;
167
167
  }>>>;
168
168
  preimages: import("@typeberry/codec").Descriptor<import("@typeberry/block").Preimage[], import("@typeberry/codec").SequenceView<import("@typeberry/block").Preimage, import("@typeberry/codec").ViewOf<import("@typeberry/block").Preimage, {
@@ -1,5 +1,6 @@
1
1
  import type { EntropyHash } from "#@typeberry/block";
2
- import { type SignedTicket } from "#@typeberry/block/tickets.js";
2
+ import type { SignedTicket } from "#@typeberry/block/tickets.js";
3
+ import type { ChainSpec } from "#@typeberry/config";
3
4
  import type { BandersnatchKey, BandersnatchSecretSeed } from "#@typeberry/crypto";
4
5
  import type { BandernsatchWasm } from "#@typeberry/safrole/bandersnatch-wasm.js";
5
6
  import { Result } from "#@typeberry/utils";
@@ -17,5 +18,5 @@ export type ValidatorKey = {
17
18
  * Each validator key produces `ticketsPerValidator` tickets using ring VRF proofs.
18
19
  * The ring keys define the anonymous set - only members can produce valid proofs.
19
20
  */
20
- export declare function generateTickets(bandersnatch: BandernsatchWasm, ringKeys: BandersnatchKey[], validatorKeys: ValidatorKey[], entropy: EntropyHash, ticketsPerValidator: number): Promise<Result<SignedTicket[], TicketGeneratorError>>;
21
+ export declare function generateTickets(bandersnatch: BandernsatchWasm, ringKeys: BandersnatchKey[], validatorKeys: ValidatorKey[], entropy: EntropyHash, ticketsPerValidator: number, chainSpec: ChainSpec): Promise<Result<SignedTicket[], TicketGeneratorError>>;
21
22
  //# sourceMappingURL=ticket-generator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ticket-generator.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/block-authorship/ticket-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,6BAA6B,CAAC;AACpF,OAAO,KAAK,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAGjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAChF,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAI1C,oBAAY,oBAAoB;IAC9B,sBAAsB,2BAA2B;IACjD,kBAAkB,uBAAuB;CAC1C;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,sBAAsB,CAAC;IAC/B,MAAM,EAAE,eAAe,CAAC;CACzB,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,YAAY,EAAE,gBAAgB,EAC9B,QAAQ,EAAE,eAAe,EAAE,EAC3B,aAAa,EAAE,YAAY,EAAE,EAC7B,OAAO,EAAE,WAAW,EACpB,mBAAmB,EAAE,MAAM,GAC1B,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,EAAE,oBAAoB,CAAC,CAAC,CAkCvD"}
1
+ {"version":3,"file":"ticket-generator.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/block-authorship/ticket-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAGjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAChF,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAI1C,oBAAY,oBAAoB;IAC9B,sBAAsB,2BAA2B;IACjD,kBAAkB,uBAAuB;CAC1C;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,sBAAsB,CAAC;IAC/B,MAAM,EAAE,eAAe,CAAC;CACzB,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,YAAY,EAAE,gBAAgB,EAC9B,QAAQ,EAAE,eAAe,EAAE,EAC3B,aAAa,EAAE,YAAY,EAAE,EAC7B,OAAO,EAAE,WAAW,EACpB,mBAAmB,EAAE,MAAM,EAC3B,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,EAAE,oBAAoB,CAAC,CAAC,CAmCvD"}
@@ -1,4 +1,3 @@
1
- import { tryAsTicketAttempt } from "#@typeberry/block/tickets.js";
2
1
  import { Logger } from "#@typeberry/logger";
3
2
  import bandersnatchVrf from "#@typeberry/safrole/bandersnatch-vrf.js";
4
3
  import { Result } from "#@typeberry/utils";
@@ -14,7 +13,7 @@ export var TicketGeneratorError;
14
13
  * Each validator key produces `ticketsPerValidator` tickets using ring VRF proofs.
15
14
  * The ring keys define the anonymous set - only members can produce valid proofs.
16
15
  */
17
- export async function generateTickets(bandersnatch, ringKeys, validatorKeys, entropy, ticketsPerValidator) {
16
+ export async function generateTickets(bandersnatch, ringKeys, validatorKeys, entropy, ticketsPerValidator, chainSpec) {
18
17
  const allTickets = [];
19
18
  for (const validatorKey of validatorKeys) {
20
19
  const proverIndex = ringKeys.findIndex((k) => k.isEqualTo(validatorKey.public));
@@ -22,7 +21,7 @@ export async function generateTickets(bandersnatch, ringKeys, validatorKeys, ent
22
21
  logger.warn `Validator public key not found in the ring, skipping ticket generation for this key`;
23
22
  continue;
24
23
  }
25
- const ticketResult = await bandersnatchVrf.generateTickets(bandersnatch, ringKeys, proverIndex, validatorKey.secret, entropy, tryAsTicketAttempt(ticketsPerValidator));
24
+ const ticketResult = await bandersnatchVrf.generateTickets(bandersnatch, ringKeys, proverIndex, validatorKey.secret, entropy, ticketsPerValidator, chainSpec);
26
25
  if (ticketResult.isOk) {
27
26
  allTickets.push(...ticketResult.ok);
28
27
  }
@@ -2,6 +2,7 @@ import assert from "node:assert";
2
2
  import { afterEach, beforeEach, describe, it, mock } from "node:test";
3
3
  import { tryAsTicketAttempt } from "#@typeberry/block/tickets.js";
4
4
  import { Bytes } from "#@typeberry/bytes";
5
+ import { tinyChainSpec } from "#@typeberry/config";
5
6
  import { BANDERSNATCH_KEY_BYTES, initWasm, SEED_SIZE } from "#@typeberry/crypto";
6
7
  import { HASH_SIZE } from "#@typeberry/hash";
7
8
  import bandersnatchVrf from "#@typeberry/safrole/bandersnatch-vrf.js";
@@ -25,7 +26,7 @@ describe("Ticket Generator", () => {
25
26
  const tickets = [];
26
27
  for (let attempt = 0; attempt < ticketsPerValidator; attempt++) {
27
28
  tickets.push({
28
- attempt: tryAsTicketAttempt(attempt),
29
+ attempt: tryAsTicketAttempt(attempt, tinyChainSpec),
29
30
  signature: Bytes.zero(784).asOpaque(),
30
31
  });
31
32
  }
@@ -40,7 +41,7 @@ describe("Ticket Generator", () => {
40
41
  const ringKeys = createMockRingKeys(3);
41
42
  const validatorKeys = createMockValidatorKeys(3);
42
43
  const ticketsPerValidator = 2;
43
- const result = await generateTickets(MOCK_BANDERSNATCH, ringKeys, validatorKeys, MOCK_ENTROPY, ticketsPerValidator);
44
+ const result = await generateTickets(MOCK_BANDERSNATCH, ringKeys, validatorKeys, MOCK_ENTROPY, ticketsPerValidator, tinyChainSpec);
44
45
  assert.ok(result.isOk);
45
46
  assert.strictEqual(result.ok.length, 6);
46
47
  });
@@ -48,18 +49,18 @@ describe("Ticket Generator", () => {
48
49
  const ringKeys = createMockRingKeys(2);
49
50
  const validatorKeys = createMockValidatorKeys(2);
50
51
  const ticketsPerValidator = 2;
51
- const result = await generateTickets(MOCK_BANDERSNATCH, ringKeys, validatorKeys, MOCK_ENTROPY, ticketsPerValidator);
52
+ const result = await generateTickets(MOCK_BANDERSNATCH, ringKeys, validatorKeys, MOCK_ENTROPY, ticketsPerValidator, tinyChainSpec);
52
53
  assert.ok(result.isOk);
53
54
  const tickets = result.ok;
54
- assert.strictEqual(tickets[0].attempt, tryAsTicketAttempt(0));
55
- assert.strictEqual(tickets[1].attempt, tryAsTicketAttempt(1));
56
- assert.strictEqual(tickets[2].attempt, tryAsTicketAttempt(0));
57
- assert.strictEqual(tickets[3].attempt, tryAsTicketAttempt(1));
55
+ assert.strictEqual(tickets[0].attempt, tryAsTicketAttempt(0, tinyChainSpec));
56
+ assert.strictEqual(tickets[1].attempt, tryAsTicketAttempt(1, tinyChainSpec));
57
+ assert.strictEqual(tickets[2].attempt, tryAsTicketAttempt(0, tinyChainSpec));
58
+ assert.strictEqual(tickets[3].attempt, tryAsTicketAttempt(1, tinyChainSpec));
58
59
  });
59
60
  it("should return empty array for no validator keys", async () => {
60
61
  const ringKeys = createMockRingKeys(3);
61
62
  const ticketsPerValidator = 2;
62
- const result = await generateTickets(MOCK_BANDERSNATCH, ringKeys, [], MOCK_ENTROPY, ticketsPerValidator);
63
+ const result = await generateTickets(MOCK_BANDERSNATCH, ringKeys, [], MOCK_ENTROPY, ticketsPerValidator, tinyChainSpec);
63
64
  assert.ok(result.isOk);
64
65
  assert.strictEqual(result.ok.length, 0);
65
66
  });
@@ -74,7 +75,7 @@ describe("Ticket Generator", () => {
74
75
  },
75
76
  ];
76
77
  const validatorKeys = [...correctValidatorKeys, ...incorrectValidatorKeys];
77
- const result = await generateTickets(MOCK_BANDERSNATCH, ringKeys, validatorKeys, MOCK_ENTROPY, ticketsPerValidator);
78
+ const result = await generateTickets(MOCK_BANDERSNATCH, ringKeys, validatorKeys, MOCK_ENTROPY, ticketsPerValidator, tinyChainSpec);
78
79
  assert.ok(result.isOk);
79
80
  // Only the 2 valid validators should produce tickets
80
81
  assert.strictEqual(result.ok.length, 4);
@@ -92,7 +93,7 @@ describe("Ticket Generator", () => {
92
93
  public: Bytes.fill(BANDERSNATCH_KEY_BYTES, 98).asOpaque(),
93
94
  },
94
95
  ];
95
- const result = await generateTickets(MOCK_BANDERSNATCH, ringKeys, invalidValidatorKeys, MOCK_ENTROPY, ticketsPerValidator);
96
+ const result = await generateTickets(MOCK_BANDERSNATCH, ringKeys, invalidValidatorKeys, MOCK_ENTROPY, ticketsPerValidator, tinyChainSpec);
96
97
  assert.ok(result.isError);
97
98
  assert.strictEqual(result.error, TicketGeneratorError.TicketGenerationFailed);
98
99
  });
@@ -0,0 +1,3 @@
1
+ export * from "./protocol.js";
2
+ export * from "./tickets-message.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/comms-authorship-network/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from "./protocol.js";
2
+ export * from "./tickets-message.js";
@@ -0,0 +1,27 @@
1
+ import { type Api, type Internal } from "#@typeberry/workers-api";
2
+ import { TicketsMessage } from "./tickets-message.js";
3
+ /**
4
+ * Port name for authorship-network direct communication.
5
+ * Used when spawning jam-network worker to pass the port for receiving tickets.
6
+ */
7
+ export declare const AUTHORSHIP_NETWORK_PORT = "authorship-network";
8
+ /**
9
+ * Protocol for direct communication between block-authorship and jam-network workers.
10
+ *
11
+ * This bypasses the main thread for ticket distribution, reducing latency.
12
+ */
13
+ export declare const protocol: import("@typeberry/workers-api").LousyProtocol<{
14
+ tickets: {
15
+ request: import("@typeberry/codec").Descriptor<TicketsMessage, import("@typeberry/codec").ViewOf<TicketsMessage, {
16
+ epochIndex: import("@typeberry/codec").Descriptor<number & import("@typeberry/numbers").WithBytesRepresentation<4> & import("@typeberry/utils").WithOpaque<"Epoch">, import("@typeberry/bytes").Bytes<4>>;
17
+ tickets: import("@typeberry/codec").Descriptor<import("@typeberry/block").SignedTicket[], import("@typeberry/codec").SequenceView<import("@typeberry/block").SignedTicket, import("@typeberry/codec").ViewOf<import("@typeberry/block").SignedTicket, {
18
+ attempt: import("@typeberry/codec").Descriptor<number & import("@typeberry/numbers").WithBytesRepresentation<1> & import("@typeberry/utils").WithOpaque<"TicketAttempt[0|1|2]">, import("@typeberry/numbers").U32>;
19
+ signature: import("@typeberry/codec").Descriptor<import("@typeberry/bytes").Bytes<784> & import("@typeberry/utils").WithOpaque<"BandersnatchRingSignature">, import("@typeberry/bytes").Bytes<784>>;
20
+ }>>>;
21
+ }>>;
22
+ response: import("@typeberry/codec").Descriptor<void, void>;
23
+ };
24
+ }, {}>;
25
+ export type NetworkingComms = Api<typeof protocol>;
26
+ export type AuthorshipComms = Internal<typeof protocol>;
27
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/comms-authorship-network/protocol.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,GAAG,EAAkB,KAAK,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD;;;GAGG;AACH,eAAO,MAAM,uBAAuB,uBAAuB,CAAC;AAE5D;;;;GAIG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;MAUnB,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC;AACnD,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC,OAAO,QAAQ,CAAC,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { codec } from "#@typeberry/codec";
2
+ import { createProtocol } from "#@typeberry/workers-api";
3
+ import { TicketsMessage } from "./tickets-message.js";
4
+ /**
5
+ * Port name for authorship-network direct communication.
6
+ * Used when spawning jam-network worker to pass the port for receiving tickets.
7
+ */
8
+ export const AUTHORSHIP_NETWORK_PORT = "authorship-network";
9
+ /**
10
+ * Protocol for direct communication between block-authorship and jam-network workers.
11
+ *
12
+ * This bypasses the main thread for ticket distribution, reducing latency.
13
+ */
14
+ export const protocol = createProtocol("authorship-network", {
15
+ // Messages from block-authorship to jam-network
16
+ toWorker: {
17
+ tickets: {
18
+ request: TicketsMessage.Codec,
19
+ response: codec.nothing,
20
+ },
21
+ },
22
+ // Messages from jam-network to block-authorship (none for now)
23
+ fromWorker: {},
24
+ });
@@ -0,0 +1,18 @@
1
+ import type { Epoch } from "#@typeberry/block";
2
+ import { SignedTicket } from "#@typeberry/block/tickets.js";
3
+ import { type CodecRecord } from "#@typeberry/codec";
4
+ import { WithDebug } from "#@typeberry/utils";
5
+ export declare class TicketsMessage extends WithDebug {
6
+ readonly epochIndex: Epoch;
7
+ readonly tickets: SignedTicket[];
8
+ static Codec: import("@typeberry/codec").Descriptor<TicketsMessage, import("@typeberry/codec").ViewOf<TicketsMessage, {
9
+ epochIndex: import("@typeberry/codec").Descriptor<number & import("@typeberry/numbers").WithBytesRepresentation<4> & import("@typeberry/utils").WithOpaque<"Epoch">, import("@typeberry/bytes").Bytes<4>>;
10
+ tickets: import("@typeberry/codec").Descriptor<SignedTicket[], import("@typeberry/codec").SequenceView<SignedTicket, import("@typeberry/codec").ViewOf<SignedTicket, {
11
+ attempt: import("@typeberry/codec").Descriptor<number & import("@typeberry/numbers").WithBytesRepresentation<1> & import("@typeberry/utils").WithOpaque<"TicketAttempt[0|1|2]">, import("@typeberry/numbers").U32>;
12
+ signature: import("@typeberry/codec").Descriptor<import("@typeberry/bytes").Bytes<784> & import("@typeberry/utils").WithOpaque<"BandersnatchRingSignature">, import("@typeberry/bytes").Bytes<784>>;
13
+ }>>>;
14
+ }>>;
15
+ static create({ epochIndex, tickets }: CodecRecord<TicketsMessage>): TicketsMessage;
16
+ private constructor();
17
+ }
18
+ //# sourceMappingURL=tickets-message.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tickets-message.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/comms-authorship-network/tickets-message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,KAAK,WAAW,EAAS,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,qBAAa,cAAe,SAAQ,SAAS;aAWzB,UAAU,EAAE,KAAK;aACjB,OAAO,EAAE,YAAY,EAAE;IAXzC,MAAM,CAAC,KAAK;;;;;;QAGT;IAEH,MAAM,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,WAAW,CAAC,cAAc,CAAC;IAIlE,OAAO;CAMR"}
@@ -0,0 +1,19 @@
1
+ import { SignedTicket } from "#@typeberry/block/tickets.js";
2
+ import { codec } from "#@typeberry/codec";
3
+ import { WithDebug } from "#@typeberry/utils";
4
+ export class TicketsMessage extends WithDebug {
5
+ epochIndex;
6
+ tickets;
7
+ static Codec = codec.Class(TicketsMessage, {
8
+ epochIndex: codec.u32.asOpaque(),
9
+ tickets: codec.sequenceVarLen(SignedTicket.Codec),
10
+ });
11
+ static create({ epochIndex, tickets }) {
12
+ return new TicketsMessage(epochIndex, tickets);
13
+ }
14
+ constructor(epochIndex, tickets) {
15
+ super();
16
+ this.epochIndex = epochIndex;
17
+ this.tickets = tickets;
18
+ }
19
+ }