@typeberry/lib 0.8.4-faebc7a → 0.9.0-3f2c45b

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 (105) 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/database-fjall/hybrid-states.d.ts +47 -10
  18. package/packages/jam/database-fjall/hybrid-states.d.ts.map +1 -1
  19. package/packages/jam/database-fjall/hybrid-states.js +78 -22
  20. package/packages/jam/database-fjall/hybrid-states.test.js +31 -1
  21. package/packages/jam/database-fjall/root.d.ts +18 -12
  22. package/packages/jam/database-fjall/root.d.ts.map +1 -1
  23. package/packages/jam/database-fjall/root.js +14 -10
  24. package/packages/jam/jamnp-s/tasks/ticket-distribution.js +1 -1
  25. package/packages/jam/node/main-fuzz.d.ts.map +1 -1
  26. package/packages/jam/node/main-fuzz.js +53 -10
  27. package/packages/jam/node/main-importer.d.ts +8 -1
  28. package/packages/jam/node/main-importer.d.ts.map +1 -1
  29. package/packages/jam/node/main-importer.js +2 -1
  30. package/packages/jam/safrole/bandersnatch-vrf.d.ts +22 -2
  31. package/packages/jam/safrole/bandersnatch-vrf.d.ts.map +1 -1
  32. package/packages/jam/safrole/bandersnatch-vrf.js +54 -20
  33. package/packages/jam/safrole/bandersnatch-vrf.test.js +3 -2
  34. package/packages/jam/safrole/bandersnatch-wasm.d.ts +10 -0
  35. package/packages/jam/safrole/bandersnatch-wasm.d.ts.map +1 -1
  36. package/packages/jam/safrole/bandersnatch-wasm.js +12 -0
  37. package/packages/jam/ticket-pool/ticket-validator.d.ts +5 -4
  38. package/packages/jam/ticket-pool/ticket-validator.d.ts.map +1 -1
  39. package/packages/jam/ticket-pool/ticket-validator.js +8 -3
  40. package/packages/jam/ticket-pool/ticket-validator.test.js +5 -4
  41. package/packages/jam/ticket-pool/verified-ticket-pool.d.ts +2 -0
  42. package/packages/jam/ticket-pool/verified-ticket-pool.d.ts.map +1 -1
  43. package/packages/jam/ticket-pool/verified-ticket-pool.js +4 -0
  44. package/packages/jam/ticket-pool/verified-ticket-pool.test.js +5 -5
  45. package/packages/workers/api-node/config.d.ts +14 -6
  46. package/packages/workers/api-node/config.d.ts.map +1 -1
  47. package/packages/workers/api-node/config.js +15 -11
  48. package/packages/workers/block-authorship/{generator.d.ts → block-generator.d.ts} +5 -5
  49. package/packages/workers/block-authorship/block-generator.d.ts.map +1 -0
  50. package/packages/workers/block-authorship/{generator.js → block-generator.js} +3 -3
  51. package/packages/workers/block-authorship/block-generator.test.d.ts +2 -0
  52. package/packages/workers/block-authorship/block-generator.test.d.ts.map +1 -0
  53. package/packages/workers/block-authorship/{generator.test.js → block-generator.test.js} +8 -8
  54. package/packages/workers/block-authorship/epoch-authoring-slots.d.ts +35 -0
  55. package/packages/workers/block-authorship/epoch-authoring-slots.d.ts.map +1 -0
  56. package/packages/workers/block-authorship/epoch-authoring-slots.js +86 -0
  57. package/packages/workers/block-authorship/epoch-tracker.d.ts +29 -0
  58. package/packages/workers/block-authorship/epoch-tracker.d.ts.map +1 -0
  59. package/packages/workers/block-authorship/epoch-tracker.js +80 -0
  60. package/packages/workers/block-authorship/index.d.ts.map +1 -1
  61. package/packages/workers/block-authorship/index.js +1 -1
  62. package/packages/workers/block-authorship/main.d.ts +3 -0
  63. package/packages/workers/block-authorship/main.d.ts.map +1 -1
  64. package/packages/workers/block-authorship/main.js +193 -261
  65. package/packages/workers/block-authorship/ticket-generator/bootstrap-main.d.ts +2 -0
  66. package/packages/workers/block-authorship/ticket-generator/bootstrap-main.d.ts.map +1 -0
  67. package/packages/workers/block-authorship/ticket-generator/bootstrap-main.js +23 -0
  68. package/packages/workers/block-authorship/ticket-generator/index.d.ts +16 -0
  69. package/packages/workers/block-authorship/ticket-generator/index.d.ts.map +1 -0
  70. package/packages/workers/block-authorship/ticket-generator/index.js +62 -0
  71. package/packages/workers/block-authorship/ticket-generator/protocol.d.ts +50 -0
  72. package/packages/workers/block-authorship/ticket-generator/protocol.d.ts.map +1 -0
  73. package/packages/workers/block-authorship/ticket-generator/protocol.js +54 -0
  74. package/packages/workers/block-authorship/{ticket-generator.d.ts → ticket-generator/ticket-generator.d.ts} +4 -0
  75. package/packages/workers/block-authorship/ticket-generator/ticket-generator.d.ts.map +1 -0
  76. package/packages/workers/block-authorship/{ticket-generator.js → ticket-generator/ticket-generator.js} +19 -9
  77. package/packages/workers/block-authorship/ticket-generator/ticket-generator.test.d.ts.map +1 -0
  78. package/packages/workers/block-authorship/{ticket-generator.test.js → ticket-generator/ticket-generator.test.js} +13 -9
  79. package/packages/workers/block-authorship/ticket-generator/worker-pool.d.ts +36 -0
  80. package/packages/workers/block-authorship/ticket-generator/worker-pool.d.ts.map +1 -0
  81. package/packages/workers/block-authorship/ticket-generator/worker-pool.js +111 -0
  82. package/packages/workers/block-authorship/ticket-validator.d.ts +7 -8
  83. package/packages/workers/block-authorship/ticket-validator.d.ts.map +1 -1
  84. package/packages/workers/block-authorship/ticket-validator.js +26 -23
  85. package/packages/workers/comms-authorship-network/protocol.d.ts +4 -4
  86. package/packages/workers/comms-authorship-network/protocol.d.ts.map +1 -1
  87. package/packages/workers/comms-authorship-network/protocol.js +4 -5
  88. package/packages/workers/comms-authorship-network/tickets-message.d.ts +0 -14
  89. package/packages/workers/comms-authorship-network/tickets-message.d.ts.map +1 -1
  90. package/packages/workers/comms-authorship-network/tickets-message.js +0 -17
  91. package/packages/workers/importer/importer.d.ts +2 -2
  92. package/packages/workers/importer/importer.d.ts.map +1 -1
  93. package/packages/workers/importer/importer.js +5 -5
  94. package/packages/workers/importer/stats.d.ts +1 -3
  95. package/packages/workers/importer/stats.d.ts.map +1 -1
  96. package/packages/workers/importer/stats.js +12 -12
  97. package/packages/workers/jam-network/main.d.ts.map +1 -1
  98. package/packages/workers/jam-network/main.js +8 -3
  99. package/packages/workers/block-authorship/generator.d.ts.map +0 -1
  100. package/packages/workers/block-authorship/generator.test.d.ts +0 -2
  101. package/packages/workers/block-authorship/generator.test.d.ts.map +0 -1
  102. package/packages/workers/block-authorship/ticket-generator.d.ts.map +0 -1
  103. package/packages/workers/block-authorship/ticket-generator.test.d.ts.map +0 -1
  104. /package/packages/configs/{typeberry-dev.json → typeberry-dev-tiny.json} +0 -0
  105. /package/packages/workers/block-authorship/{ticket-generator.test.d.ts → ticket-generator/ticket-generator.test.d.ts} +0 -0
