@lodestar/beacon-node 1.47.0-dev.d9c16ea16f → 1.47.0-dev.da8dfeabda

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 (258) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +4 -7
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
  5. package/lib/api/impl/beacon/pool/index.js +12 -1
  6. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  7. package/lib/api/impl/beacon/state/utils.d.ts +2 -1
  8. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  9. package/lib/api/impl/beacon/state/utils.js.map +1 -1
  10. package/lib/api/impl/events/index.d.ts +1 -1
  11. package/lib/api/impl/events/index.d.ts.map +1 -1
  12. package/lib/api/impl/events/index.js +10 -3
  13. package/lib/api/impl/events/index.js.map +1 -1
  14. package/lib/api/impl/validator/index.d.ts.map +1 -1
  15. package/lib/api/impl/validator/index.js +12 -22
  16. package/lib/api/impl/validator/index.js.map +1 -1
  17. package/lib/api/impl/validator/utils.d.ts +5 -0
  18. package/lib/api/impl/validator/utils.d.ts.map +1 -1
  19. package/lib/api/impl/validator/utils.js +18 -12
  20. package/lib/api/impl/validator/utils.js.map +1 -1
  21. package/lib/chain/archiveStore/historicalState/metrics.d.ts.map +1 -1
  22. package/lib/chain/archiveStore/historicalState/metrics.js +21 -0
  23. package/lib/chain/archiveStore/historicalState/metrics.js.map +1 -1
  24. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  25. package/lib/chain/blocks/importBlock.js +2 -7
  26. package/lib/chain/blocks/importBlock.js.map +1 -1
  27. package/lib/chain/blocks/importExecutionPayload.d.ts +3 -2
  28. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  29. package/lib/chain/blocks/importExecutionPayload.js +11 -9
  30. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  31. package/lib/chain/blocks/index.d.ts.map +1 -1
  32. package/lib/chain/blocks/index.js +15 -7
  33. package/lib/chain/blocks/index.js.map +1 -1
  34. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts.map +1 -1
  35. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js +22 -12
  36. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js.map +1 -1
  37. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +2 -2
  38. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -1
  39. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +2 -2
  40. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -1
  41. package/lib/chain/bls/index.d.ts +1 -1
  42. package/lib/chain/bls/index.d.ts.map +1 -1
  43. package/lib/chain/bls/interface.d.ts +5 -5
  44. package/lib/chain/bls/interface.d.ts.map +1 -1
  45. package/lib/chain/bls/multithread/index.d.ts +5 -11
  46. package/lib/chain/bls/multithread/index.d.ts.map +1 -1
  47. package/lib/chain/bls/multithread/index.js +116 -101
  48. package/lib/chain/bls/multithread/index.js.map +1 -1
  49. package/lib/chain/bls/multithread/jobItem.d.ts +5 -19
  50. package/lib/chain/bls/multithread/jobItem.d.ts.map +1 -1
  51. package/lib/chain/bls/multithread/jobItem.js +10 -65
  52. package/lib/chain/bls/multithread/jobItem.js.map +1 -1
  53. package/lib/chain/bls/multithread/types.d.ts +29 -8
  54. package/lib/chain/bls/multithread/types.d.ts.map +1 -1
  55. package/lib/chain/bls/multithread/types.js +12 -0
  56. package/lib/chain/bls/multithread/types.js.map +1 -1
  57. package/lib/chain/bls/multithread/utils.d.ts +4 -0
  58. package/lib/chain/bls/multithread/utils.d.ts.map +1 -1
  59. package/lib/chain/bls/multithread/utils.js +10 -0
  60. package/lib/chain/bls/multithread/utils.js.map +1 -1
  61. package/lib/chain/bls/multithread/worker.js +49 -23
  62. package/lib/chain/bls/multithread/worker.js.map +1 -1
  63. package/lib/chain/bls/singleThread.d.ts +4 -10
  64. package/lib/chain/bls/singleThread.d.ts.map +1 -1
  65. package/lib/chain/bls/singleThread.js +8 -45
  66. package/lib/chain/bls/singleThread.js.map +1 -1
  67. package/lib/chain/bls/utils.d.ts +4 -4
  68. package/lib/chain/bls/utils.d.ts.map +1 -1
  69. package/lib/chain/bls/utils.js +18 -19
  70. package/lib/chain/bls/utils.js.map +1 -1
  71. package/lib/chain/builderCircuitBreaker.d.ts +6 -5
  72. package/lib/chain/builderCircuitBreaker.d.ts.map +1 -1
  73. package/lib/chain/builderCircuitBreaker.js +28 -15
  74. package/lib/chain/builderCircuitBreaker.js.map +1 -1
  75. package/lib/chain/chain.d.ts +3 -2
  76. package/lib/chain/chain.d.ts.map +1 -1
  77. package/lib/chain/chain.js +8 -5
  78. package/lib/chain/chain.js.map +1 -1
  79. package/lib/chain/errors/blockError.d.ts +2 -0
  80. package/lib/chain/errors/blockError.d.ts.map +1 -1
  81. package/lib/chain/errors/blockError.js +6 -1
  82. package/lib/chain/errors/blockError.js.map +1 -1
  83. package/lib/chain/errors/proposerPreferences.d.ts +6 -0
  84. package/lib/chain/errors/proposerPreferences.d.ts.map +1 -1
  85. package/lib/chain/errors/proposerPreferences.js +1 -0
  86. package/lib/chain/errors/proposerPreferences.js.map +1 -1
  87. package/lib/chain/interface.d.ts +2 -1
  88. package/lib/chain/interface.d.ts.map +1 -1
  89. package/lib/chain/interface.js.map +1 -1
  90. package/lib/chain/opPools/aggregatedAttestationPool.js +1 -1
  91. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  92. package/lib/chain/opPools/attestationPool.d.ts +1 -1
  93. package/lib/chain/opPools/attestationPool.d.ts.map +1 -1
  94. package/lib/chain/opPools/attestationPool.js +1 -1
  95. package/lib/chain/opPools/attestationPool.js.map +1 -1
  96. package/lib/chain/opPools/payloadAttestationPool.js +3 -3
  97. package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
  98. package/lib/chain/opPools/syncCommitteeMessagePool.js +1 -1
  99. package/lib/chain/opPools/syncCommitteeMessagePool.js.map +1 -1
  100. package/lib/chain/opPools/syncContributionAndProofPool.js +1 -1
  101. package/lib/chain/opPools/syncContributionAndProofPool.js.map +1 -1
  102. package/lib/chain/opPools/utils.d.ts +1 -1
  103. package/lib/chain/opPools/utils.d.ts.map +1 -1
  104. package/lib/chain/opPools/utils.js +1 -1
  105. package/lib/chain/opPools/utils.js.map +1 -1
  106. package/lib/chain/options.d.ts +1 -1
  107. package/lib/chain/options.d.ts.map +1 -1
  108. package/lib/chain/prepareNextSlot.js +1 -1
  109. package/lib/chain/prepareNextSlot.js.map +1 -1
  110. package/lib/chain/produceBlock/produceBlockBody.d.ts +2 -0
  111. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  112. package/lib/chain/produceBlock/produceBlockBody.js +6 -1
  113. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  114. package/lib/chain/seenCache/seenAttesters.d.ts +9 -5
  115. package/lib/chain/seenCache/seenAttesters.d.ts.map +1 -1
  116. package/lib/chain/seenCache/seenAttesters.js +25 -4
  117. package/lib/chain/seenCache/seenAttesters.js.map +1 -1
  118. package/lib/chain/seenCache/seenBlockProposers.d.ts +5 -1
  119. package/lib/chain/seenCache/seenBlockProposers.d.ts.map +1 -1
  120. package/lib/chain/seenCache/seenBlockProposers.js +10 -3
  121. package/lib/chain/seenCache/seenBlockProposers.js.map +1 -1
  122. package/lib/chain/validation/attestation.d.ts.map +1 -1
  123. package/lib/chain/validation/attestation.js +1 -4
  124. package/lib/chain/validation/attestation.js.map +1 -1
  125. package/lib/chain/validation/attesterSlashing.d.ts.map +1 -1
  126. package/lib/chain/validation/attesterSlashing.js +1 -1
  127. package/lib/chain/validation/attesterSlashing.js.map +1 -1
  128. package/lib/chain/validation/block.d.ts.map +1 -1
  129. package/lib/chain/validation/block.js +21 -7
  130. package/lib/chain/validation/block.js.map +1 -1
  131. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  132. package/lib/chain/validation/executionPayloadBid.js +1 -2
  133. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  134. package/lib/chain/validation/executionPayloadEnvelope.js +1 -1
  135. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  136. package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
  137. package/lib/chain/validation/payloadAttestationMessage.js +5 -14
  138. package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
  139. package/lib/chain/validation/proposerPreferences.d.ts +1 -1
  140. package/lib/chain/validation/proposerPreferences.d.ts.map +1 -1
  141. package/lib/chain/validation/proposerPreferences.js +13 -4
  142. package/lib/chain/validation/proposerPreferences.js.map +1 -1
  143. package/lib/chain/validation/proposerSlashing.js +1 -1
  144. package/lib/chain/validation/proposerSlashing.js.map +1 -1
  145. package/lib/execution/builder/http.d.ts +10 -7
  146. package/lib/execution/builder/http.d.ts.map +1 -1
  147. package/lib/execution/builder/http.js +11 -8
  148. package/lib/execution/builder/http.js.map +1 -1
  149. package/lib/metrics/metrics/beacon.d.ts +3 -3
  150. package/lib/metrics/metrics/beacon.d.ts.map +1 -1
  151. package/lib/metrics/metrics/beacon.js +9 -9
  152. package/lib/metrics/metrics/beacon.js.map +1 -1
  153. package/lib/metrics/metrics/lodestar.d.ts +48 -18
  154. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  155. package/lib/metrics/metrics/lodestar.js +96 -50
  156. package/lib/metrics/metrics/lodestar.js.map +1 -1
  157. package/lib/network/gossip/topic.d.ts +13 -0
  158. package/lib/network/gossip/topic.d.ts.map +1 -1
  159. package/lib/network/gossip/topic.js +37 -0
  160. package/lib/network/gossip/topic.js.map +1 -1
  161. package/lib/network/libp2p/index.d.ts.map +1 -1
  162. package/lib/network/libp2p/index.js +10 -2
  163. package/lib/network/libp2p/index.js.map +1 -1
  164. package/lib/network/network.d.ts.map +1 -1
  165. package/lib/network/network.js +22 -43
  166. package/lib/network/network.js.map +1 -1
  167. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  168. package/lib/network/processor/gossipHandlers.js +32 -5
  169. package/lib/network/processor/gossipHandlers.js.map +1 -1
  170. package/lib/network/reqresp/score.d.ts.map +1 -1
  171. package/lib/network/reqresp/score.js +5 -11
  172. package/lib/network/reqresp/score.js.map +1 -1
  173. package/lib/network/util.d.ts +0 -1
  174. package/lib/network/util.d.ts.map +1 -1
  175. package/lib/network/util.js +0 -4
  176. package/lib/network/util.js.map +1 -1
  177. package/lib/node/nodejs.d.ts +2 -1
  178. package/lib/node/nodejs.d.ts.map +1 -1
  179. package/lib/node/nodejs.js.map +1 -1
  180. package/lib/sync/range/batch.d.ts +23 -5
  181. package/lib/sync/range/batch.d.ts.map +1 -1
  182. package/lib/sync/range/batch.js +61 -22
  183. package/lib/sync/range/batch.js.map +1 -1
  184. package/lib/sync/range/chain.d.ts +2 -1
  185. package/lib/sync/range/chain.d.ts.map +1 -1
  186. package/lib/sync/range/chain.js +23 -10
  187. package/lib/sync/range/chain.js.map +1 -1
  188. package/lib/sync/types.d.ts.map +1 -1
  189. package/lib/sync/types.js.map +1 -1
  190. package/lib/sync/unknownBlock.d.ts +9 -0
  191. package/lib/sync/unknownBlock.d.ts.map +1 -1
  192. package/lib/sync/unknownBlock.js +110 -14
  193. package/lib/sync/unknownBlock.js.map +1 -1
  194. package/package.json +18 -18
  195. package/src/api/impl/beacon/blocks/index.ts +5 -7
  196. package/src/api/impl/beacon/pool/index.ts +12 -1
  197. package/src/api/impl/beacon/state/utils.ts +2 -1
  198. package/src/api/impl/events/index.ts +10 -4
  199. package/src/api/impl/validator/index.ts +22 -27
  200. package/src/api/impl/validator/utils.ts +30 -15
  201. package/src/chain/archiveStore/historicalState/metrics.ts +22 -0
  202. package/src/chain/blocks/importBlock.ts +1 -6
  203. package/src/chain/blocks/importExecutionPayload.ts +12 -11
  204. package/src/chain/blocks/index.ts +19 -7
  205. package/src/chain/blocks/verifyBlocksStateTransitionOnly.ts +25 -16
  206. package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +1 -9
  207. package/src/chain/bls/index.ts +1 -1
  208. package/src/chain/bls/interface.ts +7 -3
  209. package/src/chain/bls/multithread/index.ts +148 -120
  210. package/src/chain/bls/multithread/jobItem.ts +12 -82
  211. package/src/chain/bls/multithread/types.ts +33 -8
  212. package/src/chain/bls/multithread/utils.ts +11 -0
  213. package/src/chain/bls/multithread/worker.ts +85 -27
  214. package/src/chain/bls/singleThread.ts +11 -55
  215. package/src/chain/bls/utils.ts +23 -24
  216. package/src/chain/builderCircuitBreaker.ts +31 -17
  217. package/src/chain/chain.ts +9 -5
  218. package/src/chain/errors/blockError.ts +9 -3
  219. package/src/chain/errors/proposerPreferences.ts +7 -0
  220. package/src/chain/interface.ts +2 -1
  221. package/src/chain/opPools/aggregatedAttestationPool.ts +1 -1
  222. package/src/chain/opPools/attestationPool.ts +1 -1
  223. package/src/chain/opPools/payloadAttestationPool.ts +3 -3
  224. package/src/chain/opPools/syncCommitteeMessagePool.ts +1 -1
  225. package/src/chain/opPools/syncContributionAndProofPool.ts +1 -1
  226. package/src/chain/opPools/utils.ts +1 -1
  227. package/src/chain/options.ts +1 -1
  228. package/src/chain/prepareNextSlot.ts +1 -1
  229. package/src/chain/produceBlock/produceBlockBody.ts +13 -0
  230. package/src/chain/seenCache/seenAttesters.ts +31 -5
  231. package/src/chain/seenCache/seenBlockProposers.ts +13 -3
  232. package/src/chain/validation/attestation.ts +1 -7
  233. package/src/chain/validation/attesterSlashing.ts +1 -8
  234. package/src/chain/validation/block.ts +21 -7
  235. package/src/chain/validation/executionPayloadBid.ts +1 -2
  236. package/src/chain/validation/executionPayloadEnvelope.ts +0 -1
  237. package/src/chain/validation/payloadAttestationMessage.ts +6 -17
  238. package/src/chain/validation/proposerPreferences.ts +15 -5
  239. package/src/chain/validation/proposerSlashing.ts +1 -1
  240. package/src/execution/builder/http.ts +11 -11
  241. package/src/metrics/metrics/beacon.ts +9 -9
  242. package/src/metrics/metrics/lodestar.ts +101 -51
  243. package/src/network/gossip/topic.ts +38 -0
  244. package/src/network/libp2p/index.ts +11 -2
  245. package/src/network/network.ts +27 -55
  246. package/src/network/processor/gossipHandlers.ts +35 -3
  247. package/src/network/reqresp/score.ts +5 -11
  248. package/src/network/util.ts +0 -5
  249. package/src/node/nodejs.ts +2 -1
  250. package/src/sync/range/batch.ts +83 -28
  251. package/src/sync/range/chain.ts +26 -11
  252. package/src/sync/types.ts +3 -1
  253. package/src/sync/unknownBlock.ts +126 -17
  254. package/lib/chain/bls/maybeBatch.d.ts +0 -12
  255. package/lib/chain/bls/maybeBatch.d.ts.map +0 -1
  256. package/lib/chain/bls/maybeBatch.js +0 -35
  257. package/lib/chain/bls/maybeBatch.js.map +0 -1
  258. package/src/chain/bls/maybeBatch.ts +0 -45
