@lodestar/beacon-node 1.47.0-dev.09607ce6d4 → 1.47.0-dev.101e2c290d
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 +3 -2
- 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 +21 -2
- 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 +12 -3
- package/lib/api/impl/events/index.js.map +1 -1
- package/lib/api/impl/lodestar/index.js +1 -1
- package/lib/api/impl/lodestar/index.js.map +1 -1
- package/lib/api/rest/base.d.ts.map +1 -1
- package/lib/api/rest/base.js +7 -0
- package/lib/api/rest/base.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +1 -1
- package/lib/chain/archiveStore/archiveStore.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 +14 -6
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +2 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +6 -2
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +14 -5
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.js +5 -0
- package/lib/chain/blocks/payloadEnvelopeInput/types.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/chain.d.ts +4 -2
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +16 -6
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/errors/blockError.d.ts +1 -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/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +4 -0
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +4 -2
- 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/deferredVoluntaryExitPool.d.ts +16 -0
- package/lib/chain/opPools/deferredVoluntaryExitPool.d.ts.map +1 -0
- package/lib/chain/opPools/deferredVoluntaryExitPool.js +57 -0
- package/lib/chain/opPools/deferredVoluntaryExitPool.js.map +1 -0
- package/lib/chain/opPools/index.d.ts +1 -0
- package/lib/chain/opPools/index.d.ts.map +1 -1
- package/lib/chain/opPools/index.js +1 -0
- package/lib/chain/opPools/index.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/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +23 -5
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +4 -2
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/interface.js +2 -0
- package/lib/chain/regen/interface.js.map +1 -1
- package/lib/chain/regen/queued.d.ts +2 -2
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +5 -5
- package/lib/chain/regen/queued.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/seenPayloadEnvelopeInput.d.ts +28 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +121 -13
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts +5 -1
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.js +6 -0
- package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +47 -5
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +117 -7
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/types.d.ts +3 -3
- package/lib/chain/stateCache/types.d.ts.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/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/chain/validation/voluntaryExit.d.ts +9 -1
- package/lib/chain/validation/voluntaryExit.d.ts.map +1 -1
- package/lib/chain/validation/voluntaryExit.js +46 -1
- package/lib/chain/validation/voluntaryExit.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +62 -22
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +114 -52
- 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/constants.d.ts +7 -0
- package/lib/network/processor/constants.d.ts.map +1 -0
- package/lib/network/processor/constants.js +7 -0
- package/lib/network/processor/constants.js.map +1 -0
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +5 -1
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/index.d.ts +3 -0
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +36 -15
- package/lib/network/processor/index.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/deferredVoluntaryExitPublisher.d.ts +15 -0
- package/lib/node/deferredVoluntaryExitPublisher.d.ts.map +1 -0
- package/lib/node/deferredVoluntaryExitPublisher.js +38 -0
- package/lib/node/deferredVoluntaryExitPublisher.js.map +1 -0
- package/lib/node/nodejs.d.ts +2 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +2 -0
- 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 +32 -0
- package/lib/sync/types.d.ts.map +1 -1
- package/lib/sync/types.js +33 -0
- package/lib/sync/types.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts +13 -2
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +204 -61
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +16 -11
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRoot.js +3 -1
- package/lib/sync/utils/downloadByRoot.js.map +1 -1
- package/package.json +35 -35
- package/src/api/impl/beacon/blocks/index.ts +3 -2
- package/src/api/impl/beacon/pool/index.ts +22 -2
- package/src/api/impl/beacon/state/utils.ts +2 -1
- package/src/api/impl/events/index.ts +12 -4
- package/src/api/impl/lodestar/index.ts +1 -1
- package/src/api/rest/base.ts +7 -0
- package/src/chain/archiveStore/archiveStore.ts +1 -1
- package/src/chain/blocks/importExecutionPayload.ts +12 -11
- package/src/chain/blocks/index.ts +18 -6
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +8 -2
- package/src/chain/blocks/payloadEnvelopeInput/types.ts +17 -4
- 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/chain.ts +17 -6
- package/src/chain/errors/blockError.ts +8 -2
- package/src/chain/errors/proposerPreferences.ts +7 -0
- package/src/chain/forkChoice/index.ts +4 -0
- package/src/chain/interface.ts +4 -1
- package/src/chain/opPools/aggregatedAttestationPool.ts +1 -1
- package/src/chain/opPools/attestationPool.ts +1 -1
- package/src/chain/opPools/deferredVoluntaryExitPool.ts +65 -0
- package/src/chain/opPools/index.ts +1 -0
- 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/prepareNextSlot.ts +23 -5
- package/src/chain/regen/interface.ts +4 -2
- package/src/chain/regen/queued.ts +5 -5
- package/src/chain/seenCache/seenAttesters.ts +31 -5
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +143 -14
- package/src/chain/stateCache/fifoBlockStateCache.ts +8 -1
- package/src/chain/stateCache/persistentCheckpointsCache.ts +133 -8
- package/src/chain/stateCache/types.ts +3 -3
- package/src/chain/validation/attestation.ts +1 -7
- package/src/chain/validation/attesterSlashing.ts +1 -8
- 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/chain/validation/voluntaryExit.ts +59 -2
- package/src/metrics/metrics/lodestar.ts +126 -57
- 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/constants.ts +6 -0
- package/src/network/processor/gossipHandlers.ts +5 -1
- package/src/network/processor/index.ts +42 -19
- package/src/network/reqresp/score.ts +5 -11
- package/src/network/util.ts +0 -5
- package/src/node/deferredVoluntaryExitPublisher.ts +54 -0
- package/src/node/nodejs.ts +5 -1
- package/src/sync/range/batch.ts +83 -28
- package/src/sync/range/chain.ts +26 -11
- package/src/sync/types.ts +36 -1
- package/src/sync/unknownBlock.ts +240 -68
- package/src/sync/utils/downloadByRange.ts +21 -12
- package/src/sync/utils/downloadByRoot.ts +3 -1
- 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
|
@@ -17,3 +17,14 @@ export function chunkifyMaximizeChunkSize<T>(arr: T[], minPerChunk: number): T[]
|
|
|
17
17
|
|
|
18
18
|
return arrArr;
|
|
19
19
|
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Splits an array into chunks that do not exceed a maximum size.
|
|
23
|
+
*/
|
|
24
|
+
export function chunkifyMaxChunkSize<T>(arr: T[], maxPerChunk: number): T[][] {
|
|
25
|
+
const chunks: T[][] = [];
|
|
26
|
+
for (let i = 0; i < arr.length; i += maxPerChunk) {
|
|
27
|
+
chunks.push(arr.slice(i, i + maxPerChunk));
|
|
28
|
+
}
|
|
29
|
+
return chunks;
|
|
30
|
+
}
|
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
import worker from "node:worker_threads";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
type BlsSignatureSet,
|
|
4
|
+
verifySignatureSets,
|
|
5
|
+
verifySignatureSetsSameMessage,
|
|
6
|
+
} from "@chainsafe/lodestar-z/bls-verifier";
|
|
3
7
|
import {expose} from "@chainsafe/threads/worker";
|
|
4
|
-
import {
|
|
5
|
-
|
|
8
|
+
import {
|
|
9
|
+
BlsWorkReq,
|
|
10
|
+
BlsWorkResult,
|
|
11
|
+
JobQueueItemType,
|
|
12
|
+
VerificationCall,
|
|
13
|
+
VerificationCallOperation,
|
|
14
|
+
WorkResult,
|
|
15
|
+
WorkResultCode,
|
|
16
|
+
WorkerData,
|
|
17
|
+
} from "./types.js";
|
|
6
18
|
import {chunkifyMaximizeChunkSize} from "./utils.js";
|
|
7
19
|
|
|
8
20
|
/**
|
|
@@ -27,23 +39,45 @@ expose({
|
|
|
27
39
|
|
|
28
40
|
function verifyManySignatureSets(workReqArr: BlsWorkReq[]): BlsWorkResult {
|
|
29
41
|
const [startSec, startNs] = process.hrtime();
|
|
30
|
-
const results: WorkResult<boolean>[] = [];
|
|
42
|
+
const results: WorkResult<boolean[]>[] = [];
|
|
43
|
+
const verificationCalls: VerificationCall[] = [];
|
|
31
44
|
let batchRetries = 0;
|
|
32
45
|
let batchSigsSuccess = 0;
|
|
33
46
|
|
|
34
47
|
// If there are multiple batchable sets attempt batch verification with them
|
|
35
|
-
const batchableSets: {idx: number; sets:
|
|
36
|
-
const nonBatchableSets: {
|
|
48
|
+
const batchableSets: {idx: number; sets: BlsSignatureSet[]}[] = [];
|
|
49
|
+
const nonBatchableSets: {
|
|
50
|
+
idx: number;
|
|
51
|
+
sets: BlsSignatureSet[];
|
|
52
|
+
operation: VerificationCallOperation.single | VerificationCallOperation.fallback;
|
|
53
|
+
}[] = [];
|
|
37
54
|
|
|
38
55
|
// Split sets between batchable and non-batchable preserving their original index in the req array
|
|
39
56
|
for (let i = 0; i < workReqArr.length; i++) {
|
|
40
57
|
const workReq = workReqArr[i];
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
58
|
+
switch (workReq.type) {
|
|
59
|
+
case JobQueueItemType.default: {
|
|
60
|
+
const {sets} = workReq;
|
|
61
|
+
if (workReq.opts.batchable) {
|
|
62
|
+
batchableSets.push({idx: i, sets});
|
|
63
|
+
} else {
|
|
64
|
+
nonBatchableSets.push({idx: i, sets, operation: VerificationCallOperation.single});
|
|
65
|
+
}
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
case JobQueueItemType.sameMessage:
|
|
69
|
+
try {
|
|
70
|
+
const result = recordVerificationCall(
|
|
71
|
+
verificationCalls,
|
|
72
|
+
VerificationCallOperation.sameMessage,
|
|
73
|
+
workReq.sets.length,
|
|
74
|
+
() => verifySignatureSetsSameMessage(workReq.sets, workReq.message)
|
|
75
|
+
);
|
|
76
|
+
results[i] = {code: WorkResultCode.success, result};
|
|
77
|
+
} catch (e) {
|
|
78
|
+
results[i] = {code: WorkResultCode.error, error: e as Error};
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
47
81
|
}
|
|
48
82
|
}
|
|
49
83
|
|
|
@@ -52,7 +86,7 @@ function verifyManySignatureSets(workReqArr: BlsWorkReq[]): BlsWorkResult {
|
|
|
52
86
|
const batchableChunks = chunkifyMaximizeChunkSize(batchableSets, BATCHABLE_MIN_PER_CHUNK);
|
|
53
87
|
|
|
54
88
|
for (const batchableChunk of batchableChunks) {
|
|
55
|
-
const allSets:
|
|
89
|
+
const allSets: BlsSignatureSet[] = [];
|
|
56
90
|
for (const {sets} of batchableChunk) {
|
|
57
91
|
for (const set of sets) {
|
|
58
92
|
allSets.push(set);
|
|
@@ -61,33 +95,49 @@ function verifyManySignatureSets(workReqArr: BlsWorkReq[]): BlsWorkResult {
|
|
|
61
95
|
|
|
62
96
|
try {
|
|
63
97
|
// Attempt to verify multiple sets at once
|
|
64
|
-
const isValid =
|
|
98
|
+
const isValid = recordVerificationCall(verificationCalls, VerificationCallOperation.batch, allSets.length, () =>
|
|
99
|
+
verifySignatureSets(allSets)
|
|
100
|
+
);
|
|
65
101
|
|
|
66
102
|
if (isValid) {
|
|
67
103
|
// The entire batch is valid, return success to all
|
|
68
104
|
for (const {idx, sets} of batchableChunk) {
|
|
69
105
|
batchSigsSuccess += sets.length;
|
|
70
|
-
results[idx] = {code: WorkResultCode.success, result: isValid};
|
|
106
|
+
results[idx] = {code: WorkResultCode.success, result: [isValid]};
|
|
71
107
|
}
|
|
72
108
|
} else {
|
|
73
109
|
batchRetries++;
|
|
74
110
|
// Re-verify all sigs
|
|
75
|
-
nonBatchableSets.push(
|
|
111
|
+
nonBatchableSets.push(
|
|
112
|
+
...batchableChunk.map(({idx, sets}) => ({
|
|
113
|
+
idx,
|
|
114
|
+
sets,
|
|
115
|
+
operation: VerificationCallOperation.fallback as const,
|
|
116
|
+
}))
|
|
117
|
+
);
|
|
76
118
|
}
|
|
77
119
|
} catch (_e) {
|
|
78
120
|
// TODO: Ignore this error expecting that the same error will happen when re-verifying the set individually
|
|
79
|
-
// It's not ideal but
|
|
121
|
+
// It's not ideal but the BLS implementation may throw errors on some conditions
|
|
80
122
|
batchRetries++;
|
|
81
123
|
// Re-verify all sigs
|
|
82
|
-
nonBatchableSets.push(
|
|
124
|
+
nonBatchableSets.push(
|
|
125
|
+
...batchableChunk.map(({idx, sets}) => ({
|
|
126
|
+
idx,
|
|
127
|
+
sets,
|
|
128
|
+
operation: VerificationCallOperation.fallback as const,
|
|
129
|
+
}))
|
|
130
|
+
);
|
|
83
131
|
}
|
|
84
132
|
}
|
|
85
133
|
}
|
|
86
134
|
|
|
87
|
-
for (const {idx, sets} of nonBatchableSets) {
|
|
135
|
+
for (const {idx, sets, operation} of nonBatchableSets) {
|
|
88
136
|
try {
|
|
89
|
-
const isValid =
|
|
90
|
-
|
|
137
|
+
const isValid = recordVerificationCall(verificationCalls, operation, sets.length, () =>
|
|
138
|
+
verifySignatureSets(sets)
|
|
139
|
+
);
|
|
140
|
+
results[idx] = {code: WorkResultCode.success, result: [isValid]};
|
|
91
141
|
} catch (e) {
|
|
92
142
|
results[idx] = {code: WorkResultCode.error, error: e as Error};
|
|
93
143
|
}
|
|
@@ -99,16 +149,24 @@ function verifyManySignatureSets(workReqArr: BlsWorkReq[]): BlsWorkResult {
|
|
|
99
149
|
workerId,
|
|
100
150
|
batchRetries,
|
|
101
151
|
batchSigsSuccess,
|
|
152
|
+
verificationCalls,
|
|
102
153
|
workerStartTime: [startSec, startNs],
|
|
103
154
|
workerEndTime: [workerEndSec, workerEndNs],
|
|
104
155
|
results,
|
|
105
156
|
};
|
|
106
157
|
}
|
|
107
158
|
|
|
108
|
-
function
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
159
|
+
function recordVerificationCall<T>(
|
|
160
|
+
calls: VerificationCall[],
|
|
161
|
+
operation: VerificationCallOperation,
|
|
162
|
+
signatureSets: number,
|
|
163
|
+
verify: () => T
|
|
164
|
+
): T {
|
|
165
|
+
const startTime = process.hrtime();
|
|
166
|
+
try {
|
|
167
|
+
return verify();
|
|
168
|
+
} finally {
|
|
169
|
+
const [seconds, nanoseconds] = process.hrtime(startTime);
|
|
170
|
+
calls.push({operation, signatureSets, duration: seconds + nanoseconds / 1e9});
|
|
171
|
+
}
|
|
114
172
|
}
|
|
@@ -1,31 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {ISignatureSet
|
|
1
|
+
import {verifySignatureSetsSameMessage} from "@chainsafe/lodestar-z/bls-verifier";
|
|
2
|
+
import {ISignatureSet} from "@lodestar/state-transition";
|
|
3
3
|
import {Metrics} from "../../metrics/index.js";
|
|
4
|
-
import {IBlsVerifier} from "./interface.js";
|
|
5
|
-
import {
|
|
6
|
-
import {getAggregatedPubkey, getAggregatedPubkeysCount} from "./utils.js";
|
|
4
|
+
import {IBlsVerifier, SameMessageSignatureSet} from "./interface.js";
|
|
5
|
+
import {chunkSameMessageSignatureSets, getAggregatedPubkeysCount, verifySignatureSetsInBatches} from "./utils.js";
|
|
7
6
|
|
|
8
7
|
export class BlsSingleThreadVerifier implements IBlsVerifier {
|
|
9
8
|
private readonly metrics: Metrics | null;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
constructor({metrics = null, pubkeyCache}: {metrics: Metrics | null; pubkeyCache: PubkeyCache}) {
|
|
9
|
+
constructor({metrics = null}: {metrics: Metrics | null}) {
|
|
13
10
|
this.metrics = metrics;
|
|
14
|
-
this.pubkeyCache = pubkeyCache;
|
|
15
11
|
}
|
|
16
12
|
|
|
17
13
|
async verifySignatureSets(sets: ISignatureSet[]): Promise<boolean> {
|
|
18
14
|
this.metrics?.bls.aggregatedPubkeys.inc(getAggregatedPubkeysCount(sets));
|
|
19
15
|
|
|
20
|
-
const setsAggregated = sets.map((set) => ({
|
|
21
|
-
publicKey: getAggregatedPubkey(set, this.pubkeyCache, this.metrics),
|
|
22
|
-
message: set.signingRoot,
|
|
23
|
-
signature: set.signature,
|
|
24
|
-
}));
|
|
25
|
-
|
|
26
|
-
// Count time after aggregating
|
|
27
16
|
const timer = this.metrics?.blsThreadPool.mainThreadDurationInThreadPool.startTimer();
|
|
28
|
-
const isValid =
|
|
17
|
+
const isValid = verifySignatureSetsInBatches(sets);
|
|
29
18
|
|
|
30
19
|
// Don't use a try/catch, only count run without exceptions
|
|
31
20
|
if (timer) {
|
|
@@ -35,46 +24,13 @@ export class BlsSingleThreadVerifier implements IBlsVerifier {
|
|
|
35
24
|
return isValid;
|
|
36
25
|
}
|
|
37
26
|
|
|
38
|
-
async verifySignatureSetsSameMessage(
|
|
39
|
-
sets: {publicKey: PublicKey; signature: Uint8Array}[],
|
|
40
|
-
message: Uint8Array
|
|
41
|
-
): Promise<boolean[]> {
|
|
27
|
+
async verifySignatureSetsSameMessage(sets: SameMessageSignatureSet[], message: Uint8Array): Promise<boolean[]> {
|
|
42
28
|
const timer = this.metrics?.blsThreadPool.mainThreadDurationInThreadPool.startTimer();
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const signatures = sets.map((set) => {
|
|
47
|
-
try {
|
|
48
|
-
return Signature.fromBytes(set.signature, true);
|
|
49
|
-
} catch (_) {
|
|
50
|
-
// at least one set has malformed signature
|
|
51
|
-
isAllValid = false;
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
if (isAllValid) {
|
|
57
|
-
const signature = aggregateSignatures(signatures as Signature[]);
|
|
58
|
-
isAllValid = verify(message, pubkey, signature);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
let result: boolean[];
|
|
62
|
-
if (isAllValid) {
|
|
63
|
-
result = sets.map(() => true);
|
|
64
|
-
} else {
|
|
65
|
-
result = sets.map((set, i) => {
|
|
66
|
-
const sig = signatures[i];
|
|
67
|
-
if (sig === null) {
|
|
68
|
-
return false;
|
|
69
|
-
}
|
|
70
|
-
return verify(message, set.publicKey, sig);
|
|
71
|
-
});
|
|
29
|
+
const result: boolean[] = [];
|
|
30
|
+
for (const setsChunk of chunkSameMessageSignatureSets(sets)) {
|
|
31
|
+
result.push(...verifySignatureSetsSameMessage(setsChunk, message));
|
|
72
32
|
}
|
|
73
|
-
|
|
74
|
-
if (timer) {
|
|
75
|
-
timer();
|
|
76
|
-
}
|
|
77
|
-
|
|
33
|
+
timer?.();
|
|
78
34
|
return result;
|
|
79
35
|
}
|
|
80
36
|
|
package/src/chain/bls/utils.ts
CHANGED
|
@@ -1,33 +1,32 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
BLS_VERIFIER_MAX_BATCH_SIZE,
|
|
3
|
+
BLS_VERIFIER_MAX_SAME_MESSAGE_BATCH_SIZE,
|
|
4
|
+
verifySignatureSets,
|
|
5
|
+
} from "@chainsafe/lodestar-z/bls-verifier";
|
|
6
|
+
import {ISignatureSet, SignatureSetType, toBlsSignatureSet} from "@lodestar/state-transition";
|
|
7
|
+
import {SameMessageSignatureSet} from "./interface.js";
|
|
4
8
|
|
|
5
|
-
export function
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
): PublicKey {
|
|
10
|
-
switch (signatureSet.type) {
|
|
11
|
-
case SignatureSetType.single:
|
|
12
|
-
return signatureSet.pubkey;
|
|
9
|
+
export function verifySignatureSetsInBatches(signatureSets: ISignatureSet[]): boolean {
|
|
10
|
+
if (signatureSets.length === 0) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
for (let start = 0; start < signatureSets.length; start += BLS_VERIFIER_MAX_BATCH_SIZE) {
|
|
15
|
+
const sets = signatureSets.slice(start, start + BLS_VERIFIER_MAX_BATCH_SIZE).map(toBlsSignatureSet);
|
|
16
|
+
if (!verifySignatureSets(sets)) {
|
|
17
|
+
return false;
|
|
16
18
|
}
|
|
19
|
+
}
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const pubkeys = signatureSet.indices.map((i) => {
|
|
21
|
-
return pubkeyCache.getOrThrow(i);
|
|
22
|
-
});
|
|
23
|
-
const aggregated = aggregatePublicKeys(pubkeys);
|
|
24
|
-
timer?.();
|
|
25
|
-
return aggregated;
|
|
26
|
-
}
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
27
23
|
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
export function chunkSameMessageSignatureSets(sets: SameMessageSignatureSet[]): SameMessageSignatureSet[][] {
|
|
25
|
+
const chunks: SameMessageSignatureSet[][] = [];
|
|
26
|
+
for (let start = 0; start < sets.length; start += BLS_VERIFIER_MAX_SAME_MESSAGE_BATCH_SIZE) {
|
|
27
|
+
chunks.push(sets.slice(start, start + BLS_VERIFIER_MAX_SAME_MESSAGE_BATCH_SIZE));
|
|
30
28
|
}
|
|
29
|
+
return chunks;
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
export function getAggregatedPubkeysCount(signatureSets: ISignatureSet[]): number {
|
package/src/chain/chain.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import {PrivateKey} from "@libp2p/interface";
|
|
3
|
+
import {type PubkeyCache} from "@chainsafe/lodestar-z/pubkeys";
|
|
3
4
|
import {Type} from "@chainsafe/ssz";
|
|
4
5
|
import {routes} from "@lodestar/api";
|
|
5
6
|
import {BeaconConfig} from "@lodestar/config";
|
|
@@ -25,7 +26,6 @@ import {
|
|
|
25
26
|
EffectiveBalanceIncrements,
|
|
26
27
|
EpochShuffling,
|
|
27
28
|
IBeaconStateView,
|
|
28
|
-
PubkeyCache,
|
|
29
29
|
computeEndSlotAtEpoch,
|
|
30
30
|
computeEpochAtSlot,
|
|
31
31
|
computeStartSlotAtEpoch,
|
|
@@ -79,6 +79,7 @@ import {CheckpointBalancesCache} from "./balancesCache.js";
|
|
|
79
79
|
import {BeaconProposerCache} from "./beaconProposerCache.js";
|
|
80
80
|
import {IBlockInput, isBlockInputBlobs, isBlockInputColumns} from "./blocks/blockInput/index.js";
|
|
81
81
|
import {BlockProcessor, ImportBlockOpts} from "./blocks/index.js";
|
|
82
|
+
import {PayloadEnvelopeInputSource} from "./blocks/payloadEnvelopeInput/index.js";
|
|
82
83
|
import {PayloadEnvelopeProcessor} from "./blocks/payloadEnvelopeProcessor.js";
|
|
83
84
|
import {ImportPayloadOpts} from "./blocks/types.js";
|
|
84
85
|
import {persistBlockInput} from "./blocks/writeBlockInputToDb.js";
|
|
@@ -94,6 +95,7 @@ import {LightClientServer} from "./lightClient/index.js";
|
|
|
94
95
|
import {
|
|
95
96
|
AggregatedAttestationPool,
|
|
96
97
|
AttestationPool,
|
|
98
|
+
DeferredVoluntaryExitPool,
|
|
97
99
|
ExecutionPayloadBidPool,
|
|
98
100
|
OpPool,
|
|
99
101
|
PayloadAttestationPool,
|
|
@@ -193,6 +195,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
193
195
|
readonly payloadAttestationPool: PayloadAttestationPool;
|
|
194
196
|
readonly proposerPreferencesPool = new ProposerPreferencesPool();
|
|
195
197
|
readonly opPool: OpPool;
|
|
198
|
+
readonly deferredVoluntaryExitPool: DeferredVoluntaryExitPool;
|
|
196
199
|
|
|
197
200
|
// Gossip seen cache
|
|
198
201
|
readonly seenAttesters = new SeenAttesters();
|
|
@@ -307,8 +310,8 @@ export class BeaconChain implements IBeaconChain {
|
|
|
307
310
|
const emitter = new ChainEventEmitter();
|
|
308
311
|
// by default, verify signatures on both main threads and worker threads
|
|
309
312
|
const bls = opts.blsVerifyAllMainThread
|
|
310
|
-
? new BlsSingleThreadVerifier({metrics
|
|
311
|
-
: new BlsMultiThreadWorkerPool(opts, {logger, metrics
|
|
313
|
+
? new BlsSingleThreadVerifier({metrics})
|
|
314
|
+
: new BlsMultiThreadWorkerPool(opts, {logger, metrics});
|
|
312
315
|
|
|
313
316
|
if (!clock) clock = new Clock({config, genesisTime: this.genesisTime, signal});
|
|
314
317
|
|
|
@@ -320,6 +323,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
320
323
|
this.executionPayloadBidPool = new ExecutionPayloadBidPool();
|
|
321
324
|
this.payloadAttestationPool = new PayloadAttestationPool(config, clock, metrics);
|
|
322
325
|
this.opPool = new OpPool(config);
|
|
326
|
+
this.deferredVoluntaryExitPool = new DeferredVoluntaryExitPool(logger);
|
|
323
327
|
|
|
324
328
|
this.seenAggregatedAttestations = new SeenAggregatedAttestations(metrics);
|
|
325
329
|
this.seenContributionAndProof = new SeenContributionAndProof(metrics);
|
|
@@ -451,6 +455,9 @@ export class BeaconChain implements IBeaconChain {
|
|
|
451
455
|
chainEvents: emitter,
|
|
452
456
|
signal,
|
|
453
457
|
serializedCache: this.serializedCache,
|
|
458
|
+
db,
|
|
459
|
+
seenBlockInputCache: this.seenBlockInputCache,
|
|
460
|
+
custodyConfig: this.custodyConfig,
|
|
454
461
|
metrics,
|
|
455
462
|
logger,
|
|
456
463
|
});
|
|
@@ -466,7 +473,8 @@ export class BeaconChain implements IBeaconChain {
|
|
|
466
473
|
bid: anchorBid,
|
|
467
474
|
sampledColumns: this.custodyConfig.sampledColumns,
|
|
468
475
|
custodyColumns: this.custodyConfig.custodyColumns,
|
|
469
|
-
|
|
476
|
+
seenTimestampSec: Date.now() / 1000,
|
|
477
|
+
source: PayloadEnvelopeInputSource.anchorState,
|
|
470
478
|
});
|
|
471
479
|
}
|
|
472
480
|
|
|
@@ -579,7 +587,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
579
587
|
// seenAggregators = single aggregator index, not participants of the aggregate
|
|
580
588
|
this.seenAggregators.isKnown(epoch, index) ||
|
|
581
589
|
// seenPayloadAttesters = single signer of payload attestation message
|
|
582
|
-
this.seenPayloadAttesters.
|
|
590
|
+
this.seenPayloadAttesters.seenAtEpoch(epoch, index) ||
|
|
583
591
|
// seenBlockProposers = single block proposer
|
|
584
592
|
this.seenBlockProposers.seenAtEpoch(epoch, index)
|
|
585
593
|
);
|
|
@@ -1090,7 +1098,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1090
1098
|
RegenCaller.produceBlock
|
|
1091
1099
|
);
|
|
1092
1100
|
const proposerIndex = state.getBeaconProposer(slot);
|
|
1093
|
-
const proposerPubKey = this.pubkeyCache.
|
|
1101
|
+
const proposerPubKey = this.pubkeyCache.getPubkeyBytesOrThrow(proposerIndex);
|
|
1094
1102
|
|
|
1095
1103
|
const {body, produceResult, executionPayloadValue, shouldOverrideBuilder} = await produceBlockBody.call(
|
|
1096
1104
|
this,
|
|
@@ -1569,6 +1577,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1569
1577
|
// aggregatedAttestationPool tracks metrics on its own
|
|
1570
1578
|
metrics.opPool.attestationPool.size.set(this.attestationPool.getAttestationCount());
|
|
1571
1579
|
metrics.opPool.attesterSlashingPoolSize.set(this.opPool.attesterSlashingsSize);
|
|
1580
|
+
metrics.opPool.deferredVoluntaryExitPool.size.set(this.deferredVoluntaryExitPool.size());
|
|
1572
1581
|
metrics.opPool.proposerSlashingPoolSize.set(this.opPool.proposerSlashingsSize);
|
|
1573
1582
|
metrics.opPool.voluntaryExitPoolSize.set(this.opPool.voluntaryExitsSize);
|
|
1574
1583
|
metrics.opPool.syncCommitteeMessagePoolSize.set(this.syncCommitteeMessagePool.size);
|
|
@@ -1577,6 +1586,8 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1577
1586
|
// syncContributionAndProofPool tracks metrics on its own
|
|
1578
1587
|
metrics.opPool.blsToExecutionChangePoolSize.set(this.opPool.blsToExecutionChangeSize);
|
|
1579
1588
|
metrics.chain.blacklistedBlocks.set(this.blacklistedBlocks.size);
|
|
1589
|
+
metrics.bls.pubkeyCacheSize.set(this.pubkeyCache.size);
|
|
1590
|
+
metrics.bls.pubkeyCacheCapacity.set(this.pubkeyCache.capacity);
|
|
1580
1591
|
|
|
1581
1592
|
const headState = this.getHeadState();
|
|
1582
1593
|
if (isStatePostElectra(headState)) {
|
|
@@ -136,7 +136,7 @@ export type BlockErrorType =
|
|
|
136
136
|
| {code: BlockErrorCode.NON_LINEAR_PARENT_ROOTS}
|
|
137
137
|
| {code: BlockErrorCode.NON_LINEAR_SLOTS}
|
|
138
138
|
| {code: BlockErrorCode.ENVELOPE_BLOCK_ROOT_MISMATCH; envelopeBlockRoot: RootHex; blockRoot: RootHex}
|
|
139
|
-
| {code: BlockErrorCode.PER_BLOCK_PROCESSING_ERROR; error: Error}
|
|
139
|
+
| {code: BlockErrorCode.PER_BLOCK_PROCESSING_ERROR; blockRoot: RootHex; error: Error}
|
|
140
140
|
| {code: BlockErrorCode.BEACON_CHAIN_ERROR; error: Error}
|
|
141
141
|
| {code: BlockErrorCode.KNOWN_BAD_BLOCK}
|
|
142
142
|
| {code: BlockErrorCode.BLACKLISTED_BLOCK}
|
|
@@ -184,13 +184,19 @@ export function isBlockErrorAborted(e: unknown): e is BlockError {
|
|
|
184
184
|
export function renderBlockErrorType(type: BlockErrorType): Record<string, string | number | null> {
|
|
185
185
|
switch (type.code) {
|
|
186
186
|
case BlockErrorCode.PRESTATE_MISSING:
|
|
187
|
-
case BlockErrorCode.PER_BLOCK_PROCESSING_ERROR:
|
|
188
187
|
case BlockErrorCode.BEACON_CHAIN_ERROR:
|
|
189
188
|
return {
|
|
190
189
|
code: type.code,
|
|
191
190
|
error: type.error.message,
|
|
192
191
|
};
|
|
193
192
|
|
|
193
|
+
case BlockErrorCode.PER_BLOCK_PROCESSING_ERROR:
|
|
194
|
+
return {
|
|
195
|
+
code: type.code,
|
|
196
|
+
blockRoot: type.blockRoot,
|
|
197
|
+
error: type.error.message,
|
|
198
|
+
};
|
|
199
|
+
|
|
194
200
|
case BlockErrorCode.INVALID_SIGNATURE:
|
|
195
201
|
return {
|
|
196
202
|
code: type.code,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import {ForkName} from "@lodestar/params";
|
|
1
2
|
import {Epoch, RootHex, Slot, ValidatorIndex} from "@lodestar/types";
|
|
2
3
|
import {GossipActionError} from "./gossipValidation.js";
|
|
3
4
|
|
|
4
5
|
export enum ProposerPreferencesErrorCode {
|
|
6
|
+
PRE_GLOAS_PROPOSAL_SLOT = "PROPOSER_PREFERENCES_ERROR_PRE_GLOAS_PROPOSAL_SLOT",
|
|
5
7
|
INVALID_EPOCH = "PROPOSER_PREFERENCES_ERROR_INVALID_EPOCH",
|
|
6
8
|
PROPOSAL_SLOT_PASSED = "PROPOSER_PREFERENCES_ERROR_PROPOSAL_SLOT_PASSED",
|
|
7
9
|
UNKNOWN_DEPENDENT_ROOT = "PROPOSER_PREFERENCES_ERROR_UNKNOWN_DEPENDENT_ROOT",
|
|
@@ -13,6 +15,11 @@ export enum ProposerPreferencesErrorCode {
|
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
export type ProposerPreferencesErrorType =
|
|
18
|
+
| {
|
|
19
|
+
code: ProposerPreferencesErrorCode.PRE_GLOAS_PROPOSAL_SLOT;
|
|
20
|
+
proposalSlot: Slot;
|
|
21
|
+
proposalFork: ForkName;
|
|
22
|
+
}
|
|
16
23
|
| {
|
|
17
24
|
code: ProposerPreferencesErrorCode.INVALID_EPOCH;
|
|
18
25
|
proposalSlot: Slot;
|
|
@@ -134,6 +134,8 @@ export function initializeForkChoiceFromFinalizedState(
|
|
|
134
134
|
stateRoot: toRootHex(blockHeader.stateRoot),
|
|
135
135
|
blockRoot: toRootHex(checkpoint.root),
|
|
136
136
|
timeliness: true, // Optimistically assume is timely
|
|
137
|
+
ptcTimeliness: true, // Spec: block_timeliness for anchor = [True, True]
|
|
138
|
+
proposerIndex: blockHeader.proposerIndex,
|
|
137
139
|
|
|
138
140
|
justifiedEpoch: justifiedCheckpoint.epoch,
|
|
139
141
|
justifiedRoot: toRootHex(justifiedCheckpoint.root),
|
|
@@ -230,6 +232,8 @@ export function initializeForkChoiceFromUnfinalizedState(
|
|
|
230
232
|
blockRoot: headRoot,
|
|
231
233
|
targetRoot: headRoot,
|
|
232
234
|
timeliness: true, // Optimistically assume is timely
|
|
235
|
+
ptcTimeliness: true, // Spec: block_timeliness for anchor = [True, True]
|
|
236
|
+
proposerIndex: blockHeader.proposerIndex,
|
|
233
237
|
|
|
234
238
|
justifiedEpoch: justifiedCheckpoint.epoch,
|
|
235
239
|
justifiedRoot: toRootHex(justifiedCheckpoint.root),
|
package/src/chain/interface.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import {type PubkeyCache} from "@chainsafe/lodestar-z/pubkeys";
|
|
1
2
|
import {Type} from "@chainsafe/ssz";
|
|
2
3
|
import {BeaconConfig} from "@lodestar/config";
|
|
3
4
|
import {CheckpointWithHex, IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
|
|
4
|
-
import {EpochShuffling, IBeaconStateView
|
|
5
|
+
import {EpochShuffling, IBeaconStateView} from "@lodestar/state-transition";
|
|
5
6
|
import {
|
|
6
7
|
BeaconBlock,
|
|
7
8
|
BlindedBeaconBlock,
|
|
@@ -44,6 +45,7 @@ import {LightClientServer} from "./lightClient/index.js";
|
|
|
44
45
|
import {AggregatedAttestationPool} from "./opPools/aggregatedAttestationPool.js";
|
|
45
46
|
import {
|
|
46
47
|
AttestationPool,
|
|
48
|
+
DeferredVoluntaryExitPool,
|
|
47
49
|
ExecutionPayloadBidPool,
|
|
48
50
|
OpPool,
|
|
49
51
|
PayloadAttestationPool,
|
|
@@ -127,6 +129,7 @@ export interface IBeaconChain {
|
|
|
127
129
|
readonly payloadAttestationPool: PayloadAttestationPool;
|
|
128
130
|
readonly proposerPreferencesPool: ProposerPreferencesPool;
|
|
129
131
|
readonly opPool: OpPool;
|
|
132
|
+
readonly deferredVoluntaryExitPool: DeferredVoluntaryExitPool;
|
|
130
133
|
|
|
131
134
|
// Gossip seen cache
|
|
132
135
|
readonly seenAttesters: SeenAttesters;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {Signature, aggregateSignatures} from "@chainsafe/blst";
|
|
1
|
+
import {Signature, aggregateSignatures} from "@chainsafe/lodestar-z/blst";
|
|
2
2
|
import {BitArray} from "@chainsafe/ssz";
|
|
3
3
|
import {BeaconConfig} from "@lodestar/config";
|
|
4
4
|
import {IForkChoice} from "@lodestar/fork-choice";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {Signature, aggregateSignatures} from "@chainsafe/blst";
|
|
1
|
+
import {Signature, aggregateSignatures} from "@chainsafe/lodestar-z/blst";
|
|
2
2
|
import {BitArray} from "@chainsafe/ssz";
|
|
3
3
|
import {ChainForkConfig} from "@lodestar/config";
|
|
4
4
|
import {MAX_COMMITTEES_PER_SLOT, isForkPostElectra} from "@lodestar/params";
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import {Logger} from "@lodestar/logger";
|
|
2
|
+
import {IBeaconStateView, VoluntaryExitValidity} from "@lodestar/state-transition";
|
|
3
|
+
import {Epoch, ValidatorIndex} from "@lodestar/types";
|
|
4
|
+
import {SignedVoluntaryExit} from "@lodestar/types/phase0";
|
|
5
|
+
import {isTransientExitValidity} from "../validation/voluntaryExit.js";
|
|
6
|
+
|
|
7
|
+
type DeferredEntry = {
|
|
8
|
+
exit: SignedVoluntaryExit;
|
|
9
|
+
validity: VoluntaryExitValidity;
|
|
10
|
+
insertedAtEpoch: Epoch;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export class DeferredVoluntaryExitPool {
|
|
14
|
+
private pool = new Map<ValidatorIndex, DeferredEntry>();
|
|
15
|
+
|
|
16
|
+
constructor(
|
|
17
|
+
private readonly logger: Logger,
|
|
18
|
+
private readonly maxSize = 1024,
|
|
19
|
+
private readonly maxDeferEpochs = 4096
|
|
20
|
+
) {}
|
|
21
|
+
|
|
22
|
+
insert(exit: SignedVoluntaryExit, validity: VoluntaryExitValidity, currentEpoch: Epoch): boolean {
|
|
23
|
+
if (!isTransientExitValidity(validity)) return false;
|
|
24
|
+
if (this.pool.size === this.maxSize) return false;
|
|
25
|
+
if (this.pool.has(exit.message.validatorIndex)) return false;
|
|
26
|
+
|
|
27
|
+
this.pool.set(exit.message.validatorIndex, {exit, validity, insertedAtEpoch: currentEpoch});
|
|
28
|
+
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
drainProcessableExits(state: IBeaconStateView): SignedVoluntaryExit[] {
|
|
33
|
+
const epoch = state.epoch;
|
|
34
|
+
const validExits: SignedVoluntaryExit[] = [];
|
|
35
|
+
for (const [validatorIndex, entry] of this.pool) {
|
|
36
|
+
try {
|
|
37
|
+
if (epoch - entry.insertedAtEpoch > this.maxDeferEpochs) {
|
|
38
|
+
this.pool.delete(validatorIndex);
|
|
39
|
+
this.logger.debug("Deferred voluntary exit expired", {validatorIndex, lastValidity: entry.validity});
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const validity = state.getVoluntaryExitValidity(entry.exit, true);
|
|
43
|
+
if (validity === VoluntaryExitValidity.valid) {
|
|
44
|
+
validExits.push(entry.exit);
|
|
45
|
+
this.pool.delete(validatorIndex);
|
|
46
|
+
} else if (!isTransientExitValidity(validity)) {
|
|
47
|
+
this.logger.debug("Deferred voluntary exit became permanently invalid", {validatorIndex, validity});
|
|
48
|
+
this.pool.delete(validatorIndex);
|
|
49
|
+
}
|
|
50
|
+
// Else if still transient - keep
|
|
51
|
+
} catch (e) {
|
|
52
|
+
this.logger.debug("Processing deferred voluntary exit failed", {validatorIndex}, e as Error);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return validExits;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
has(validatorIndex: ValidatorIndex): boolean {
|
|
59
|
+
return this.pool.has(validatorIndex);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
size(): number {
|
|
63
|
+
return this.pool.size;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export {AggregatedAttestationPool} from "./aggregatedAttestationPool.js";
|
|
2
2
|
export {AttestationPool} from "./attestationPool.js";
|
|
3
|
+
export {DeferredVoluntaryExitPool} from "./deferredVoluntaryExitPool.js";
|
|
3
4
|
export {ExecutionPayloadBidPool} from "./executionPayloadBidPool.js";
|
|
4
5
|
export {OpPool} from "./opPool.js";
|
|
5
6
|
export {PayloadAttestationPool} from "./payloadAttestationPool.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {Signature, aggregateSignatures} from "@chainsafe/blst";
|
|
1
|
+
import {Signature, aggregateSignatures} from "@chainsafe/lodestar-z/blst";
|
|
2
2
|
import {BitArray} from "@chainsafe/ssz";
|
|
3
3
|
import {ChainForkConfig} from "@lodestar/config";
|
|
4
4
|
import {MAX_COMMITTEES_PER_SLOT, MAX_PAYLOAD_ATTESTATIONS, PTC_SIZE} from "@lodestar/params";
|
|
@@ -178,8 +178,8 @@ function aggregateMessageInto(
|
|
|
178
178
|
validatorCommitteeIndices: number[],
|
|
179
179
|
aggregate: AggregateFast
|
|
180
180
|
): InsertOutcome {
|
|
181
|
-
// Gossip dedup via `seenPayloadAttesters` is keyed by (
|
|
182
|
-
// validator's message is never processed twice
|
|
181
|
+
// Gossip dedup via `seenPayloadAttesters` is keyed by (slot, validatorIndex), so the same
|
|
182
|
+
// validator's message is never processed twice for this aggregate's slot. All of its bits are set together or none.
|
|
183
183
|
// Checking the first index is sufficient.
|
|
184
184
|
if (aggregate.aggregationBits.get(validatorCommitteeIndices[0]) === true) {
|
|
185
185
|
return InsertOutcome.AlreadyKnown;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {Signature, aggregateSignatures} from "@chainsafe/blst";
|
|
1
|
+
import {Signature, aggregateSignatures} from "@chainsafe/lodestar-z/blst";
|
|
2
2
|
import {BitArray} from "@chainsafe/ssz";
|
|
3
3
|
import {ChainForkConfig} from "@lodestar/config";
|
|
4
4
|
import {SYNC_COMMITTEE_SIZE, SYNC_COMMITTEE_SUBNET_COUNT} from "@lodestar/params";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {Signature, aggregateSignatures} from "@chainsafe/blst";
|
|
1
|
+
import {Signature, aggregateSignatures} from "@chainsafe/lodestar-z/blst";
|
|
2
2
|
import {BitArray} from "@chainsafe/ssz";
|
|
3
3
|
import {ChainForkConfig} from "@lodestar/config";
|
|
4
4
|
import {SYNC_COMMITTEE_SIZE, SYNC_COMMITTEE_SUBNET_SIZE} from "@lodestar/params";
|