@@ -8,7 +8,7 @@ import { v1 as fuzzV1 } from "#@typeberry/fuzz-proto";
8
8
  import { HASH_SIZE } from "#@typeberry/hash";
9
9
  import { Logger } from "#@typeberry/logger";
10
10
  import { CURRENT_VERSION, Result, version } from "#@typeberry/utils";
11
- import { logHostEnvironment } from "#@typeberry/workers-api-node";
11
+ import { FjallValuesSession, logHostEnvironment } from "#@typeberry/workers-api-node";
12
12
  import { getChainSpec } from "./common.js";
13
13
  import { mainImporter } from "./main-importer.js";
14
14
  const logger = Logger.new(import.meta.filename, "fuzztarget");
@@ -17,6 +17,14 @@ const FUZZ_DB_SUBDIR = "typeberry-fuzz-db";
17
17
  const FUZZ_DB_FJALL = "fjall-hybrid";
18
18
  const FUZZ_DB_LMDB = "lmdb-hybrid";
19
19
  const FUZZ_DB_OPTIONS = [FUZZ_DB_FJALL, FUZZ_DB_LMDB];
20
+ /** Subdirectory (under the fuzzer's db dir) holding the reused fjall values keyspace. */
21
+ const FUZZ_FJALL_VALUES_SUBDIR = "values-session";
22
+ /**
23
+ * Size of the fjall block-cache for the fuzz session. Values pile up across
24
+ * resets (for fjall we do not wipe between them), so this cache is what keeps
25
+ * the resident memory bounded.
26
+ */
27
+ const FUZZ_FJALL_CACHE_BYTES = 128 * 1024 * 1024;
20
28
  /**
21
29
  * Resolve the directory the fuzzer should use for its on-disk database, or
22
30
  * `undefined` for an in-memory database. The dedicated `FUZZ_DB_SUBDIR` is
@@ -63,6 +71,10 @@ export async function mainFuzz(fuzzConfig, withRelPath) {
63
71
  logger.info `🗄️ Fuzz persistent backend: ${hybridStateBackend}.`;
64
72
  }
65
73
  let runningNode = null;
74
+ // The fjall values keyspace is opened once per fuzz session and reused on
75
+ // every reset, because opening it is the slow part. Only the in-memory blocks
76
+ // and leaf sets are rebuilt for each vector. fjall-hybrid only.
77
+ let fjallSession = null;
66
78
  const chainSpec = getChainSpec(config.node.flavor);
67
79
  const closeFuzzTarget = startFuzzTarget(fuzzConfig.version, fuzzConfig.socket, {
68
80
  ...getFuzzDetails(),
@@ -113,20 +125,43 @@ export async function mainFuzz(fuzzConfig, withRelPath) {
113
125
  // like the in-memory backend; only the large values live on disk.
114
126
  dummyFinalityDepth: 20,
115
127
  pruneBlocks: true,
116
- // Long full-spec sessions accumulate a large, never-pruned values db.
117
- // Syncing lets the OS reclaim dirty mmap pages, and compression (full
118
- // spec only, where values are big) bounds its on-disk/page-cache size.
119
- // Tiny stays uncompressed since its db is small and speed matters more.
128
+ // The on-disk fuzz db is throwaway (we wipe it), so open it ephemeral and
129
+ // skip the fsync, we do not need durability here. On full spec ephemeral
130
+ // also turns on compression further down, so the big values do not grow the
131
+ // db too much. Tiny stays uncompressed, its db is small and speed matters more.
120
132
  ephemeral: isPersistent,
121
133
  stateBackend: isPersistent ? hybridStateBackend : "lmdb",
134
+ // Reuse the session keyspace (fjall-hybrid only, other backends
135
+ // ignore it). Nothing to pass for the in-memory fallback.
136
+ sharedFjallSession: isPersistent ? (fjallSession ?? undefined) : undefined,
122
137
  });
123
138
  };
124
139
  if (fuzzDbBase !== undefined) {
125
- // Each reset starts a fresh session from the genesis the fuzzer just sent,
126
- // so the on-disk db must be empty: otherwise initializeDatabase sees an
127
- // already-initialized db and silently resumes the previous run's state.
128
- await wipeFuzzDb(fuzzDbBase);
129
140
  try {
141
+ if (hybridStateBackend === FUZZ_DB_FJALL) {
142
+ // fjall-hybrid: open the values keyspace once and reuse it on every
143
+ // reset. The values partition is content-addressed and immutable, so
144
+ // it is fine that values pile up across resets, the unreferenced ones
145
+ // just sit there. `initializeDatabase` decides whether the db is
146
+ // already initialized from the in-memory blocks, which we rebuild on
147
+ // every reset, not from the values store, so reusing it does not
148
+ // resume the previous run.
149
+ if (fjallSession === null) {
150
+ // Start from a clean slate once, then keep the keyspace open.
151
+ await wipeFuzzDb(fuzzDbBase);
152
+ fjallSession = await FjallValuesSession.open(`${withRelPath(fuzzDbBase)}/${FUZZ_FJALL_VALUES_SUBDIR}`, {
153
+ ephemeral: true,
154
+ cacheSizeBytes: FUZZ_FJALL_CACHE_BYTES,
155
+ });
156
+ logger.info `🗄️ Opened reusable fjall values session at ${withRelPath(fuzzDbBase)}/${FUZZ_FJALL_VALUES_SUBDIR}`;
157
+ }
158
+ }
159
+ else {
160
+ // lmdb-hybrid: keep the old behaviour, wipe and reopen on every
161
+ // reset. A fresh db each reset makes `initializeDatabase` set up
162
+ // genesis again instead of resuming the previous run.
163
+ await wipeFuzzDb(fuzzDbBase);
164
+ }
130
165
  runningNode = await buildNode(fuzzDbBase);
131
166
  return await runningNode.getBestStateRootHash();
132
167
  }
@@ -142,9 +177,17 @@ export async function mainFuzz(fuzzConfig, withRelPath) {
142
177
  });
143
178
  return () => {
144
179
  closeFuzzTarget();
180
+ // Close the reused fjall values session (if any) before wiping its files, so
181
+ // the keyspace handle is released first.
182
+ const closed = fjallSession?.close() ?? Promise.resolve();
183
+ fjallSession = null;
145
184
  if (fuzzDbBase !== undefined) {
146
185
  // best-effort cleanup on shutdown; ignore failures (dir may already be gone).
147
- wipeFuzzDb(fuzzDbBase).catch(() => { });
186
+ closed
187
+ .catch(() => { })
188
+ .finally(() => {
189
+ wipeFuzzDb(fuzzDbBase).catch(() => { });
190
+ });
148
191
  }
149
192
  };
150
193
  }
@@ -1,3 +1,4 @@
1
+ import { type FjallValuesSession } from "#@typeberry/workers-api-node";
1
2
  import type { JamConfig } from "./jam-config.js";
2
3
  import type { NodeApi } from "./main.js";
3
4
  export type StateBackend = "lmdb" | "lmdb-hybrid" | "fjall-hybrid";
@@ -8,9 +9,15 @@ export type ImporterOptions = {
8
9
  /** Open the database without fsync/compression. Only safe for throwaway dbs (e.g. fuzzing). */