@@ -6,27 +6,26 @@ import {Worker, spawn} from "@chainsafe/threads";
6
6
  // biome-ignore lint/suspicious/noGlobalAssign: We need the global `self` to reassign module properties later
7
7
  self = undefined;
8
8
 
9
- import {PublicKey} from "@chainsafe/blst";
10
- import {ISignatureSet, PubkeyCache} from "@lodestar/state-transition";
9
+ import {ISignatureSet} from "@lodestar/state-transition";
11
10
  import {Logger} from "@lodestar/utils";
12
11
  import {Metrics} from "../../../metrics/index.js";
13
12
  import {LinkedList} from "../../../util/array.js";
14
13
  import {callInNextEventLoop} from "../../../util/eventLoop.js";
15
14
  import {QueueError, QueueErrorCode} from "../../../util/queue/index.js";
16
- import {IBlsVerifier, VerifySignatureOpts} from "../interface.js";
17
- import {verifySignatureSetsMaybeBatch} from "../maybeBatch.js";
18
- import {getAggregatedPubkey, getAggregatedPubkeysCount} from "../utils.js";
15
+ import {IBlsVerifier, SameMessageSignatureSet, VerifySignatureOpts} from "../interface.js";
16
+ import {chunkSameMessageSignatureSets, getAggregatedPubkeysCount, verifySignatureSetsInBatches} from "../utils.js";
17
+ import {JobQueueItem, jobItemSigSets, jobItemWorkReq} from "./jobItem.js";
18
+ import {defaultPoolSize} from "./poolSize.js";
19
19
  import {
20
- JobQueueItem,
21
- JobQueueItemSameMessage,
20
+ BlsWorkReq,
21
+ BlsWorkResult,
22
22
  JobQueueItemType,
23
- jobItemSameMessageToMultiSet,
24
- jobItemSigSets,
25
- jobItemWorkReq,
26
- } from "./jobItem.js";
27
- import {defaultPoolSize} from "./poolSize.js";
28
- import {BlsWorkReq, BlsWorkResult, WorkResultCode, WorkResultError, WorkerData} from "./types.js";
29
- import {chunkifyMaximizeChunkSize} from "./utils.js";
23
+ WorkResult,
24
+ WorkResultCode,
25
+ WorkResultError,
26
+ WorkerData,
27
+ } from "./types.js";
28
+ import {chunkifyMaxChunkSize} from "./utils.js";
30
29
 
