@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.
- package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/blocks/index.js +4 -7
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/pool/index.js +12 -1
- package/lib/api/impl/beacon/pool/index.js.map +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts +2 -1
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/utils.js.map +1 -1
- package/lib/api/impl/events/index.d.ts +1 -1
- package/lib/api/impl/events/index.d.ts.map +1 -1
- package/lib/api/impl/events/index.js +10 -3
- package/lib/api/impl/events/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +12 -22
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/api/impl/validator/utils.d.ts +5 -0
- package/lib/api/impl/validator/utils.d.ts.map +1 -1
- package/lib/api/impl/validator/utils.js +18 -12
- package/lib/api/impl/validator/utils.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/metrics.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/metrics.js +21 -0
- package/lib/chain/archiveStore/historicalState/metrics.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +2 -7
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +3 -2
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +11 -9
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +15 -7
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js +22 -12
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js.map +1 -1
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +2 -2
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +2 -2
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -1
- package/lib/chain/bls/index.d.ts +1 -1
- package/lib/chain/bls/index.d.ts.map +1 -1
- package/lib/chain/bls/interface.d.ts +5 -5
- package/lib/chain/bls/interface.d.ts.map +1 -1
- package/lib/chain/bls/multithread/index.d.ts +5 -11
- package/lib/chain/bls/multithread/index.d.ts.map +1 -1
- package/lib/chain/bls/multithread/index.js +116 -101
- package/lib/chain/bls/multithread/index.js.map +1 -1
- package/lib/chain/bls/multithread/jobItem.d.ts +5 -19
- package/lib/chain/bls/multithread/jobItem.d.ts.map +1 -1
- package/lib/chain/bls/multithread/jobItem.js +10 -65
- package/lib/chain/bls/multithread/jobItem.js.map +1 -1
- package/lib/chain/bls/multithread/types.d.ts +29 -8
- package/lib/chain/bls/multithread/types.d.ts.map +1 -1
- package/lib/chain/bls/multithread/types.js +12 -0
- package/lib/chain/bls/multithread/types.js.map +1 -1
- package/lib/chain/bls/multithread/utils.d.ts +4 -0
- package/lib/chain/bls/multithread/utils.d.ts.map +1 -1
- package/lib/chain/bls/multithread/utils.js +10 -0
- package/lib/chain/bls/multithread/utils.js.map +1 -1
- package/lib/chain/bls/multithread/worker.js +49 -23
- package/lib/chain/bls/multithread/worker.js.map +1 -1
- package/lib/chain/bls/singleThread.d.ts +4 -10
- package/lib/chain/bls/singleThread.d.ts.map +1 -1
- package/lib/chain/bls/singleThread.js +8 -45
- package/lib/chain/bls/singleThread.js.map +1 -1
- package/lib/chain/bls/utils.d.ts +4 -4
- package/lib/chain/bls/utils.d.ts.map +1 -1
- package/lib/chain/bls/utils.js +18 -19
- package/lib/chain/bls/utils.js.map +1 -1
- package/lib/chain/builderCircuitBreaker.d.ts +6 -5
- package/lib/chain/builderCircuitBreaker.d.ts.map +1 -1
- package/lib/chain/builderCircuitBreaker.js +28 -15
- package/lib/chain/builderCircuitBreaker.js.map +1 -1
- package/lib/chain/chain.d.ts +3 -2
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +8 -5
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/errors/blockError.d.ts +2 -0
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js +6 -1
- package/lib/chain/errors/blockError.js.map +1 -1
- package/lib/chain/errors/proposerPreferences.d.ts +6 -0
- package/lib/chain/errors/proposerPreferences.d.ts.map +1 -1
- package/lib/chain/errors/proposerPreferences.js +1 -0
- package/lib/chain/errors/proposerPreferences.js.map +1 -1
- package/lib/chain/interface.d.ts +2 -1
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/opPools/attestationPool.d.ts +1 -1
- package/lib/chain/opPools/attestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/attestationPool.js +1 -1
- package/lib/chain/opPools/attestationPool.js.map +1 -1
- package/lib/chain/opPools/payloadAttestationPool.js +3 -3
- package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
- package/lib/chain/opPools/syncCommitteeMessagePool.js +1 -1
- package/lib/chain/opPools/syncCommitteeMessagePool.js.map +1 -1
- package/lib/chain/opPools/syncContributionAndProofPool.js +1 -1
- package/lib/chain/opPools/syncContributionAndProofPool.js.map +1 -1
- package/lib/chain/opPools/utils.d.ts +1 -1
- package/lib/chain/opPools/utils.d.ts.map +1 -1
- package/lib/chain/opPools/utils.js +1 -1
- package/lib/chain/opPools/utils.js.map +1 -1
- package/lib/chain/options.d.ts +1 -1
- package/lib/chain/options.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +1 -1
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +2 -0
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +6 -1
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/seenCache/seenAttesters.d.ts +9 -5
- package/lib/chain/seenCache/seenAttesters.d.ts.map +1 -1
- package/lib/chain/seenCache/seenAttesters.js +25 -4
- package/lib/chain/seenCache/seenAttesters.js.map +1 -1
- package/lib/chain/seenCache/seenBlockProposers.d.ts +5 -1
- package/lib/chain/seenCache/seenBlockProposers.d.ts.map +1 -1
- package/lib/chain/seenCache/seenBlockProposers.js +10 -3
- package/lib/chain/seenCache/seenBlockProposers.js.map +1 -1
- package/lib/chain/validation/attestation.d.ts.map +1 -1
- package/lib/chain/validation/attestation.js +1 -4
- package/lib/chain/validation/attestation.js.map +1 -1
- package/lib/chain/validation/attesterSlashing.d.ts.map +1 -1
- package/lib/chain/validation/attesterSlashing.js +1 -1
- package/lib/chain/validation/attesterSlashing.js.map +1 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +21 -7
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +1 -2
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.js +5 -14
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/chain/validation/proposerPreferences.d.ts +1 -1
- package/lib/chain/validation/proposerPreferences.d.ts.map +1 -1
- package/lib/chain/validation/proposerPreferences.js +13 -4
- package/lib/chain/validation/proposerPreferences.js.map +1 -1
- package/lib/chain/validation/proposerSlashing.js +1 -1
- package/lib/chain/validation/proposerSlashing.js.map +1 -1
- package/lib/execution/builder/http.d.ts +10 -7
- package/lib/execution/builder/http.d.ts.map +1 -1
- package/lib/execution/builder/http.js +11 -8
- package/lib/execution/builder/http.js.map +1 -1
- package/lib/metrics/metrics/beacon.d.ts +3 -3
- package/lib/metrics/metrics/beacon.d.ts.map +1 -1
- package/lib/metrics/metrics/beacon.js +9 -9
- package/lib/metrics/metrics/beacon.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +48 -18
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +96 -50
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +13 -0
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/gossip/topic.js +37 -0
- package/lib/network/gossip/topic.js.map +1 -1
- package/lib/network/libp2p/index.d.ts.map +1 -1
- package/lib/network/libp2p/index.js +10 -2
- package/lib/network/libp2p/index.js.map +1 -1
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +22 -43
- package/lib/network/network.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +32 -5
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/reqresp/score.d.ts.map +1 -1
- package/lib/network/reqresp/score.js +5 -11
- package/lib/network/reqresp/score.js.map +1 -1
- package/lib/network/util.d.ts +0 -1
- package/lib/network/util.d.ts.map +1 -1
- package/lib/network/util.js +0 -4
- package/lib/network/util.js.map +1 -1
- package/lib/node/nodejs.d.ts +2 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js.map +1 -1
- package/lib/sync/range/batch.d.ts +23 -5
- package/lib/sync/range/batch.d.ts.map +1 -1
- package/lib/sync/range/batch.js +61 -22
- package/lib/sync/range/batch.js.map +1 -1
- package/lib/sync/range/chain.d.ts +2 -1
- package/lib/sync/range/chain.d.ts.map +1 -1
- package/lib/sync/range/chain.js +23 -10
- package/lib/sync/range/chain.js.map +1 -1
- package/lib/sync/types.d.ts.map +1 -1
- package/lib/sync/types.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts +9 -0
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +110 -14
- package/lib/sync/unknownBlock.js.map +1 -1
- package/package.json +18 -18
- package/src/api/impl/beacon/blocks/index.ts +5 -7
- package/src/api/impl/beacon/pool/index.ts +12 -1
- package/src/api/impl/beacon/state/utils.ts +2 -1
- package/src/api/impl/events/index.ts +10 -4
- package/src/api/impl/validator/index.ts +22 -27
- package/src/api/impl/validator/utils.ts +30 -15
- package/src/chain/archiveStore/historicalState/metrics.ts +22 -0
- package/src/chain/blocks/importBlock.ts +1 -6
- package/src/chain/blocks/importExecutionPayload.ts +12 -11
- package/src/chain/blocks/index.ts +19 -7
- package/src/chain/blocks/verifyBlocksStateTransitionOnly.ts +25 -16
- package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +1 -9
- package/src/chain/bls/index.ts +1 -1
- package/src/chain/bls/interface.ts +7 -3
- package/src/chain/bls/multithread/index.ts +148 -120
- package/src/chain/bls/multithread/jobItem.ts +12 -82
- package/src/chain/bls/multithread/types.ts +33 -8
- package/src/chain/bls/multithread/utils.ts +11 -0
- package/src/chain/bls/multithread/worker.ts +85 -27
- package/src/chain/bls/singleThread.ts +11 -55
- package/src/chain/bls/utils.ts +23 -24
- package/src/chain/builderCircuitBreaker.ts +31 -17
- package/src/chain/chain.ts +9 -5
- package/src/chain/errors/blockError.ts +9 -3
- package/src/chain/errors/proposerPreferences.ts +7 -0
- package/src/chain/interface.ts +2 -1
- package/src/chain/opPools/aggregatedAttestationPool.ts +1 -1
- package/src/chain/opPools/attestationPool.ts +1 -1
- package/src/chain/opPools/payloadAttestationPool.ts +3 -3
- package/src/chain/opPools/syncCommitteeMessagePool.ts +1 -1
- package/src/chain/opPools/syncContributionAndProofPool.ts +1 -1
- package/src/chain/opPools/utils.ts +1 -1
- package/src/chain/options.ts +1 -1
- package/src/chain/prepareNextSlot.ts +1 -1
- package/src/chain/produceBlock/produceBlockBody.ts +13 -0
- package/src/chain/seenCache/seenAttesters.ts +31 -5
- package/src/chain/seenCache/seenBlockProposers.ts +13 -3
- package/src/chain/validation/attestation.ts +1 -7
- package/src/chain/validation/attesterSlashing.ts +1 -8
- package/src/chain/validation/block.ts +21 -7
- package/src/chain/validation/executionPayloadBid.ts +1 -2
- package/src/chain/validation/executionPayloadEnvelope.ts +0 -1
- package/src/chain/validation/payloadAttestationMessage.ts +6 -17
- package/src/chain/validation/proposerPreferences.ts +15 -5
- package/src/chain/validation/proposerSlashing.ts +1 -1
- package/src/execution/builder/http.ts +11 -11
- package/src/metrics/metrics/beacon.ts +9 -9
- package/src/metrics/metrics/lodestar.ts +101 -51
- package/src/network/gossip/topic.ts +38 -0
- package/src/network/libp2p/index.ts +11 -2
- package/src/network/network.ts +27 -55
- package/src/network/processor/gossipHandlers.ts +35 -3
- package/src/network/reqresp/score.ts +5 -11
- package/src/network/util.ts +0 -5
- package/src/node/nodejs.ts +2 -1
- package/src/sync/range/batch.ts +83 -28
- package/src/sync/range/chain.ts +26 -11
- package/src/sync/types.ts +3 -1
- package/src/sync/unknownBlock.ts +126 -17
- package/lib/chain/bls/maybeBatch.d.ts +0 -12
- package/lib/chain/bls/maybeBatch.d.ts.map +0 -1
- package/lib/chain/bls/maybeBatch.js +0 -35
- package/lib/chain/bls/maybeBatch.js.map +0 -1
- 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 {
|
|
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 {
|
|
18
|
-
import {
|
|
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
|
-
|
|
21
|
-
|
|
20
|
+
BlsWorkReq,
|
|
21
|
+
BlsWorkResult,
|
|
22
22
|
JobQueueItemType,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
import {
|
|
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
|
-
*
|
|
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.
|
|
73
|
-
*
|
|
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
|
|
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
|
|
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
|
-
|
|
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:
|
|
207
|
+
sets: SameMessageSignatureSet[],
|
|
217
208
|
message: Uint8Array,
|
|
218
209
|
opts: Omit<VerifySignatureOpts, "verifyOnMainThread"> = {}
|
|
219
210
|
): Promise<boolean[]> {
|
|
220
|
-
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
(
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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
|
-
|
|
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.
|
|
403
|
-
|
|
404
|
-
|
|
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
|
|
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} =
|
|
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
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
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
|
|
507
|
-
|
|
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.
|
|
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 +=
|
|
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
|
|
556
|
-
|
|
557
|
-
|
|
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 {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
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:
|
|
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
|
-
|
|
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
|
|
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(
|
|
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 {
|
|
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
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
|
19
|
+
export type BlsWorkReqSameMessage = {
|
|
20
|
+
type: JobQueueItemType.sameMessage;
|
|
14
21
|
opts: VerifySignatureOpts;
|
|
15
|
-
sets:
|
|
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
|
};
|