@typeberry/lib 0.8.4-faebc7a → 0.9.0-c9f9e4d

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 (90) hide show
  1. package/package.json +1 -1
  2. package/packages/configs/index.d.ts +30 -1
  3. package/packages/configs/index.d.ts.map +1 -1
  4. package/packages/configs/index.js +4 -2
  5. package/packages/configs/typeberry-dev-full.json +29 -0
  6. package/packages/core/bytes/bytes.d.ts +1 -0
  7. package/packages/core/bytes/bytes.d.ts.map +1 -1
  8. package/packages/core/bytes/bytes.js +8 -0
  9. package/packages/core/utils/debug.d.ts +4 -2
  10. package/packages/core/utils/debug.d.ts.map +1 -1
  11. package/packages/core/utils/debug.js +18 -13
  12. package/packages/core/utils/debug.test.js +12 -6
  13. package/packages/jam/config-node/node-config.d.ts +2 -1
  14. package/packages/jam/config-node/node-config.d.ts.map +1 -1
  15. package/packages/jam/config-node/node-config.js +8 -3
  16. package/packages/jam/config-node/node-config.test.js +3 -3
  17. package/packages/jam/jamnp-s/tasks/ticket-distribution.js +1 -1
  18. package/packages/jam/safrole/bandersnatch-vrf.d.ts +22 -2
  19. package/packages/jam/safrole/bandersnatch-vrf.d.ts.map +1 -1
  20. package/packages/jam/safrole/bandersnatch-vrf.js +54 -20
  21. package/packages/jam/safrole/bandersnatch-vrf.test.js +3 -2
  22. package/packages/jam/safrole/bandersnatch-wasm.d.ts +10 -0
  23. package/packages/jam/safrole/bandersnatch-wasm.d.ts.map +1 -1
  24. package/packages/jam/safrole/bandersnatch-wasm.js +12 -0
  25. package/packages/jam/ticket-pool/ticket-validator.d.ts +5 -4
  26. package/packages/jam/ticket-pool/ticket-validator.d.ts.map +1 -1
  27. package/packages/jam/ticket-pool/ticket-validator.js +8 -3
  28. package/packages/jam/ticket-pool/ticket-validator.test.js +5 -4
  29. package/packages/jam/ticket-pool/verified-ticket-pool.d.ts +2 -0
  30. package/packages/jam/ticket-pool/verified-ticket-pool.d.ts.map +1 -1
  31. package/packages/jam/ticket-pool/verified-ticket-pool.js +4 -0
  32. package/packages/jam/ticket-pool/verified-ticket-pool.test.js +5 -5
  33. package/packages/workers/block-authorship/{generator.d.ts → block-generator.d.ts} +5 -5
  34. package/packages/workers/block-authorship/block-generator.d.ts.map +1 -0
  35. package/packages/workers/block-authorship/{generator.js → block-generator.js} +3 -3
  36. package/packages/workers/block-authorship/block-generator.test.d.ts +2 -0
  37. package/packages/workers/block-authorship/block-generator.test.d.ts.map +1 -0
  38. package/packages/workers/block-authorship/{generator.test.js → block-generator.test.js} +8 -8
  39. package/packages/workers/block-authorship/epoch-authoring-slots.d.ts +35 -0
  40. package/packages/workers/block-authorship/epoch-authoring-slots.d.ts.map +1 -0
  41. package/packages/workers/block-authorship/epoch-authoring-slots.js +86 -0
  42. package/packages/workers/block-authorship/epoch-tracker.d.ts +29 -0
  43. package/packages/workers/block-authorship/epoch-tracker.d.ts.map +1 -0
  44. package/packages/workers/block-authorship/epoch-tracker.js +80 -0
  45. package/packages/workers/block-authorship/index.d.ts.map +1 -1
  46. package/packages/workers/block-authorship/index.js +1 -1
  47. package/packages/workers/block-authorship/main.d.ts +3 -0
  48. package/packages/workers/block-authorship/main.d.ts.map +1 -1
  49. package/packages/workers/block-authorship/main.js +193 -261
  50. package/packages/workers/block-authorship/ticket-generator/bootstrap-main.d.ts +2 -0
  51. package/packages/workers/block-authorship/ticket-generator/bootstrap-main.d.ts.map +1 -0
  52. package/packages/workers/block-authorship/ticket-generator/bootstrap-main.js +23 -0
  53. package/packages/workers/block-authorship/ticket-generator/index.d.ts +16 -0
  54. package/packages/workers/block-authorship/ticket-generator/index.d.ts.map +1 -0
  55. package/packages/workers/block-authorship/ticket-generator/index.js +62 -0
  56. package/packages/workers/block-authorship/ticket-generator/protocol.d.ts +50 -0
  57. package/packages/workers/block-authorship/ticket-generator/protocol.d.ts.map +1 -0
  58. package/packages/workers/block-authorship/ticket-generator/protocol.js +54 -0
  59. package/packages/workers/block-authorship/{ticket-generator.d.ts → ticket-generator/ticket-generator.d.ts} +4 -0
  60. package/packages/workers/block-authorship/ticket-generator/ticket-generator.d.ts.map +1 -0
  61. package/packages/workers/block-authorship/{ticket-generator.js → ticket-generator/ticket-generator.js} +19 -9
  62. package/packages/workers/block-authorship/ticket-generator/ticket-generator.test.d.ts.map +1 -0
  63. package/packages/workers/block-authorship/{ticket-generator.test.js → ticket-generator/ticket-generator.test.js} +13 -9
  64. package/packages/workers/block-authorship/ticket-generator/worker-pool.d.ts +36 -0
  65. package/packages/workers/block-authorship/ticket-generator/worker-pool.d.ts.map +1 -0
  66. package/packages/workers/block-authorship/ticket-generator/worker-pool.js +111 -0
  67. package/packages/workers/block-authorship/ticket-validator.d.ts +7 -8
  68. package/packages/workers/block-authorship/ticket-validator.d.ts.map +1 -1
  69. package/packages/workers/block-authorship/ticket-validator.js +26 -23
  70. package/packages/workers/comms-authorship-network/protocol.d.ts +4 -4
  71. package/packages/workers/comms-authorship-network/protocol.d.ts.map +1 -1
  72. package/packages/workers/comms-authorship-network/protocol.js +4 -5
  73. package/packages/workers/comms-authorship-network/tickets-message.d.ts +0 -14
  74. package/packages/workers/comms-authorship-network/tickets-message.d.ts.map +1 -1
  75. package/packages/workers/comms-authorship-network/tickets-message.js +0 -17
  76. package/packages/workers/importer/importer.d.ts +2 -2
  77. package/packages/workers/importer/importer.d.ts.map +1 -1
  78. package/packages/workers/importer/importer.js +5 -5
  79. package/packages/workers/importer/stats.d.ts +1 -3
  80. package/packages/workers/importer/stats.d.ts.map +1 -1
  81. package/packages/workers/importer/stats.js +12 -12
  82. package/packages/workers/jam-network/main.d.ts.map +1 -1
  83. package/packages/workers/jam-network/main.js +8 -3
  84. package/packages/workers/block-authorship/generator.d.ts.map +0 -1
  85. package/packages/workers/block-authorship/generator.test.d.ts +0 -2
  86. package/packages/workers/block-authorship/generator.test.d.ts.map +0 -1
  87. package/packages/workers/block-authorship/ticket-generator.d.ts.map +0 -1
  88. package/packages/workers/block-authorship/ticket-generator.test.d.ts.map +0 -1
  89. /package/packages/configs/{typeberry-dev.json → typeberry-dev-tiny.json} +0 -0
  90. /package/packages/workers/block-authorship/{ticket-generator.test.d.ts → ticket-generator/ticket-generator.test.d.ts} +0 -0