31
30
  // Worker constructor consider the path relative to the current working directory
32
31
  const workerDir = process.env.NODE_ENV === "test" ? "../../../../lib/chain/bls/multithread" : "./";
@@ -34,7 +33,6 @@ const workerDir = process.env.NODE_ENV === "test" ? "../../../../lib/chain/bls/m
34
33
  export type BlsMultiThreadWorkerPoolModules = {
35
34
  logger: Logger;
36
35
  metrics: Metrics | null;
37
- pubkeyCache: PubkeyCache;
38
36
  };
39
37
 
40
38
  export type BlsMultiThreadWorkerPoolOptions = {
@@ -52,7 +50,7 @@ const blsPoolSize = Math.max(defaultPoolSize - 1, 1);
52
50
  * The biggest sets happen during sync, on mainnet batches of 64 blocks have around ~8000 signatures.
53
51
  * The latency cost of sending the job to and from the worker is approx a single sig verification.
54
52
  * If you split a big signature into 2, the extra time cost is `(2+2N)/(1+2N)`.
55
- * For 128, the extra time cost is about 0.3%. No specific reasoning for `128`, it's just good enough.
53
+ * Keep the scheduler quantum below Lodestar-Z's 256-set verifier bound to limit per-dispatch latency.
56
54
  */
57
55
  const MAX_SIGNATURE_SETS_PER_JOB = 128;
58
56
 
@@ -69,8 +67,8 @@ const MAX_BUFFERED_SIGS = 32;
69
67
  * efficiency, at the cost of delaying validation. Unless running in production shows otherwise, it's not critical
70
68
  * to hold attestations and aggregates for 100ms. Lodestar existing queues may hold those objects for much more anyway.
71
69
  *
72
- * There's no exact reasoning for the `100` milliseconds number. The metric `batchSigsSuccess` should indicate if this
73
- * value needs revision
70
+ * There's no exact reasoning for the `100` milliseconds number. Buffer flush size and reason metrics show whether the
71
+ * wait produces useful batches, while job-duration metrics expose its latency cost.
74
72
  */
75
73
  const MAX_BUFFER_WAIT_MS = 100;
76
74
 
@@ -103,6 +101,9 @@ type WorkerDescriptor = {
103
101
  status: WorkerStatus;
104
102
  };
105
103
 
104
+ type BufferFlushReason = "size" | "timeout";
105
+ type BlsJobOutcome = "valid" | "invalid" | "prepError" | "verifyError" | "workerError";
106
+
106
107
  /**
107
108
  * Wraps "threads" library thread pool queue system with the goals:
108
109
  * - Complete total outstanding jobs in total minimum time possible.
@@ -114,7 +115,6 @@ type WorkerDescriptor = {
114
115
  export class BlsMultiThreadWorkerPool implements IBlsVerifier {
115
116
  private readonly logger: Logger;
116
117
  private readonly metrics: Metrics | null;
117
- private readonly pubkeyCache: PubkeyCache;
118
118
 
119
119
  private readonly workers: WorkerDescriptor[];
120
120
  private readonly jobs = new LinkedList<JobQueueItem>();
@@ -130,20 +130,18 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
130
130
  private workersBusy = 0;
131
131
 
132
132
  constructor(options: BlsMultiThreadWorkerPoolOptions, modules: BlsMultiThreadWorkerPoolModules) {
133
- const {logger, metrics, pubkeyCache} = modules;
133
+ const {logger, metrics} = modules;
134
134
  this.logger = logger;
135
135
  this.metrics = metrics;
136
- this.pubkeyCache = pubkeyCache;
137
136
  this.blsVerifyAllMultiThread = options.blsVerifyAllMultiThread ?? false;
138
137
 
139
- // Use compressed for herumi for now.
140
- // THe worker is not able to deserialize from uncompressed
141
- // `Error: err _wrapDeserialize`
142
138
  this.workers = this.createWorkers(blsPoolSize);
143
139
 
144
140
  if (metrics) {
145
141
  metrics.blsThreadPool.queueLength.addCollect(() => {
142
+ const bufferedJobs = (this.bufferedJobs?.jobs.length ?? 0) + (this.bufferedJobs?.prioritizedJobs.length ?? 0);
146
143
  metrics.blsThreadPool.queueLength.set(this.jobs.length);
144
+ metrics.blsThreadPool.bufferedQueueLength.set(bufferedJobs);
147
145
  metrics.blsThreadPool.workersBusy.set(this.workersBusy);
148
146
  });
149
147
  }
@@ -158,7 +156,6 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
158
156
  }
159
157
 
160
158
  async verifySignatureSets(sets: ISignatureSet[], opts: VerifySignatureOpts = {}): Promise<boolean> {
161
- // Pubkeys are aggregated in the main thread regardless if verified in workers or in main thread
162
159
  this.metrics?.bls.aggregatedPubkeys.inc(getAggregatedPubkeysCount(sets));
163
160
  this.metrics?.blsThreadPool.totalSigSets.inc(sets.length);
164
161
  if (opts.priority) {
@@ -171,13 +168,7 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
171
168
  if (opts.verifyOnMainThread && !this.blsVerifyAllMultiThread) {
172
169
  const timer = this.metrics?.blsThreadPool.mainThreadDurationInThreadPool.startTimer();
173
170
  try {
174
- return verifySignatureSetsMaybeBatch(
175
- sets.map((set) => ({
176
- publicKey: getAggregatedPubkey(set, this.pubkeyCache),
177
- message: set.signingRoot.valueOf(),
178
- signature: set.signature,
179
- }))
180
- );
171
+ return verifySignatureSetsInBatches(sets);
181
172
  } finally {
182
173
  if (timer) timer();
183
174
  }
@@ -186,7 +177,7 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
186
177
  // Split large array of sets into smaller.
187
178
  // Very helpful when syncing finalized, sync may submit +1000 sets so chunkify allows to distribute to many workers
188
179
  const results = await Promise.all(
189
- chunkifyMaximizeChunkSize(sets, MAX_SIGNATURE_SETS_PER_JOB).map(
180
+ chunkifyMaxChunkSize(sets, MAX_SIGNATURE_SETS_PER_JOB).map(
190
181
  (setsChunk) =>
191
182
  new Promise<boolean>((resolve, reject) => {
192
183
  return this.queueBlsWork({
@@ -213,27 +204,27 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
213
204
  * Verify signature sets of the same message, only supports worker verification.
214
205
  */
215
206
  async verifySignatureSetsSameMessage(
216
- sets: {publicKey: PublicKey; signature: Uint8Array}[],
207
+ sets: SameMessageSignatureSet[],
217
208
  message: Uint8Array,
218
209
  opts: Omit<VerifySignatureOpts, "verifyOnMainThread"> = {}
219
210
  ): Promise<boolean[]> {
220
- // chunkify so that it reduce the risk of retrying when there is at least one invalid signature
221
- const results = await Promise.all(
222
- chunkifyMaximizeChunkSize(sets, MAX_SIGNATURE_SETS_PER_JOB).map(
223
- (setsChunk) =>
224
- new Promise<boolean[]>((resolve, reject) => {
225
- this.queueBlsWork({
226
- type: JobQueueItemType.sameMessage,
227
- resolve,
228
- reject,
229
- addedTimeMs: Date.now(),
230
- opts,
231
- sets: setsChunk,
232
- message,
233
- });
234
- })
235
- )
236
- );
211
+ const promises: Promise<boolean[]>[] = [];
212
+ for (const setsChunk of chunkSameMessageSignatureSets(sets)) {
213
+ promises.push(
214
+ new Promise<boolean[]>((resolve, reject) => {
215
+ this.queueBlsWork({
216
+ type: JobQueueItemType.sameMessage,
217
+ resolve,
218
+ reject,
219
+ addedTimeMs: Date.now(),
220
+ opts,
221
+ sets: setsChunk,
222
+ message,
223
+ });
224
+ })
225
+ );
226
+ }
227
+ const results = await Promise.all(promises);
237
228
 
238
229
  return results.flat();
239
230
  }
@@ -266,6 +257,7 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
266
257
 
267
258
  for (let i = 0; i < poolSize; i++) {
268
259
  const workerData: WorkerData = {workerId: i};
260
+ this.metrics?.blsThreadPool.jobsWorkerTime.inc({workerId: i}, 0);
269
261
  const worker = new Worker(path.join(workerDir, "worker.js"), {
270
262
  workerData,
271
263
  } as ConstructorParameters<typeof Worker>[1]);
@@ -329,7 +321,7 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
329
321
  prioritizedJobs: new LinkedList(),
330
322
  sigCount: 0,
331
323
  firstPush: Date.now(),
332
- timeout: setTimeout(this.runBufferedJobs, MAX_BUFFER_WAIT_MS),
324
+ timeout: setTimeout(() => this.runBufferedJobs("timeout"), MAX_BUFFER_WAIT_MS),
333
325
  };
334
326
  }