9
10
  ephemeral?: boolean;
10
11
  /**
11
- * Persistent backend to use when `databaseBasePath` is set. Defaults to full LMDB.
12
+ * Persistent backend used when `databaseBasePath` is set. Defaults to full LMDB.
12
13
  */
13
14
  stateBackend?: StateBackend;
15
+ /**
16
+ * Reuse an already-open fjall values session instead of opening a fresh
17
+ * keyspace. Only used when `stateBackend === "fjall-hybrid"`. The fuzz target
18
+ * opens one per run and reuses it across resets.
19
+ */
20
+ sharedFjallSession?: FjallValuesSession;
14
21
  };
15
22
  export declare function mainImporter(config: JamConfig, withRelPath: (v: string) => string, options?: ImporterOptions): Promise<NodeApi>;
16
23
  //# sourceMappingURL=main-importer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"main-importer.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/main-importer.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,aAAa,GAAG,cAAc,CAAC;AAEnE,MAAM,MAAM,eAAe,GAAG;IAC5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+FAA+F;IAC/F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B,CAAC;AAEF,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAClC,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,OAAO,CAAC,CAqGlB"}
1
+ {"version":3,"file":"main-importer.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/main-importer.ts"],"names":[],"mappings":"AASA,OAAO,EACL,KAAK,kBAAkB,EAIxB,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,aAAa,GAAG,cAAc,CAAC;AAEnE,MAAM,MAAM,eAAe,GAAG;IAC5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+FAA+F;IAC/F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC,CAAC;AAEF,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAClC,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,OAAO,CAAC,CAsGlB"}
@@ -6,7 +6,7 @@ import { Blake2b, HASH_SIZE } from "#@typeberry/hash";
6
6
  import { createImporter, ImporterConfig } from "#@typeberry/importer";