@@ -71,6 +71,7 @@ export declare class Bytes<T extends number> extends BytesBlob {
71
71
  isEqualTo(other: Bytes<T>): boolean;
72
72
  /** Converts current type into some opaque extension. */
73
73
  asOpaque<R>(): Opaque<Bytes<T>, TokenOf<R, Bytes<T>>>;
74
+ toStringTruncated(): string;
74
75
  }
75
76
  export declare const bytesBlobComparator: Comparator<BytesBlob>;
76
77
  //# sourceMappingURL=bytes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["../../../../../packages/core/bytes/bytes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["../../../../../packages/core/bytes/bytes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAGL,KAAK,MAAM,EAEX,kBAAkB,EAClB,KAAK,OAAO,EACb,MAAM,kBAAkB,CAAC;AAG1B;;;;;GAKG;AACH,qBAAa,SAAS;IACpB,CAAC,kBAAkB,CAAC;IAIpB,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAK;IAE5B,SAAS,aAAa,IAAI,EAAE,UAAU;IAKtC;;OAEG;IACH,QAAQ;IAIR,oFAAoF;IACpF,iBAAiB;IAUjB,MAAM;IAIN,wCAAwC;IACxC,MAAM;IAKN,2CAA2C;IAC3C,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO;IAQpC;;;OAGG;IACI,OAAO,CAAC,KAAK,EAAE,SAAS;IA0B/B,+CAA+C;IAC/C,MAAM,CAAC,KAAK,IAAI,SAAS;IAIzB,sFAAsF;IACtF,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS;IAK3C,+DAA+D;IAC/D,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,UAAU,GAAG,SAAS;IAIzC,oFAAoF;IACpF,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,UAAU,GAAG,UAAU,EAAE,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE;IAgBxE,yDAAyD;IACzD,MAAM,CAAC,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS;IAM9C,0DAA0D;IAC1D,MAAM,CAAC,iBAAiB,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS;IAe9C,uDAAuD;IACvD,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS;IAOtC;;;;OAIG;IACF,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC;CAK7D;AAED;;GAEG;AACH,qBAAa,KAAK,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,SAAS;IACpD,iCAAiC;IACjC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAEnB,OAAO;IAMP,sEAAsE;IACtE,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IAIlE,uEAAuE;IACvE,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IAMnE,oDAAoD;IACpD,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IAK/C,2EAA2E;IAC3E,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC;IAO9D,kEAAkE;IAClE,MAAM,CAAC,kBAAkB,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IASxE,+DAA+D;IAC/D,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IAShE,2CAA2C;IAC3C,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,OAAO;IAKnC,wDAAwD;IACxD,QAAQ,CAAC,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAIrD,iBAAiB;CAQlB;AA0DD,eAAO,MAAM,mBAAmB,EAAE,UAAU,CAAC,SAAS,CAAqD,CAAC"}