335
327
  const jobs = job.opts.priority ? this.bufferedJobs.prioritizedJobs : this.bufferedJobs.jobs;
@@ -337,7 +329,7 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
337
329
  this.bufferedJobs.sigCount += jobItemSigSets(job);
338
330
  if (this.bufferedJobs.sigCount > MAX_BUFFERED_SIGS) {
339
331
  clearTimeout(this.bufferedJobs.timeout);
340
- this.runBufferedJobs();
332
+ this.runBufferedJobs("size");
341
333
  }
342
334
  }
343
335
 
@@ -381,6 +373,12 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
381
373
  const workerApi = worker.status.workerApi;
382
374
  worker.status = {code: WorkerStatusCode.running, workerApi};
383
375
  this.workersBusy++;
376
+ const jobsStarted: JobQueueItem[] = [];
377
+ let completedJobsCount = 0;
378
+
379
+ if (this.jobs.length > 0) {
380
+ callInNextEventLoop(this.runJob);
381
+ }
384
382
 
385
383
  try {
386
384
  let startedJobsDefault = 0;
@@ -388,30 +386,20 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
388
386
  let startedSetsDefault = 0;
389
387
  let startedSetsSameMessage = 0;
390
388
  const workReqs: BlsWorkReq[] = [];
391
- const jobsStarted: JobQueueItem[] = [];
392
389
 
393
390
  for (const job of jobsInput) {
394
- this.metrics?.blsThreadPool.jobWaitTime.observe((Date.now() - job.addedTimeMs) / 1000);
391
+ this.metrics?.blsThreadPool.jobWaitTime.observe(jobMetricLabels(job), (Date.now() - job.addedTimeMs) / 1000);
392
+ }
395
393
 
394
+ const preparationStartTime = process.hrtime();
395
+ for (const job of jobsInput) {
396
396
  let workReq: BlsWorkReq;
397
397
  try {
398
- // Note: This can throw, must be handled per-job.
399
- // Pubkey and signature aggregation is defered here
400
- workReq = await jobItemWorkReq(job, this.pubkeyCache, this.metrics);
398
+ workReq = jobItemWorkReq(job);
401
399
  } catch (e) {
402
- this.metrics?.blsThreadPool.errorAggregateSignatureSetsCount.inc({type: job.type});
403
-
404
- switch (job.type) {
405
- case JobQueueItemType.default:
406
- job.reject(e as Error);
407
- break;
408
-
409
- case JobQueueItemType.sameMessage:
410
- // there could be an invalid pubkey/signature, retry each individually
411
- this.retryJobItemSameMessage(job);
412
- break;
413
- }
414
-
400
+ this.metrics?.blsThreadPool.errorJobsSignatureSetsCount.inc(jobItemSigSets(job));
401
+ this.observeJobCompletion(job, "prepError");
402
+ job.reject(e as Error);
415
403
  continue;
416
404
  }
417
405
  // Re-push all jobs with matching workReq for easier accounting of results
@@ -426,8 +414,19 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
426
414
  startedSetsDefault += job.sets.length;
427
415
  }
428
416
  }