7
7
  import { tryAsU16 } from "#@typeberry/numbers";
8
8
  import { CURRENT_SUITE, CURRENT_VERSION, Result, resultToString, version } from "#@typeberry/utils";
9
- import { HybridWorkerConfig, InMemWorkerConfig, LmdbWorkerConfig } from "#@typeberry/workers-api-node";
9
+ import { HybridWorkerConfig, InMemWorkerConfig, LmdbWorkerConfig, } from "#@typeberry/workers-api-node";
10
10
  import { getChainSpec, getDatabasePath, initializeDatabase, logger } from "./common.js";
11
11
  const zeroHash = Bytes.zero(HASH_SIZE).asOpaque();
12
12
  export async function mainImporter(config, withRelPath, options = {}) {
@@ -49,6 +49,7 @@ export async function mainImporter(config, withRelPath, options = {}) {
49
49
  ephemeral,
50
50
  compression,
51
51
  backend: dbBackend === "lmdb-hybrid" ? "lmdb" : "fjall",
52
+ sharedFjallSession: options.sharedFjallSession,
52
53
  })
53
54
  : LmdbWorkerConfig.new({
54
55
  nodeName,
@@ -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":"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;AAEjF,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;AA4C/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;;;;GAIG;AACH,iBAAe,eAAe,CAC5B,YAAY,EAAE,gBAAgB,EAC9B,QAAQ,EAAE,eAAe,EAAE,EAC3B,gBAAgB,EAAE,SAAS,MAAM,EAAE,EACnC,OAAO,EAAE,SAAS,sBAAsB,EAAE,EAC1C,OAAO,EAAE,WAAW,EACpB,mBAAmB,EAAE,MAAM,GAC1B,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC,CAsBzC;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,WAAW,EACpB,mBAAmB,EAAE,MAAM,GAC1B;IAAE,UAAU,EAAE,UAAU,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,CASrD;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,UAAU,EAClB,aAAa,EAAE,MAAM,EACrB,mBAAmB,EAAE,MAAM,GAC1B,MAAM,CAAC,YAAY,EAAE,EAAE,EAAE,IAAI,CAAC,CAoBhC"}
@@ -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);
@@ -2,10 +2,12 @@ import type { MessagePort } from "node:worker_threads";
2
2
  import { type Decode, type Encode } from "#@typeberry/codec";
3
3
  import { ChainSpec } from "#@typeberry/config";
4
4
  import { type BlocksDb, type RootDb, type SerializedStatesDb } from "#@typeberry/database";
5
+ import { FjallValuesSession } from "#@typeberry/database-fjall";
5
6
  import { Blake2b } from "#@typeberry/hash";
6
7
  import type { WorkerConfig } from "#@typeberry/workers-api";
7
8
  import { ThreadPort, type TransferablePort } from "./port.js";
8
- /** A worker config that's usable in node.js and uses LMDB database backend. */
9
+ export { FjallValuesSession };
10
+ /** Worker config for node.js, backed by the LMDB database. */
9
11
  export declare class LmdbWorkerConfig<T = void> implements WorkerConfig<T, BlocksDb, SerializedStatesDb> {
10
12
  readonly nodeName: string;
11
13
  readonly chainSpec: ChainSpec;
@@ -75,11 +77,10 @@ export declare class InMemWorkerConfig<T = undefined> implements WorkerConfig<T,
75
77
  export type HybridBackend = "lmdb" | "fjall";
76
78
  /**
77
79
  * Hybrid worker config for the fuzz target: in-memory blocks and leaf sets,
78
- * but large values persisted to disk (LMDB or fjall, selected by `backend`).
80
+ * but large values persisted to disk. The `backend` picks where the values go
81
+ * (lmdb or fjall).
79
82
  *
80
- * The fjall backend is opt-in so its performance can be compared against LMDB
81
- * before committing to it. fjall opens its keyspace asynchronously, hence the
82
- * async `new`.
83
+ * fjall opens its keyspace asynchronously, that is why `new` here is async.
83
84
  *
84
85
  * Like `InMemWorkerConfig`, the blocks and leaf sets are shared across the
85
86
  * open/close/reopen dance that genesis init performs, so `openDatabase`
@@ -99,7 +100,7 @@ export declare class HybridWorkerConfig<T = undefined> implements WorkerConfig<T
99
100
  readonly ephemeral: boolean;
100
101
  readonly compression: boolean;
101
102
  private readonly states;
102
- static new<T>({ nodeName, chainSpec, workerParams, blake2b, dbPath, ephemeral, compression, backend, }: {
103
+ static new<T>({ nodeName, chainSpec, workerParams, blake2b, dbPath, ephemeral, compression, backend, sharedFjallSession, }: {
103
104
  nodeName: string;
104
105
  chainSpec: ChainSpec;
105
106
  workerParams: T;
@@ -108,6 +109,13 @@ export declare class HybridWorkerConfig<T = undefined> implements WorkerConfig<T
108
109
  ephemeral?: boolean;
109
110
  compression?: boolean;
110
111
  backend?: HybridBackend;
112
+ /**
113
+ * Reuse an already-open fjall values session instead of opening a fresh
114
+ * keyspace. The fuzz target opens one per run and passes it on every reset,
115
+ * so only the in-memory blocks/leaf sets are rebuilt per vector. Ignored
116
+ * unless `backend === "fjall"`.
117
+ */
118
+ sharedFjallSession?: FjallValuesSession;
111
119
  }): Promise<HybridWorkerConfig<T>>;
112
120
  private readonly blocks;
113
121
  private constructor();
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/api-node/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/api-node/config.ts"],"names":[],"mappings":"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"}