@@ -197,6 +197,14 @@ export class Bytes extends BytesBlob {
197
197
  asOpaque() {
198
198
  return asOpaqueType(this);
199
199
  }
200
+ toStringTruncated() {
201
+ if (this.raw.length > 8) {
202
+ const start = bytesToHexString(this.raw.subarray(0, 2));
203
+ const end = bytesToHexString(this.raw.subarray(this.raw.length - 2));
204
+ return `${start}...${end.substring(2)}`;
205
+ }
206
+ return `${this.toString()}`;
207
+ }
200
208
  }
201
209
  function byteFromString(s) {
202
210
  check `${s.length === 2} Two-character string expected`;
@@ -59,9 +59,11 @@ export declare function measure(id: string): () => {
59
59
  * `arrayBuffers` should allow tracking WASM memory, since every instance backs its
60
60
  * memory with `ArrayBuffer`.
61
61
  */
62
- export declare function memoryUsage(): string;
62
+ export declare function memoryUsage(withDetails: boolean): string;
63
63
  /** Create a stateful memory usage reporter. */
64
- export declare function memoryTracker(): () => string;
64
+ export declare function memoryTracker(withDetails: boolean): {
65
+ toString(): string;
66
+ };
65
67
  /** A class that adds `toString` method that prints all properties of an object. */
66
68
  export declare abstract class WithDebug {
67
69
  toString(): string;
@@ -1 +1 @@
1
- {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../../../../packages/core/utils/debug.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,YAExB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,GAAG,cAA6F,CAAC;AAE9G;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CACnB,OAAO,EAAE,oBAAoB,EAC7B,SAAS,EAAE,OAAO,EAClB,GAAG,IAAI,EAAE,OAAO,EAAE,GACjB,OAAO,CAAC,SAAS,IAAI,IAAI,CAO3B;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAE/C;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,QAKpE;AAED,6BAA6B;AAC7B,wBAAgB,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,MAAM,CAEzC;AAkED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM;;;;;EAgBjC;AAcD;;;;;;;GAOG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAMpC;AAED,+CAA+C;AAC/C,wBAAgB,aAAa,IAAI,MAAM,MAAM,CAc5C;AAED,mFAAmF;AACnF,8BAAsB,SAAS;IAC7B,QAAQ;CAGT;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;;EAMpC"}
1
+ {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../../../../packages/core/utils/debug.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,YAExB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,GAAG,cAA6F,CAAC;AAE9G;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CACnB,OAAO,EAAE,oBAAoB,EAC7B,SAAS,EAAE,OAAO,EAClB,GAAG,IAAI,EAAE,OAAO,EAAE,GACjB,OAAO,CAAC,SAAS,IAAI,IAAI,CAO3B;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAE/C;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,QAKpE;AAED,6BAA6B;AAC7B,wBAAgB,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,MAAM,CAEzC;AAkED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM;;;;;EAgBjC;AAcD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,OAAO,GAAG,MAAM,CAUxD;AAED,+CAA+C;AAC/C,wBAAgB,aAAa,CAAC,WAAW,EAAE,OAAO,GAAG;IAAE,QAAQ,IAAI,MAAM,CAAA;CAAE,CAgB1E;AAED,mFAAmF;AACnF,8BAAsB,SAAS;IAC7B,QAAQ;CAGT;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;;EAMpC"}
@@ -148,26 +148,31 @@ function rawMemoryUsage() {
148
148
  * `arrayBuffers` should allow tracking WASM memory, since every instance backs its
149
149
  * memory with `ArrayBuffer`.
150
150
  */
151
- export function memoryUsage() {
151
+ export function memoryUsage(withDetails) {
152
152
  const m = rawMemoryUsage();
153
153
  if (m === null) {
154
154
  return "";
155
155
  }
156
- return `rss=${toMb(m.rss)}MB heap=${toMb(m.heapUsed)}/${toMb(m.heapTotal)}MB external=${toMb(m.external)}MB arrayBuffers=${toMb(m.arrayBuffers)}MB`;
156
+ if (withDetails) {
157
+ return `rss=${toMb(m.rss)}MB heap=${toMb(m.heapUsed)}/${toMb(m.heapTotal)}MB external=${toMb(m.external)}MB arrayBuffers=${toMb(m.arrayBuffers)}MB`;
158
+ }
159
+ return `rss=${toMb(m.rss)}MB heap=${toMb(m.heapUsed)}/${toMb(m.heapTotal)}MB`;
157
160
  }
158
161
  /** Create a stateful memory usage reporter. */
159
- export function memoryTracker() {
162
+ export function memoryTracker(withDetails) {
160
163
  let prev = null;
161
- return () => {
162
- const m = rawMemoryUsage();
163
- if (m === null) {
164
- return "";
165
- }
166
- const delta = prev === null
167
- ? ""
168
- : ` (Δrss=${signedMb(m.rss - prev.rss)}MB ΔarrayBuffers=${signedMb(m.arrayBuffers - prev.arrayBuffers)}MB)`;
169
- prev = m;
170
- return `${memoryUsage()}${delta}`;
164
+ return {
165
+ toString() {
166
+ const m = rawMemoryUsage();
167
+ if (m === null) {
168
+ return "";
169
+ }
170
+ const delta = prev === null || withDetails === false
171
+ ? ""
172
+ : ` (Δrss=${signedMb(m.rss - prev.rss)}MB ΔarrayBuffers=${signedMb(m.arrayBuffers - prev.arrayBuffers)}MB)`;
173
+ prev = m;
174
+ return `${memoryUsage(withDetails)}${delta}`;
175
+ },
171
176
  };
172
177
  }
173
178
  /** A class that adds `toString` method that prints all properties of an object. */
@@ -25,21 +25,27 @@ describe("utils::lazyInspect", () => {
25
25
  });
26
26
  describe("utils::memoryUsage", () => {
27
27
  it("should report all memory fields", () => {
28
- const usage = memoryUsage();
28
+ const usage = memoryUsage(true);
29
29
  for (const field of ["rss=", "heap=", "external=", "arrayBuffers="]) {
30
30
  assert.ok(usage.includes(field), `expected "${field}" in "${usage}"`);
31
31
  }
32
32
  });
33
+ it("should report all memory fields without details", () => {
34
+ const usage = memoryUsage(false);
35
+ for (const field of ["rss=", "heap="]) {
36
+ assert.ok(usage.includes(field), `expected "${field}" in "${usage}"`);
37
+ }
38
+ });
33
39
  });
34
40
  describe("utils::memoryTracker", () => {
35
41
  it("should not include a delta on the first call", () => {
36
- const tracker = memoryTracker();
37
- assert.ok(!tracker().includes("Δrss"));
42
+ const tracker = memoryTracker(true);
43
+ assert.ok(!tracker.toString().includes("Δrss"));
38
44
  });
39
45
  it("should include a delta on subsequent calls", () => {
40
- const tracker = memoryTracker();
41
- tracker();
42
- const second = tracker();
46
+ const tracker = memoryTracker(true);
47
+ tracker.toString();
48
+ const second = tracker.toString();
43
49
  assert.ok(second.includes("Δrss="), `expected delta in "${second}"`);
44
50
  assert.ok(second.includes("ΔarrayBuffers="), `expected delta in "${second}"`);
45
51
  });
@@ -4,7 +4,8 @@ import { type FromJson } from "#@typeberry/json-parser";
4
4
  import { AuthorshipOptions } from "./authorship.js";
5
5
  import { JipChainSpec } from "./jip-chain-spec.js";
6
6
  /** Development config. Will accept unsealed blocks for now. */
7
- export declare const DEV_CONFIG = "dev";
7
+ export declare const DEV_TINY_CONFIG = "dev";
8
+ export declare const DEV_FULL_CONFIG = "dev-full";
8
9
  /** Default config file. */
9
10
  export declare const DEFAULT_CONFIG = "default";
10
11
  export declare const NODE_DEFAULTS: {
@@ -1 +1 @@
1
- {"version":3,"file":"node-config.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/config-node/node-config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,OAAO,EAAE,KAAK,QAAQ,EAAuB,MAAM,wBAAwB,CAAC;AAG5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAInD,+DAA+D;AAC/D,eAAO,MAAM,UAAU,QAAQ,CAAC;AAChC,2BAA2B;AAC3B,eAAO,MAAM,cAAc,YAAY,CAAC;AAExC,eAAO,MAAM,aAAa;;;;CAIzB,CAAC;AAEF,0BAA0B;AAC1B,oBAAY,cAAc;IACxB,uBAAuB;IACvB,IAAI,SAAS;IACb,uBAAuB;IACvB,IAAI,SAAS;CACd;AAED,eAAO,MAAM,sBAAsB,EAS7B,QAAQ,CAAC,cAAc,CAAC,CAAC;AAE/B,qBAAa,iBAAiB;aAqBV,OAAO,EAAE,MAAM;aACf,OAAO,EAAE,MAAM;aACf,MAAM,EAAE,cAAc;aACtB,SAAS,EAAE,YAAY;IACvC,iEAAiE;aACjD,gBAAgB,EAAE,MAAM,GAAG,SAAS;aACpC,UAAU,EAAE,iBAAiB;IA1B/C,MAAM,CAAC,QAAQ,kFAUb;IAEF,MAAM,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,EAAE,UAAU,EAAE,EAAE,UAAU,CAAC,iBAAiB,CAAC;IAOlH,OAAO;CASR;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,iBAAiB,CAkDlG"}
1
+ {"version":3,"file":"node-config.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/config-node/node-config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,OAAO,EAAE,KAAK,QAAQ,EAAuB,MAAM,wBAAwB,CAAC;AAG5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAInD,+DAA+D;AAC/D,eAAO,MAAM,eAAe,QAAQ,CAAC;AACrC,eAAO,MAAM,eAAe,aAAa,CAAC;AAE1C,2BAA2B;AAC3B,eAAO,MAAM,cAAc,YAAY,CAAC;AAExC,eAAO,MAAM,aAAa;;;;CAIzB,CAAC;AAEF,0BAA0B;AAC1B,oBAAY,cAAc;IACxB,uBAAuB;IACvB,IAAI,SAAS;IACb,uBAAuB;IACvB,IAAI,SAAS;CACd;AAED,eAAO,MAAM,sBAAsB,EAS7B,QAAQ,CAAC,cAAc,CAAC,CAAC;AAE/B,qBAAa,iBAAiB;aAqBV,OAAO,EAAE,MAAM;aACf,OAAO,EAAE,MAAM;aACf,MAAM,EAAE,cAAc;aACtB,SAAS,EAAE,YAAY;IACvC,iEAAiE;aACjD,gBAAgB,EAAE,MAAM,GAAG,SAAS;aACpC,UAAU,EAAE,iBAAiB;IA1B/C,MAAM,CAAC,QAAQ,kFAUb;IAEF,MAAM,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,EAAE,UAAU,EAAE,EAAE,UAAU,CAAC,iBAAiB,CAAC;IAOlH,OAAO;CASR;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,iBAAiB,CAuDlG"}
@@ -9,7 +9,8 @@ import { AuthorshipOptions } from "./authorship.js";
9
9
  import { JipChainSpec } from "./jip-chain-spec.js";
10
10
  const logger = Logger.new(import.meta.filename, "config");
11
11
  /** Development config. Will accept unsealed blocks for now. */
12
- export const DEV_CONFIG = "dev";
12
+ export const DEV_TINY_CONFIG = "dev";
13
+ export const DEV_FULL_CONFIG = "dev-full";
13
14
  /** Default config file. */
14
15
  export const DEFAULT_CONFIG = "default";
15
16
  export const NODE_DEFAULTS = {
@@ -72,8 +73,12 @@ export function loadConfig(config, withRelPath) {
72
73
  let mergedJson = {};
73
74
  for (const entry of config) {
74
75
  logger.log `🔧 Applying '${entry}'`;
75
- if (entry === DEV_CONFIG) {
76
- mergedJson = structuredClone(configs.dev); // clone to avoid mutating the original config. not doing a merge since dev and default should theoretically replace all properties.
76
+ if (entry === DEV_TINY_CONFIG) {
77
+ mergedJson = structuredClone(configs.devTiny); // clone to avoid mutating the original config. not doing a merge since dev and default should theoretically replace all properties.
78
+ continue;
79
+ }
80
+ if (entry === DEV_FULL_CONFIG) {
81
+ mergedJson = structuredClone(configs.devFull); // clone to avoid mutating the original config. not doing a merge since dev and default should theoretically replace all properties.
77
82
  continue;
78
83
  }
79
84
  if (entry === DEFAULT_CONFIG) {
@@ -70,7 +70,7 @@ describe("loadConfig", () => {
70
70
  });
71
71
  it("should load dev config", () => {
72
72
  const config = loadConfig(["dev"], withRelPath);
73
- assert.deepStrictEqual(config, parseFromJson(configs.dev, NodeConfiguration.fromJson));
73
+ assert.deepStrictEqual(config, parseFromJson(configs.devTiny, NodeConfiguration.fromJson));
74
74
  });
75
75
  it("should parse inline json config and deep merge onto previous entries", () => {
76
76
  const config = loadConfig(["default", JSON.stringify({ database_base_path: "/test/path", chain_spec: { bootnodes: [] } })], withRelPath);
@@ -138,9 +138,9 @@ describe("loadConfig", () => {
138
138
  `.database_base_path="/test/path-1"`,
139
139
  ], withRelPath);
140
140
  assert.deepStrictEqual(config, parseFromJson({
141
- ...configs.dev,
141
+ ...configs.devTiny,
142
142
  database_base_path: "/test/path-1",
143
- chain_spec: { ...configs.dev.chain_spec, bootnodes: [] },
143
+ chain_spec: { ...configs.devTiny.chain_spec, bootnodes: [] },
144
144
  }, NodeConfiguration.fromJson));
145
145
  });
146
146
  it("should throw an error if an invalid json file is provided", () => {
@@ -108,7 +108,7 @@ export class TicketDistributionTask {
108
108
  // Wrap with Promise.resolve().then() so a synchronous throw inside the validator
109
109
  // funnels into the same .catch() as an async rejection.
110
110
  Promise.resolve()
111
- .then(() => validator.validate(epochIndex, ticket))
111
+ .then(() => validator.validate(epochIndex, [ticket]))
112
112
  .then((result) => {
113
113
  if (result.isOk) {
114
114
  this.addTicket(epochIndex, ticket);
@@ -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
- * Generates signed tickets for all attempts at once using batch ring VRF.
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[], proverKeyIndex: number, key: BandersnatchSecretSeed, entropy: EntropyHash, ticketsPerValidator: number): Promise<Result<SignedTicket[], null>>;
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;AACjF,OAAO,EAIL,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC9B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAa,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAwC/D,QAAA,MAAM,SAAS;;;;;;;;CAQd,CAAC;AAKF,eAAe,SAAS,CAAC;AAIzB,iBAAe,iBAAiB,CAC9B,YAAY,EAAE,gBAAgB,EAC9B,SAAS,EAAE,eAAe,EAC1B,SAAS,EAAE,wBAAwB,EACnC,OAAO,EAAE,SAAS,EAClB,qBAAqB,EAAE,SAAS,EAChC,gBAAgB,EAAE,wBAAwB,EAC1C,oBAAoB,EAAE,SAAS,GAC9B,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,IAAI,CAAC,CAAC,CAkBnD;AAED,iBAAe,UAAU,CACvB,YAAY,EAAE,gBAAgB,EAC9B,SAAS,EAAE,eAAe,EAC1B,SAAS,EAAE,wBAAwB,EACnC,OAAO,EAAE,SAAS,EAClB,qBAAqB,EAAE,SAAS,GAC/B,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAapC;AAED,iBAAS,iBAAiB,CACxB,YAAY,EAAE,gBAAgB,EAC9B,UAAU,EAAE,eAAe,EAAE,GAC5B,OAAO,CAAC,MAAM,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAC,CAe7C;AAgBD,iBAAe,aAAa,CAC1B,YAAY,EAAE,gBAAgB,EAC9B,kBAAkB,EAAE,MAAM,EAC1B,SAAS,EAAE,oBAAoB,EAC/B,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,WAAW,EAAE,CAAA;CAAE,CAAC,CA0BvD;AAGD,iBAAe,YAAY,CACzB,YAAY,EAAE,gBAAgB,EAC9B,SAAS,EAAE,sBAAsB,EACjC,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,SAAS,GACjB,OAAO,CAAC,MAAM,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC,CAQjD;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;AAGlE,iBAAe,gBAAgB,CAC7B,YAAY,EAAE,gBAAgB,EAC9B,SAAS,EAAE,sBAAsB,EACjC,KAAK,EAAE,SAAS,GACf,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,CAQtC;AAKD;;GAEG;AACH,iBAAe,eAAe,CAC5B,YAAY,EAAE,gBAAgB,EAC9B,QAAQ,EAAE,eAAe,EAAE,EAC3B,cAAc,EAAE,MAAM,EACtB,GAAG,EAAE,sBAAsB,EAC3B,OAAO,EAAE,WAAW,EACpB,mBAAmB,EAAE,MAAM,GAC1B,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,EAAE,IAAI,CAAC,CAAC,CA0CvC"}
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
- * Generates signed tickets for all attempts at once using batch ring VRF.
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, proverKeyIndex, key, entropy, ticketsPerValidator) {
128
- // Build VRF inputs: JAM_TICKET_SEAL || entropy || attempt_byte for each attempt
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
- const attemptLength = 1;
134
- const vrfInputDataLen = JAM_TICKET_SEAL.length + entropy.length + attemptLength;
135
- const inputsData = BytesBlob.blobFromParts(vrfInputParts).raw;
136
- const ringKeysData = BytesBlob.blobFromParts(ringKeys.map((k) => k.raw)).raw;
137
- const result = await bandersnatch.batchGenerateRingVrf(ringKeysData, proverKeyIndex, key.raw, inputsData, vrfInputDataLen);
138
- const tickets = [];
139
- for (let attempt = 0; attempt < ticketsPerValidator; attempt++) {
140
- const offset = attempt * GENERATE_RESULT_ENTRY_LENGTH;
141
- const resultByte = result[offset];
142
- if (resultByte === ResultValues.Error) {
143
- return Result.error(null, () => `Ring VRF proof generation failed for attempt ${attempt}`);
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
- const signature = Bytes.fromBlob(new Uint8Array(result.subarray(offset + 1, offset + GENERATE_RESULT_ENTRY_LENGTH)), BANDERSNATCH_PROOF_BYTES).asOpaque();
146
- tickets.push(SignedTicket.create({
147
- attempt: tryAsTicketAttempt(attempt),
148
- signature,
149
- }));
183
+ perValidator.push(tickets);
150
184
  }
151
- return Result.ok(tickets);
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
- const verifyResult = await bandersnatchVrf.verifyTickets(await bandersnatchWasm, ringKeys.length, commitment.ok, genResult.ok, entropy);
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;CAI1B"}
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
- id: EntropyHash | null;
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, ticket: SignedTicket): Promise<Result<ValidatedTicket, ValidationError>>;
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, _ticket: SignedTicket): Promise<Result<ValidatedTicket, ValidationError>>;
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, _ticket: SignedTicket): Promise<Result<ValidatedTicket, ValidationError>>;
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;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"}
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, _ticket) {
18
- return Result.ok({ id: null });
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, _ticket) {
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 null id", async () => {
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, null);
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)) {
@@ -21,17 +21,17 @@ function makeId(byte) {
21
21
  }
22
22
  describe("VerifiedTicketPool", () => {
23
23
  it("starts empty", () => {
24
- const pool = new VerifiedTicketPool();
24
+ const pool = VerifiedTicketPool.new();
25
25
  assert.deepStrictEqual(pool.getForEpoch(E1), []);
26
26
  });
27
27
  it("adds and retrieves tickets per epoch", () => {
28
- const pool = new VerifiedTicketPool();
28
+ const pool = VerifiedTicketPool.new();
29
29
  pool.add(E1, [{ ticket: makeTicket(1), id: makeId(0xaa) }]);
30
30
  assert.strictEqual(pool.getForEpoch(E1).length, 1);
31
31
  assert.deepStrictEqual(pool.getForEpoch(E2), []);
32
32
  });
33
33
  it("dedups by id", () => {
34
- const pool = new VerifiedTicketPool();
34
+ const pool = VerifiedTicketPool.new();
35
35
  const id = makeId(0x01);
36
36
  pool.add(E1, [{ ticket: makeTicket(1), id }]);
37
37
  pool.add(E1, [{ ticket: makeTicket(2), id }]);
@@ -39,14 +39,14 @@ describe("VerifiedTicketPool", () => {
39
39
  assert.strictEqual(pool.getForEpoch(E1)[0].ticket.signature.raw[0], 1);
40
40
  });
41
41
  it("clears previous epochs when a new epoch is added", () => {
42
- const pool = new VerifiedTicketPool();
42
+ const pool = VerifiedTicketPool.new();
43
43
  pool.add(E1, [{ ticket: makeTicket(1), id: makeId(1) }]);
44
44
  pool.add(E2, [{ ticket: makeTicket(2), id: makeId(2) }]);
45
45
  assert.deepStrictEqual(pool.getForEpoch(E1), []);
46
46
  assert.strictEqual(pool.getForEpoch(E2).length, 1);
47
47
  });
48
48
  it("appends across multiple add() calls for the same epoch", () => {
49
- const pool = new VerifiedTicketPool();
49
+ const pool = VerifiedTicketPool.new();
50
50
  pool.add(E1, [{ ticket: makeTicket(1), id: makeId(1) }]);
51
51
  pool.add(E1, [{ ticket: makeTicket(2), id: makeId(2) }]);
52
52
  assert.strictEqual(pool.getForEpoch(E1).length, 2);