417
+ const [preparationSeconds, preparationNanoseconds] = process.hrtime(preparationStartTime);
418
+ this.metrics?.blsThreadPool.workRequestPreparationDuration.observe(
419
+ preparationSeconds + preparationNanoseconds / 1e9
420
+ );
429
421
 
430
422
  const startedSigSets = startedSetsDefault + startedSetsSameMessage;
423
+ if (workReqs.length === 0) {
424
+ worker.status = {code: WorkerStatusCode.idle, workerApi};
425
+ this.workersBusy--;
426
+ callInNextEventLoop(this.runJob);
427
+ return;
428
+ }
429
+
431
430
  this.metrics?.blsThreadPool.totalJobsGroupsStarted.inc(1);
432
431
  this.metrics?.blsThreadPool.totalJobsStarted.inc({type: JobQueueItemType.default}, startedJobsDefault);
433
432
  this.metrics?.blsThreadPool.totalJobsStarted.inc({type: JobQueueItemType.sameMessage}, startedJobsSameMessage);
@@ -435,13 +434,13 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
435
434
  this.metrics?.blsThreadPool.totalSigSetsStarted.inc({type: JobQueueItemType.sameMessage}, startedSetsSameMessage);
436
435
 
437
436
  // Send work package to the worker
438
- // If the job, metrics or any code below throws: the job will reject never going stale.
439
- // Only downside is the job promise may be resolved twice, but that's not an issue
437
+ // If worker communication or result processing throws, all unresolved jobs are rejected.
440
438
 
441
439
  const [jobStartSec, jobStartNs] = process.hrtime();
442
440
  const workResult = await workerApi.verifyManySignatureSets(workReqs);
443
441
  const [jobEndSec, jobEndNs] = process.hrtime();
444
- const {workerId, batchRetries, batchSigsSuccess, workerStartTime, workerEndTime, results} = workResult;
442
+ const {workerId, batchRetries, batchSigsSuccess, verificationCalls, workerStartTime, workerEndTime, results} =
443
+ workResult;
445
444
 
446
445
  const [workerStartSec, workerStartNs] = workerStartTime;
447
446
  const [workerEndSec, workerEndNs] = workerEndTime;
@@ -453,36 +452,14 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
453
452
  for (let i = 0; i < jobsStarted.length; i++) {
454
453
  const job = jobsStarted[i];
455
454
  const jobResult = results[i];
456
- const sigSetCount = jobItemSigSets(job);
457
-
458
- // TODO: enable exhaustive switch case checks lint rule
459
- switch (job.type) {
460
- case JobQueueItemType.default:
461
- if (!jobResult || jobResult.code !== WorkResultCode.success) {
462
- job.reject(getJobResultError(jobResult, i));
463
- errorCount += sigSetCount;
464
- } else {
465
- job.resolve(jobResult.result);
466
- successCount += sigSetCount;
467
- }
468
- break;
469
-
470
- // handle result of the verification of aggregated signature against aggregated pubkeys
471
- case JobQueueItemType.sameMessage:
472
- if (!jobResult || jobResult.code !== WorkResultCode.success) {
473
- job.reject(getJobResultError(jobResult, i));
474
- errorCount += 1;
475
- } else {
476
- if (jobResult.result) {
477
- // All are valid, most of the time it goes here
478
- job.resolve(job.sets.map(() => true));
479
- } else {
480
- // Retry each individually
481
- this.retryJobItemSameMessage(job);
482
- }
483
- successCount += 1;
484
- }
485
- break;
455
+ const signatureSets = jobItemSigSets(job);
456
+ const outcome = completeJob(job, jobResult, i, signatureSets);
457
+ completedJobsCount = i + 1;
458
+ this.observeJobCompletion(job, outcome);
459
+ if (outcome === "prepError" || outcome === "verifyError" || outcome === "workerError") {
460
+ errorCount += signatureSets;
461
+ } else {
462
+ successCount += signatureSets;
486
463
  }
487
464
  }
488
465
 
@@ -498,15 +475,24 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
498
475
  this.metrics?.blsThreadPool.errorJobsSignatureSetsCount.inc(errorCount);
499
476
  this.metrics?.blsThreadPool.batchRetries.inc(batchRetries);
500
477
  this.metrics?.blsThreadPool.batchSigsSuccess.inc(batchSigsSuccess);
478
+ for (const {operation, duration, signatureSets} of verificationCalls) {
479
+ this.metrics?.blsThreadPool.verificationCallDuration.observe({operation}, duration);
480
+ this.metrics?.blsThreadPool.verificationCallSignatureSets.inc({operation}, signatureSets);
481
+ }
501
482
  } catch (e) {
502
483
  // Worker communications should never reject
503
484
  if (!this.closed) {
504
485
  this.logger.error("BlsMultiThreadWorkerPool error", {}, e as Error);
505
486
  }
506
- // Reject all
507
- for (const job of jobsInput) {
487
+ // Reject jobs that were not already completed
488
+ let errorSignatureSets = 0;
489
+ for (let i = completedJobsCount; i < jobsStarted.length; i++) {
490
+ const job = jobsStarted[i];
491
+ this.observeJobCompletion(job, "workerError");
492
+ errorSignatureSets += jobItemSigSets(job);
508
493
  job.reject(e as Error);
509
494
  }
495
+ this.metrics?.blsThreadPool.errorJobsSignatureSetsCount.inc(errorSignatureSets);
510
496
  }
511
497
 
512
498
  worker.status = {code: WorkerStatusCode.idle, workerApi};
@@ -524,13 +510,19 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
524
510
  let totalSigs = 0;
525
511
 
526
512
  while (totalSigs < MAX_SIGNATURE_SETS_PER_JOB) {
527
- const job = this.jobs.shift();
513
+ const job = this.jobs.first();
528
514
  if (!job) {
529
515
  break;
530
516
  }
531
517
 
518
+ const jobSigSets = jobItemSigSets(job);
519
+ if (jobs.length > 0 && totalSigs + jobSigSets > MAX_SIGNATURE_SETS_PER_JOB) {
520
+ break;
521
+ }
522
+
523
+ this.jobs.shift();
532
524
  jobs.push(job);
533
- totalSigs += jobItemSigSets(job);
525
+ totalSigs += jobSigSets;
534
526
  }
535
527
 
536
528
  return jobs;
@@ -539,8 +531,10 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
539
531
  /**
540
532
  * Add all buffered jobs to the job queue and potentially run them immediately
541
533
  */
542
- private runBufferedJobs = (): void => {
534
+ private runBufferedJobs = (reason: BufferFlushReason): void => {
543
535
  if (this.bufferedJobs) {
536
+ this.metrics?.blsThreadPool.bufferFlushes.inc({reason});
537
+ this.metrics?.blsThreadPool.bufferedSignatureSets.observe(this.bufferedJobs.sigCount);
544
538
  for (const job of this.bufferedJobs.jobs) {
545
539
  this.jobs.push(job);
546
540
  }
@@ -552,17 +546,9 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
552
546
  }
553
547
  };
554
548
 
555
- private retryJobItemSameMessage(job: JobQueueItemSameMessage): void {
556
- // Create new jobs for each pubkey set, and Promise.all all the results
557
- for (const j of jobItemSameMessageToMultiSet(job)) {
558
- if (j.opts.priority) {
559
- this.jobs.unshift(j);
560
- } else {
561
- this.jobs.push(j);
562
- }
563
- }
564
- this.metrics?.blsThreadPool.sameMessageRetryJobs.inc(1);
565
- this.metrics?.blsThreadPool.sameMessageRetrySets.inc(job.sets.length);
549
+ private observeJobCompletion(job: JobQueueItem, outcome: BlsJobOutcome): void {
550
+ this.metrics?.blsThreadPool.jobDuration.observe(jobMetricLabels(job), (Date.now() - job.addedTimeMs) / 1000);
551
+ this.metrics?.blsThreadPool.jobResults.inc({type: job.type, outcome});
566
552
  }
567
553
 
568
554
  /** For testing */
@@ -577,8 +563,50 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
577
563
  }
578
564
  }
579
565
 
566
+ function completeJob(
567
+ job: JobQueueItem,
568
+ jobResult: WorkResult<boolean[]> | undefined,
569
+ index: number,
570
+ signatureSets: number
571
+ ): BlsJobOutcome {
572
+ if (!jobResult || jobResult.code !== WorkResultCode.success) {
573
+ job.reject(getJobResultError(jobResult ?? null, index));
574
+ return "verifyError";
575
+ }
576
+
577
+ switch (job.type) {
578
+ case JobQueueItemType.default: {
579
+ const [result] = jobResult.result;
580
+ if (jobResult.result.length !== 1 || result === undefined) {
581
+ job.reject(getInvalidResultLengthError(index, 1, jobResult.result.length));
582
+ return "workerError";
583
+ }
584
+
585
+ job.resolve(result);
586
+ return result ? "valid" : "invalid";
587
+ }
588
+
589
+ case JobQueueItemType.sameMessage:
590
+ if (jobResult.result.length !== signatureSets) {
591
+ job.reject(getInvalidResultLengthError(index, signatureSets, jobResult.result.length));
592
+ return "workerError";
593
+ }
594
+
595
+ job.resolve(jobResult.result);
596
+ return jobResult.result.every(Boolean) ? "valid" : "invalid";
597
+ }
598
+ }
599
+
600
+ function jobMetricLabels(job: JobQueueItem): {type: JobQueueItemType} {
601
+ return {type: job.type};
602
+ }
603
+
580
604
  function getJobResultError(jobResult: WorkResultError | null, i: number): Error {
581
605
  const workerError = jobResult ? Error(jobResult.error.message) : Error(`No jobResult for index ${i}`);
582
606
  if (jobResult?.error?.stack) workerError.stack = jobResult.error.stack;
583
607
  return workerError;
584
608
  }
609
+
610
+ function getInvalidResultLengthError(index: number, expected: number, actual: number): Error {
611
+ return Error(`Invalid BLS worker result length for index ${index}: expected ${expected}, got ${actual}`);
612
+ }
@@ -1,10 +1,6 @@
1
- import {PublicKey, asyncAggregateWithRandomness} from "@chainsafe/blst";
2
- import {ISignatureSet, PubkeyCache, SignatureSetType} from "@lodestar/state-transition";
3
- import {Metrics} from "../../../metrics/metrics.js";
4
- import {LinkedList} from "../../../util/array.js";
5
- import {VerifySignatureOpts} from "../interface.js";
6
- import {getAggregatedPubkey} from "../utils.js";
7
- import {BlsWorkReq} from "./types.js";
1
+ import {ISignatureSet, toBlsSignatureSet} from "@lodestar/state-transition";
2
+ import {SameMessageSignatureSet, VerifySignatureOpts} from "../interface.js";
3
+ import {BlsWorkReq, JobQueueItemType} from "./types.js";
8
4
 
9
5
  export type JobQueueItem = JobQueueItemDefault | JobQueueItemSameMessage;
10
6
 
@@ -23,101 +19,35 @@ export type JobQueueItemSameMessage = {
23
19
  reject: (error?: Error) => void;
24
20
  addedTimeMs: number;
25
21
  opts: VerifySignatureOpts;
26
- sets: {publicKey: PublicKey; signature: Uint8Array}[];
22
+ sets: SameMessageSignatureSet[];
27
23
  message: Uint8Array;
28
24
  };
29
25
 
30
- export enum JobQueueItemType {
31
- default = "default",
32
- sameMessage = "same_message",
33
- }
34
-
35
26
  /**
36
27
  * Return count of signature sets from a JobQueueItem
37
28
  */
38
29
  export function jobItemSigSets(job: JobQueueItem): number {
39
- switch (job.type) {
40
- case JobQueueItemType.default:
41
- return job.sets.length;
42
- case JobQueueItemType.sameMessage:
43
- return 1;
44
- }
30
+ return job.sets.length;
45
31
  }
46
32
 
47
33
  /**
48
34
  * Prepare BlsWorkReq from JobQueueItem
49
35
  * WARNING: May throw with untrusted user input
50
36
  */
51
- export async function jobItemWorkReq(
52
- job: JobQueueItem,
53
- pubkeyCache: PubkeyCache,
54
- metrics: Metrics | null
55
- ): Promise<BlsWorkReq> {
37
+ export function jobItemWorkReq(job: JobQueueItem): BlsWorkReq {
56
38
  switch (job.type) {
57
39
  case JobQueueItemType.default:
58
40
  return {
41
+ type: JobQueueItemType.default,
59
42
  opts: job.opts,
60
- sets: job.sets.map((set) => ({
61
- // this can throw, handled in the consumer code
62
- publicKey: getAggregatedPubkey(set, pubkeyCache, metrics).toBytes(),
63
- signature: set.signature,
64
- message: set.signingRoot,
65
- })),
43
+ sets: job.sets.map(toBlsSignatureSet),
66
44
  };
67
- case JobQueueItemType.sameMessage: {
68
- const timer = metrics?.blsThreadPool.aggregateWithRandomnessAsyncDuration.startTimer();
69
- const {pk, sig} = await asyncAggregateWithRandomness(
70
- job.sets.map((set) => ({pk: set.publicKey, sig: set.signature}))
71
- );
72
- timer?.();
73
-
45
+ case JobQueueItemType.sameMessage:
74
46
  return {
47
+ type: JobQueueItemType.sameMessage,
75
48
  opts: job.opts,
76
- sets: [
77
- {
78
- publicKey: pk.toBytes(),
79
- signature: sig.toBytes(),
80
- message: job.message,
81
- },
82
- ],
49
+ sets: job.sets,
50
+ message: job.message,
83
51
  };
84
- }
85
52
  }
86
53
  }
87
-
88
- /**
89
- * Convert a JobQueueItemSameMessage into multiple JobQueueItemDefault linked to the original promise
90
- */
91
- export function jobItemSameMessageToMultiSet(job: JobQueueItemSameMessage): LinkedList<JobQueueItemDefault> {
92
- // Retry each individually
93
- // Create new jobs for each pubkey set, and Promise.all all the results
94
- const promises: Promise<boolean>[] = [];
95
- const jobs = new LinkedList<JobQueueItemDefault>();
96
-
97
- for (const set of job.sets) {
98
- promises.push(
99
- new Promise<boolean>((resolve, reject) => {
100
- jobs.push({
101
- type: JobQueueItemType.default,
102
- resolve,
103
- reject,
104
- addedTimeMs: job.addedTimeMs,
105
- opts: {batchable: false, priority: job.opts.priority},
106
- sets: [
107
- {
108
- type: SignatureSetType.single,
109
- pubkey: set.publicKey,
110
- signature: set.signature,
111
- signingRoot: job.message,
112
- },
113
- ],
114
- });
115
- })
116
- );
117
- }
118
-
119
- // Connect jobs to main job
120
- Promise.all(promises).then(job.resolve, job.reject);
121
-
122
- return jobs;
123
- }
@@ -1,25 +1,48 @@
1
- import {VerifySignatureOpts} from "../interface.js";
1
+ import {type BlsSignatureSet} from "@chainsafe/lodestar-z/bls-verifier";
2
+ import {SameMessageSignatureSet, VerifySignatureOpts} from "../interface.js";
2
3
 
3
4
  export type WorkerData = {
4
5
  workerId: number;
5
6
  };
6
7
 
7
- export type SerializedSet = {
8
- publicKey: Uint8Array;
9
- message: Uint8Array;
10
- signature: Uint8Array;
8
+ export enum JobQueueItemType {
9
+ default = "default",
10
+ sameMessage = "same_message",
11
+ }
12
+
13
+ export type BlsWorkReqDefault = {
14
+ type: JobQueueItemType.default;
15
+ opts: VerifySignatureOpts;
16
+ sets: BlsSignatureSet[];
11
17
  };
12
18
 
13
- export type BlsWorkReq = {
19
+ export type BlsWorkReqSameMessage = {
20
+ type: JobQueueItemType.sameMessage;
14
21
  opts: VerifySignatureOpts;
15
- sets: SerializedSet[];
22
+ sets: SameMessageSignatureSet[];
23
+ message: Uint8Array;
16
24
  };
17
25
 
26
+ export type BlsWorkReq = BlsWorkReqDefault | BlsWorkReqSameMessage;
27
+
18
28
  export enum WorkResultCode {
19
29
  success = "success",
20
30
  error = "error",
21
31
  }
22
32
 
33
+ export enum VerificationCallOperation {
34
+ batch = "batch",
35
+ single = "single",
36
+ fallback = "fallback",
37
+ sameMessage = "same_message",
38
+ }
39
+
40
+ export type VerificationCall = {
41
+ operation: VerificationCallOperation;
42
+ duration: number;
43
+ signatureSets: number;
44
+ };
45
+
23
46
  export type WorkResultError = {code: WorkResultCode.error; error: Error};
24
47
  export type WorkResult<R> = {code: WorkResultCode.success; result: R} | WorkResultError;
25
48
 
@@ -30,9 +53,11 @@ export type BlsWorkResult = {
30
53
  batchRetries: number;
31
54
  /** Total num of sigs that have been successfully verified with batching */
32
55
  batchSigsSuccess: number;
56
+ /** Every lodestar-z verification call made while processing this work group */
57
+ verificationCalls: VerificationCall[];
33
58
  /** Time worker function starts - UNIX timestamp in seconds and nanoseconds */
34
59
  workerStartTime: [number, number];
35
60
  /** Time worker function ends - UNIX timestamp in seconds and nanoseconds */
36
61
  workerEndTime: [number, number];
37
- results: WorkResult<boolean>[];
62
+ results: WorkResult<boolean[]>[];
38
63
  };