@lodestar/beacon-node 1.47.0-dev.0bcaaaebb5 → 1.47.0-dev.157b2b2a96
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 +12 -3
- package/lib/api/impl/events/index.js.map +1 -1
- package/lib/api/impl/validator/index.js +1 -1
- package/lib/api/impl/validator/index.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 +14 -6
- 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 +2 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +6 -4
- 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/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/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/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/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 +7 -2
- 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 +12 -4
- package/src/api/impl/validator/index.ts +1 -1
- 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 +18 -6
- 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 +7 -5
- package/src/chain/errors/blockError.ts +8 -2
- 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/seenCache/seenAttesters.ts +31 -5
- 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/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 +9 -0
- 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
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {computeEpochAtSlot} from "@lodestar/state-transition";
|
|
2
|
+
import {Epoch, Slot, ValidatorIndex} from "@lodestar/types";
|
|
2
3
|
import {MapDef} from "@lodestar/utils";
|
|
3
4
|
|
|
4
5
|
// How many *non future* epochs we intend to keep for SeenAttesters.
|
|
@@ -57,7 +58,32 @@ export class SeenAttesters {
|
|
|
57
58
|
*/
|
|
58
59
|
export class SeenAggregators extends SeenAttesters {}
|
|
59
60
|
|
|
60
|
-
/**
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
/** Keeps a cache to filter payload attestations from the same validator in the same slot. */
|
|
62
|
+
export class SeenPayloadAttesters {
|
|
63
|
+
private readonly validatorIndexesBySlot = new MapDef<Slot, Set<ValidatorIndex>>(() => new Set<ValidatorIndex>());
|
|
64
|
+
private readonly validatorIndexesByEpoch = new SeenAttesters();
|
|
65
|
+
|
|
66
|
+
isKnown(slot: Slot, validatorIndex: ValidatorIndex): boolean {
|
|
67
|
+
return this.validatorIndexesBySlot.get(slot)?.has(validatorIndex) === true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
add(slot: Slot, validatorIndex: ValidatorIndex): void {
|
|
71
|
+
const epoch = computeEpochAtSlot(slot);
|
|
72
|
+
this.validatorIndexesByEpoch.add(epoch, validatorIndex);
|
|
73
|
+
this.validatorIndexesBySlot.getOrDefault(slot).add(validatorIndex);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
seenAtEpoch(epoch: Epoch, validatorIndex: ValidatorIndex): boolean {
|
|
77
|
+
return this.validatorIndexesByEpoch.isKnown(epoch, validatorIndex);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
prune(currentEpoch: Epoch): void {
|
|
81
|
+
const lowestPermissibleEpoch = Math.max(currentEpoch - EPOCH_LOOKBACK_LIMIT, 0);
|
|
82
|
+
for (const slot of this.validatorIndexesBySlot.keys()) {
|
|
83
|
+
if (computeEpochAtSlot(slot) < lowestPermissibleEpoch) {
|
|
84
|
+
this.validatorIndexesBySlot.delete(slot);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
this.validatorIndexesByEpoch.prune(currentEpoch);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -142,13 +142,7 @@ export async function validateGossipAttestationsSameAttData(
|
|
|
142
142
|
const batchableBls = signatureSets.length >= chain.opts.minSameMessageSignatureSetsToBatch;
|
|
143
143
|
if (batchableBls) {
|
|
144
144
|
// all signature sets should have same signing root since we filtered in network processor
|
|
145
|
-
signatureValids = await chain.bls.verifySignatureSetsSameMessage(
|
|
146
|
-
signatureSets.map((set) => {
|
|
147
|
-
const publicKey = chain.pubkeyCache.getOrThrow(set.index);
|
|
148
|
-
return {publicKey, signature: set.signature};
|
|
149
|
-
}),
|
|
150
|
-
signatureSets[0].signingRoot
|
|
151
|
-
);
|
|
145
|
+
signatureValids = await chain.bls.verifySignatureSetsSameMessage(signatureSets, signatureSets[0].signingRoot);
|
|
152
146
|
} else {
|
|
153
147
|
// don't want to block the main thread if there are too few signatures
|
|
154
148
|
signatureValids = await Promise.all(
|
|
@@ -44,14 +44,7 @@ export async function validateAttesterSlashing(
|
|
|
44
44
|
// [REJECT] All of the conditions within process_attester_slashing pass validation.
|
|
45
45
|
try {
|
|
46
46
|
// verifySignature = false, verified in batch below
|
|
47
|
-
assertValidAttesterSlashing(
|
|
48
|
-
chain.config,
|
|
49
|
-
chain.pubkeyCache,
|
|
50
|
-
state.slot,
|
|
51
|
-
state.validatorCount,
|
|
52
|
-
attesterSlashing,
|
|
53
|
-
false
|
|
54
|
-
);
|
|
47
|
+
assertValidAttesterSlashing(chain.config, state.slot, state.validatorCount, attesterSlashing, false);
|
|
55
48
|
} catch (e) {
|
|
56
49
|
throw new AttesterSlashingError(GossipAction.REJECT, {
|
|
57
50
|
code: AttesterSlashingErrorCode.INVALID,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {PublicKey} from "@chainsafe/blst";
|
|
2
1
|
import {IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
|
|
3
2
|
import {PAYLOAD_BUILDER_VERSION} from "@lodestar/params";
|
|
4
3
|
import {
|
|
@@ -345,7 +344,7 @@ async function validateExecutionPayloadBid(
|
|
|
345
344
|
|
|
346
345
|
// [REJECT] `signed_execution_payload_bid.signature` is valid with respect to the `bid.builder_index`.
|
|
347
346
|
const signatureSet = createSingleSignatureSetFromComponents(
|
|
348
|
-
|
|
347
|
+
builder.pubkey,
|
|
349
348
|
getExecutionPayloadBidSigningRoot(chain.config, bid),
|
|
350
349
|
signedExecutionPayloadBid.signature
|
|
351
350
|
);
|
|
@@ -170,7 +170,6 @@ async function validateExecutionPayloadEnvelope(
|
|
|
170
170
|
// by `verify_execution_payload_envelope_signature`.
|
|
171
171
|
const signatureSet = getExecutionPayloadEnvelopeSignatureSet(
|
|
172
172
|
chain.config,
|
|
173
|
-
chain.pubkeyCache,
|
|
174
173
|
blockState,
|
|
175
174
|
executionPayloadEnvelope,
|
|
176
175
|
payloadInput.proposerIndex
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
createSingleSignatureSetFromComponents,
|
|
2
|
+
createIndexedSignatureSetFromComponents,
|
|
4
3
|
getPayloadAttestationDataSigningRoot,
|
|
5
4
|
isStatePostGloas,
|
|
6
5
|
} from "@lodestar/state-transition";
|
|
@@ -36,7 +35,6 @@ async function validatePayloadAttestationMessage(
|
|
|
36
35
|
prioritizeBls = false
|
|
37
36
|
): Promise<PayloadAttestationValidationResult> {
|
|
38
37
|
const {data, validatorIndex} = payloadAttestationMessage;
|
|
39
|
-
const epoch = computeEpochAtSlot(data.slot);
|
|
40
38
|
|
|
41
39
|
// [IGNORE] The message's slot is for the current slot (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance), i.e. `data.slot == current_slot`.
|
|
42
40
|
if (!chain.clock.isCurrentSlotGivenGossipDisparity(data.slot)) {
|
|
@@ -48,9 +46,8 @@ async function validatePayloadAttestationMessage(
|
|
|
48
46
|
}
|
|
49
47
|
|
|
50
48
|
// [IGNORE] The `payload_attestation_message` is the first valid message received
|
|
51
|
-
// from the validator with index `payload_attestation_message.validator_index`.
|
|
52
|
-
|
|
53
|
-
if (chain.seenPayloadAttesters.isKnown(epoch, validatorIndex)) {
|
|
49
|
+
// for the slot from the validator with index `payload_attestation_message.validator_index`.
|
|
50
|
+
if (chain.seenPayloadAttesters.isKnown(data.slot, validatorIndex)) {
|
|
54
51
|
throw new PayloadAttestationError(GossipAction.IGNORE, {
|
|
55
52
|
code: PayloadAttestationErrorCode.PAYLOAD_ATTESTATION_ALREADY_KNOWN,
|
|
56
53
|
validatorIndex,
|
|
@@ -114,16 +111,8 @@ async function validatePayloadAttestationMessage(
|
|
|
114
111
|
}
|
|
115
112
|
|
|
116
113
|
// [REJECT] `payload_attestation_message.signature` is valid with respect to the validator's public key.
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
throw new PayloadAttestationError(GossipAction.REJECT, {
|
|
120
|
-
code: PayloadAttestationErrorCode.INVALID_ATTESTER,
|
|
121
|
-
attesterIndex: validatorIndex,
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const signatureSet = createSingleSignatureSetFromComponents(
|
|
126
|
-
validatorPubkey,
|
|
114
|
+
const signatureSet = createIndexedSignatureSetFromComponents(
|
|
115
|
+
validatorIndex,
|
|
127
116
|
getPayloadAttestationDataSigningRoot(chain.config, data),
|
|
128
117
|
payloadAttestationMessage.signature
|
|
129
118
|
);
|
|
@@ -135,7 +124,7 @@ async function validatePayloadAttestationMessage(
|
|
|
135
124
|
}
|
|
136
125
|
|
|
137
126
|
// Valid
|
|
138
|
-
chain.seenPayloadAttesters.add(
|
|
127
|
+
chain.seenPayloadAttesters.add(data.slot, validatorIndex);
|
|
139
128
|
|
|
140
129
|
return {
|
|
141
130
|
attDataRootHex: toRootHex(ssz.gloas.PayloadAttestationData.hashTreeRoot(data)),
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
|
|
2
|
-
import {GENESIS_EPOCH, GENESIS_SLOT, MIN_SEED_LOOKAHEAD, SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
2
|
+
import {GENESIS_EPOCH, GENESIS_SLOT, MIN_SEED_LOOKAHEAD, SLOTS_PER_EPOCH, isForkPostGloas} from "@lodestar/params";
|
|
3
3
|
import {
|
|
4
4
|
computeEpochAtSlot,
|
|
5
5
|
computeStartSlotAtEpoch,
|
|
6
|
-
|
|
6
|
+
createIndexedSignatureSetFromComponents,
|
|
7
7
|
getProposerPreferencesSigningRoot,
|
|
8
8
|
} from "@lodestar/state-transition";
|
|
9
9
|
import {Epoch, Slot, ValidatorIndex, gloas} from "@lodestar/types";
|
|
@@ -13,7 +13,7 @@ import {IBeaconChain} from "../index.js";
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Validates a gossiped `SignedProposerPreferences` per
|
|
16
|
-
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.
|
|
16
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.14/specs/gloas/p2p-interface.md#new-proposer_preferences
|
|
17
17
|
*/
|
|
18
18
|
export async function validateGossipProposerPreferences(
|
|
19
19
|
chain: IBeaconChain,
|
|
@@ -24,6 +24,16 @@ export async function validateGossipProposerPreferences(
|
|
|
24
24
|
const dependentRootHex = toRootHex(dependentRoot);
|
|
25
25
|
const proposalEpoch = computeEpochAtSlot(proposalSlot);
|
|
26
26
|
|
|
27
|
+
// [IGNORE] The proposal epoch is after the Gloas upgrade
|
|
28
|
+
const proposalFork = chain.config.getForkName(proposalSlot);
|
|
29
|
+
if (!isForkPostGloas(proposalFork)) {
|
|
30
|
+
throw new ProposerPreferencesError(GossipAction.IGNORE, {
|
|
31
|
+
code: ProposerPreferencesErrorCode.PRE_GLOAS_PROPOSAL_SLOT,
|
|
32
|
+
proposalSlot,
|
|
33
|
+
proposalFork,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
27
37
|
// [IGNORE] `preferences.proposal_slot` is within the proposer lookahead,
|
|
28
38
|
// allowing for `MAXIMUM_GOSSIP_CLOCK_DISPARITY`.
|
|
29
39
|
const currentEpoch = computeEpochAtSlot(chain.clock.currentSlotWithGossipDisparity);
|
|
@@ -129,8 +139,8 @@ export async function validateGossipProposerPreferences(
|
|
|
129
139
|
}
|
|
130
140
|
|
|
131
141
|
// [REJECT] `signed_proposer_preferences.signature` is valid with respect to the validator's public key.
|
|
132
|
-
const signatureSet =
|
|
133
|
-
|
|
142
|
+
const signatureSet = createIndexedSignatureSetFromComponents(
|
|
143
|
+
validatorIndex,
|
|
134
144
|
getProposerPreferencesSigningRoot(chain.config, preferences),
|
|
135
145
|
signedProposerPreferences.signature
|
|
136
146
|
);
|
|
@@ -37,7 +37,7 @@ async function validateProposerSlashing(
|
|
|
37
37
|
try {
|
|
38
38
|
const proposer = state.getValidator(proposerSlashing.signedHeader1.message.proposerIndex);
|
|
39
39
|
// verifySignature = false, verified in batch below
|
|
40
|
-
assertValidProposerSlashing(chain.config,
|
|
40
|
+
assertValidProposerSlashing(chain.config, state.slot, proposerSlashing, proposer, false);
|
|
41
41
|
} catch (e) {
|
|
42
42
|
throw new ProposerSlashingError(GossipAction.REJECT, {
|
|
43
43
|
code: ProposerSlashingErrorCode.INVALID,
|
|
@@ -71,15 +71,18 @@ export class NoBidReceived extends Error {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
/**
|
|
74
|
-
*
|
|
75
|
-
* the circuit breaker (so at boot time and once for each unique boot).
|
|
74
|
+
* Default circuit breaker parameters:
|
|
76
75
|
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
76
|
+
* SLOTS_PER_EPOCH <= FAULT_INSPECTION_WINDOW < 2 * SLOTS_PER_EPOCH (randomized at initialization)
|
|
77
|
+
* ALLOWED_FAULTS: FAULT_INSPECTION_WINDOW // 4
|
|
79
78
|
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
79
|
+
* e.g. on mainnet SLOTS_PER_EPOCH is 32, so FAULT_INSPECTION_WINDOW is between 32 and 63,
|
|
80
|
+
* and a window of 40 results in ALLOWED_FAULTS = 10.
|
|
81
|
+
*
|
|
82
|
+
* The randomized default window keeps the exact slots under inspection unpredictable per node,
|
|
83
|
+
* so a builder cannot tell when past faults age out of a given proposer's window and time
|
|
84
|
+
* withholding around trip or recovery points. Explicitly configured windows are clamped to at
|
|
85
|
+
* least SLOTS_PER_EPOCH, and configured allowedFaults is capped at the default ~25% budget.
|
|
83
86
|
*/
|
|
84
87
|
export function getFaultInspectionParams(opts: {faultInspectionWindow?: number; allowedFaults?: number}): {
|
|
85
88
|
faultInspectionWindow: number;
|
|
@@ -90,10 +93,7 @@ export function getFaultInspectionParams(opts: {faultInspectionWindow?: number;
|
|
|
90
93
|
SLOTS_PER_EPOCH
|
|
91
94
|
);
|
|
92
95
|
// allowedFaults should be < faultInspectionWindow, limiting them to faultInspectionWindow/4
|
|
93
|
-
const allowedFaults = Math.min(
|
|
94
|
-
opts.allowedFaults ?? Math.floor(faultInspectionWindow / 4),
|
|
95
|
-
Math.floor(faultInspectionWindow / 4)
|
|
96
|
-
);
|
|
96
|
+
const allowedFaults = Math.min(opts.allowedFaults ?? Infinity, Math.floor(faultInspectionWindow / 4));
|
|
97
97
|
return {faultInspectionWindow, allowedFaults};
|
|
98
98
|
}
|
|
99
99
|
|
|
@@ -143,17 +143,17 @@ export function createBeaconMetrics(register: RegistryMetricCreator) {
|
|
|
143
143
|
name: "beacon_builder_circuit_breaker_active",
|
|
144
144
|
help: "Whether the builder circuit breaker is active (1) causing builder bids to be ignored",
|
|
145
145
|
}),
|
|
146
|
-
|
|
147
|
-
name: "
|
|
148
|
-
help: "Count of
|
|
146
|
+
canonicalBlocks: register.gauge({
|
|
147
|
+
name: "beacon_builder_circuit_breaker_canonical_blocks",
|
|
148
|
+
help: "Count of canonical FULL and EMPTY blocks in the fault inspection window",
|
|
149
149
|
}),
|
|
150
|
-
|
|
151
|
-
name: "
|
|
152
|
-
help: "Count of blocks
|
|
150
|
+
fullBlocks: register.gauge({
|
|
151
|
+
name: "beacon_builder_circuit_breaker_full_blocks",
|
|
152
|
+
help: "Count of canonical FULL blocks in the fault inspection window",
|
|
153
153
|
}),
|
|
154
|
-
|
|
155
|
-
name: "
|
|
156
|
-
help: "Count of
|
|
154
|
+
emptyBlocks: register.gauge({
|
|
155
|
+
name: "beacon_builder_circuit_breaker_empty_blocks",
|
|
156
|
+
help: "Count of canonical EMPTY blocks in the fault inspection window",
|
|
157
157
|
}),
|
|
158
158
|
},
|
|
159
159
|
|
|
@@ -31,6 +31,10 @@ import {RegistryMetricCreator} from "../utils/registryMetricCreator.js";
|
|
|
31
31
|
|
|
32
32
|
export type LodestarMetrics = ReturnType<typeof createLodestarMetrics>;
|
|
33
33
|
|
|
34
|
+
type BlsJobOutcome = "valid" | "invalid" | "prepError" | "verifyError" | "workerError";
|
|
35
|
+
type BlsBufferFlushReason = "size" | "timeout";
|
|
36
|
+
type BlsVerificationCallOperation = "batch" | "single" | "fallback" | "same_message";
|
|
37
|
+
|
|
34
38
|
/**
|
|
35
39
|
* Extra Lodestar custom metrics
|
|
36
40
|
*/
|
|
@@ -396,86 +400,108 @@ export function createLodestarMetrics(
|
|
|
396
400
|
// BLS verifier thread pool and queue
|
|
397
401
|
|
|
398
402
|
bls: {
|
|
399
|
-
aggregatedPubkeys: register.
|
|
403
|
+
aggregatedPubkeys: register.counter({
|
|
400
404
|
name: "lodestar_bls_aggregated_pubkeys_total",
|
|
401
|
-
help: "Total
|
|
405
|
+
help: "Total validator public keys used as inputs to aggregate signature sets",
|
|
406
|
+
}),
|
|
407
|
+
pubkeyCacheSize: register.gauge({
|
|
408
|
+
name: "lodestar_bls_pubkey_cache_size",
|
|
409
|
+
help: "Current number of validator public keys in the native cache",
|
|
410
|
+
}),
|
|
411
|
+
pubkeyCacheCapacity: register.gauge({
|
|
412
|
+
name: "lodestar_bls_pubkey_cache_capacity",
|
|
413
|
+
help: "Number of validator public keys the native cache can hold without growing",
|
|
402
414
|
}),
|
|
403
415
|
},
|
|
404
416
|
|
|
405
417
|
blsThreadPool: {
|
|
406
|
-
jobsWorkerTime: register.
|
|
418
|
+
jobsWorkerTime: register.counter<{workerId: number}>({
|
|
407
419
|
name: "lodestar_bls_thread_pool_time_seconds_sum",
|
|
408
|
-
help: "
|
|
420
|
+
help: "Cumulative wall time spent processing BLS dispatch groups by worker",
|
|
409
421
|
labelNames: ["workerId"],
|
|
410
422
|
}),
|
|
411
|
-
successJobsSignatureSetsCount: register.
|
|
423
|
+
successJobsSignatureSetsCount: register.counter({
|
|
412
424
|
name: "lodestar_bls_thread_pool_success_jobs_signature_sets_count",
|
|
413
|
-
help: "Count of
|
|
425
|
+
help: "Count of signature sets completed without an operational error",
|
|
414
426
|
}),
|
|
415
|
-
|
|
416
|
-
name: "lodestar_bls_thread_pool_error_aggregate_signature_sets_count",
|
|
417
|
-
help: "Count of error when aggregating pubkeys or signatures",
|
|
418
|
-
labelNames: ["type"],
|
|
419
|
-
}),
|
|
420
|
-
errorJobsSignatureSetsCount: register.gauge({
|
|
427
|
+
errorJobsSignatureSetsCount: register.counter({
|
|
421
428
|
name: "lodestar_bls_thread_pool_error_jobs_signature_sets_count",
|
|
422
|
-
help: "Count of
|
|
429
|
+
help: "Count of signature sets that ended in an input, binding, or worker error",
|
|
423
430
|
}),
|
|
424
|
-
jobWaitTime: register.histogram({
|
|
431
|
+
jobWaitTime: register.histogram<{type: JobQueueItemType}>({
|
|
425
432
|
name: "lodestar_bls_thread_pool_queue_job_wait_time_seconds",
|
|
426
|
-
help: "Time from job
|
|
427
|
-
|
|
433
|
+
help: "Time from adding a BLS job until it is selected for a worker dispatch group",
|
|
434
|
+
labelNames: ["type"],
|
|
435
|
+
buckets: [0.005, 0.01, 0.025, 0.05, 0.1, 0.2, 0.5, 1, 2],
|
|
436
|
+
}),
|
|
437
|
+
jobDuration: register.histogram<{type: JobQueueItemType}>({
|
|
438
|
+
name: "lodestar_bls_thread_pool_job_duration_seconds",
|
|
439
|
+
help: "End-to-end duration of a BLS job from submission through completion",
|
|
440
|
+
labelNames: ["type"],
|
|
441
|
+
buckets: [0.005, 0.01, 0.025, 0.05, 0.1, 0.2, 0.5, 1, 2],
|
|
442
|
+
}),
|
|
443
|
+
jobResults: register.counter<{type: JobQueueItemType; outcome: BlsJobOutcome}>({
|
|
444
|
+
name: "lodestar_bls_thread_pool_job_results_total",
|
|
445
|
+
help: "Count of completed BLS jobs by cryptographic or operational outcome",
|
|
446
|
+
labelNames: ["type", "outcome"],
|
|
428
447
|
}),
|
|
429
448
|
queueLength: register.gauge({
|
|
430
449
|
name: "lodestar_bls_thread_pool_queue_length",
|
|
431
|
-
help: "Count of
|
|
450
|
+
help: "Count of ready BLS jobs waiting for a worker",
|
|
451
|
+
}),
|
|
452
|
+
bufferedQueueLength: register.gauge({
|
|
453
|
+
name: "lodestar_bls_thread_pool_buffered_queue_length",
|
|
454
|
+
help: "Count of BLS jobs waiting in the intentional batching buffer",
|
|
432
455
|
}),
|
|
433
456
|
workersBusy: register.gauge({
|
|
434
457
|
name: "lodestar_bls_thread_pool_workers_busy",
|
|
435
458
|
help: "Count of current busy workers",
|
|
436
459
|
}),
|
|
437
|
-
totalJobsGroupsStarted: register.
|
|
460
|
+
totalJobsGroupsStarted: register.counter({
|
|
438
461
|
name: "lodestar_bls_thread_pool_job_groups_started_total",
|
|
439
|
-
help: "Count of
|
|
462
|
+
help: "Count of worker dispatch groups started by the BLS thread pool",
|
|
440
463
|
}),
|
|
441
|
-
totalJobsStarted: register.
|
|
464
|
+
totalJobsStarted: register.counter<{type: JobQueueItemType}>({
|
|
442
465
|
name: "lodestar_bls_thread_pool_jobs_started_total",
|
|
443
|
-
help: "Count of
|
|
466
|
+
help: "Count of jobs started by the BLS thread pool",
|
|
444
467
|
labelNames: ["type"],
|
|
445
468
|
}),
|
|
446
|
-
totalSigSetsStarted: register.
|
|
469
|
+
totalSigSetsStarted: register.counter<{type: JobQueueItemType}>({
|
|
447
470
|
name: "lodestar_bls_thread_pool_sig_sets_started_total",
|
|
448
|
-
help: "Count of
|
|
471
|
+
help: "Count of signature sets started by the BLS thread pool",
|
|
449
472
|
labelNames: ["type"],
|
|
450
473
|
}),
|
|
451
474
|
// Re-verifying a batch means doing double work. This number must be very low or it can be a waste of CPU resources
|
|
452
|
-
batchRetries: register.
|
|
475
|
+
batchRetries: register.counter({
|
|
453
476
|
name: "lodestar_bls_thread_pool_batch_retries_total",
|
|
454
|
-
help: "Count of
|
|
477
|
+
help: "Count of combined batches that failed and required per-job fallback",
|
|
455
478
|
}),
|
|
456
479
|
// To count how many sigs are being validated with the optimization of batching them
|
|
457
|
-
batchSigsSuccess: register.
|
|
480
|
+
batchSigsSuccess: register.counter({
|
|
458
481
|
name: "lodestar_bls_thread_pool_batch_sigs_success_total",
|
|
459
|
-
help: "Count of
|
|
482
|
+
help: "Count of signature sets accepted by combined batch verification without fallback",
|
|
460
483
|
}),
|
|
461
|
-
|
|
462
|
-
name: "
|
|
463
|
-
help: "Count of
|
|
484
|
+
bufferFlushes: register.counter<{reason: BlsBufferFlushReason}>({
|
|
485
|
+
name: "lodestar_bls_thread_pool_buffer_flushes_total",
|
|
486
|
+
help: "Count of batching-buffer flushes by trigger",
|
|
487
|
+
labelNames: ["reason"],
|
|
464
488
|
}),
|
|
465
|
-
|
|
466
|
-
name: "
|
|
467
|
-
help: "Count of
|
|
489
|
+
bufferedSignatureSets: register.histogram({
|
|
490
|
+
name: "lodestar_bls_thread_pool_buffered_signature_sets",
|
|
491
|
+
help: "Count of signature sets included in each batching-buffer flush",
|
|
492
|
+
buckets: [1, 8, 16, 24, 28, 32, 36, 40, 44, 48, 64, 128],
|
|
468
493
|
}),
|
|
469
494
|
// To measure the time cost of main thread <-> worker message passing
|
|
470
495
|
latencyToWorker: register.histogram({
|
|
471
496
|
name: "lodestar_bls_thread_pool_latency_to_worker",
|
|
472
497
|
help: "Time from sending the job to the worker and the worker receiving it",
|
|
473
|
-
|
|
498
|
+
// The dashboard treats 20ms as slow; values above 100ms only need severe-stall classification.
|
|
499
|
+
buckets: [0.00025, 0.001, 0.005, 0.02, 0.1],
|
|
474
500
|
}),
|
|
475
501
|
latencyFromWorker: register.histogram({
|
|
476
502
|
name: "lodestar_bls_thread_pool_latency_from_worker",
|
|
477
503
|
help: "Time from the worker sending the result and the main thread receiving it",
|
|
478
|
-
buckets: [0.
|
|
504
|
+
buckets: [0.00025, 0.001, 0.005, 0.02, 0.1],
|
|
479
505
|
}),
|
|
480
506
|
mainThreadDurationInThreadPool: register.histogram({
|
|
481
507
|
name: "lodestar_bls_thread_pool_main_thread_time_seconds",
|
|
@@ -485,32 +511,40 @@ export function createLodestarMetrics(
|
|
|
485
511
|
}),
|
|
486
512
|
timePerSigSet: register.histogram({
|
|
487
513
|
name: "lodestar_bls_worker_thread_time_per_sigset_seconds",
|
|
488
|
-
help: "
|
|
514
|
+
help: "Average BLS worker dispatch wall time per original signature set",
|
|
489
515
|
// Time per sig ~0.9ms on good machines
|
|
490
|
-
buckets: [0.5e-3, 0.75e-3, 1e-3, 1.5e-3, 2e-3, 5e-3],
|
|
491
|
-
}),
|
|
492
|
-
|
|
516
|
+
buckets: [0.5e-3, 0.75e-3, 1e-3, 1.5e-3, 2e-3, 5e-3, 10e-3, 20e-3, 50e-3, 100e-3],
|
|
517
|
+
}),
|
|
518
|
+
workRequestPreparationDuration: register.histogram({
|
|
519
|
+
name: "lodestar_bls_thread_pool_work_request_preparation_duration_seconds",
|
|
520
|
+
help: "Main-thread time spent converting one worker dispatch group to binding inputs",
|
|
521
|
+
// Normal requests take microseconds; the dashboard treats 1ms as a main-thread stall.
|
|
522
|
+
buckets: [0.000005, 0.000025, 0.0001, 0.0005, 0.001, 0.005, 0.025],
|
|
523
|
+
}),
|
|
524
|
+
verificationCallDuration: register.histogram<{operation: BlsVerificationCallOperation}>({
|
|
525
|
+
name: "lodestar_bls_thread_pool_verification_call_duration_seconds",
|
|
526
|
+
help: "Duration of one worker-side lodestar-z verification binding call, including input conversion",
|
|
527
|
+
labelNames: ["operation"],
|
|
528
|
+
// Verification ranges from sub-millisecond calls to large batches; above 500ms is uniformly severe.
|
|
529
|
+
buckets: [0.00025, 0.001, 0.005, 0.02, 0.1, 0.5],
|
|
530
|
+
}),
|
|
531
|
+
verificationCallSignatureSets: register.counter<{operation: BlsVerificationCallOperation}>({
|
|
532
|
+
name: "lodestar_bls_thread_pool_verification_call_signature_sets_total",
|
|
533
|
+
help: "Count of signature sets passed to worker-side lodestar-z verification binding calls",
|
|
534
|
+
labelNames: ["operation"],
|
|
535
|
+
}),
|
|
536
|
+
totalSigSets: register.counter({
|
|
493
537
|
name: "lodestar_bls_thread_pool_sig_sets_total",
|
|
494
538
|
help: "Count of total signature sets",
|
|
495
539
|
}),
|
|
496
|
-
prioritizedSigSets: register.
|
|
540
|
+
prioritizedSigSets: register.counter({
|
|
497
541
|
name: "lodestar_bls_thread_pool_prioritized_sig_sets_total",
|
|
498
542
|
help: "Count of total prioritized signature sets",
|
|
499
543
|
}),
|
|
500
|
-
batchableSigSets: register.
|
|
544
|
+
batchableSigSets: register.counter({
|
|
501
545
|
name: "lodestar_bls_thread_pool_batchable_sig_sets_total",
|
|
502
546
|
help: "Count of total batchable signature sets",
|
|
503
547
|
}),
|
|
504
|
-
aggregateWithRandomnessAsyncDuration: register.histogram({
|
|
505
|
-
name: "lodestar_bls_thread_pool_aggregate_with_randomness_async_time_seconds",
|
|
506
|
-
help: "Total time performing aggregateWithRandomness async",
|
|
507
|
-
buckets: [0.001, 0.005, 0.01, 0.1, 0.3],
|
|
508
|
-
}),
|
|
509
|
-
pubkeysAggregationMainThreadDuration: register.histogram({
|
|
510
|
-
name: "lodestar_bls_thread_pool_pubkeys_aggregation_main_thread_time_seconds",
|
|
511
|
-
help: "Total time spent aggregating pubkeys on main thread",
|
|
512
|
-
buckets: [0.001, 0.005, 0.01, 0.1],
|
|
513
|
-
}),
|
|
514
548
|
},
|
|
515
549
|
|
|
516
550
|
// BLS time on single thread mode
|
|
@@ -908,6 +942,22 @@ export function createLodestarMetrics(
|
|
|
908
942
|
labelNames: ["error"],
|
|
909
943
|
}),
|
|
910
944
|
},
|
|
945
|
+
gossipExecutionPayloadBid: {
|
|
946
|
+
elapsedTimeTillReceived: register.histogram<{source: OpSource}>({
|
|
947
|
+
name: "lodestar_gossip_execution_payload_bid_elapsed_time_till_received_seconds",
|
|
948
|
+
help: "Time elapsed between the bid's slot start and the time the execution payload bid was received (negative = received before its slot, broadcast in the previous slot; positive = received during its own slot, late)",
|
|
949
|
+
labelNames: ["source"],
|
|
950
|
+
buckets: [-6, -3, -1, 0, 3],
|
|
951
|
+
}),
|
|
952
|
+
},
|
|
953
|
+
gossipPayloadAttestationMessage: {
|
|
954
|
+
elapsedTimeTillReceived: register.histogram<{source: OpSource}>({
|
|
955
|
+
name: "lodestar_gossip_payload_attestation_message_elapsed_time_till_received_seconds",
|
|
956
|
+
help: "Time elapsed between slot time and the time the payload attestation message was received",
|
|
957
|
+
labelNames: ["source"],
|
|
958
|
+
buckets: [3, 6, 9, 12],
|
|
959
|
+
}),
|
|
960
|
+
},
|
|
911
961
|
// recovery in the case of specific blob rows required
|
|
912
962
|
recoverBlobSidecars: {
|
|
913
963
|
blobsReconstructed: register.counter({
|
|
@@ -414,3 +414,41 @@ export const gossipTopicIgnoreDuplicatePublishError: Record<GossipType, boolean>
|
|
|
414
414
|
[GossipType.execution_payload_bid]: true,
|
|
415
415
|
[GossipType.proposer_preferences]: true,
|
|
416
416
|
};
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Whether a publish that reached zero subscribed peers is an acceptable outcome for a topic.
|
|
420
|
+
*
|
|
421
|
+
* Publishing to a topic with no subscribed peers throws `PublishError.NoPeersSubscribedToTopic`, which
|
|
422
|
+
* propagates to the caller and, for messages submitted through the beacon API, is surfaced to the
|
|
423
|
+
* validator client. That is the right default: a message that reached nobody is a failed broadcast, and a
|
|
424
|
+
* VC configured with several beacon nodes can fall back to another one.
|
|
425
|
+
*
|
|
426
|
+
* Only topics that have a concrete reason to tolerate it opt out here, ie. are set to `true`, and the
|
|
427
|
+
* reason is named on the entry. Everything else is `false` and keeps raising. Note this is applied per
|
|
428
|
+
* publish, a topic set to `false` still honors the global `--network.allowPublishToZeroPeers` flag.
|
|
429
|
+
*/
|
|
430
|
+
export const gossipTopicAllowPublishToZeroPeers: Record<GossipType, boolean> = {
|
|
431
|
+
[GossipType.beacon_block]: false,
|
|
432
|
+
[GossipType.blob_sidecar]: false,
|
|
433
|
+
// data_column_sidecar: we ensure having all topic peers via prioritizePeers(). Even with 0 peers on the
|
|
434
|
+
// topic the overall publish can still succeed, because a supernode rebuilds and publishes the missing
|
|
435
|
+
// columns for us, so track sent peers as 0 instead of raising
|
|
436
|
+
[GossipType.data_column_sidecar]: true,
|
|
437
|
+
[GossipType.beacon_aggregate_and_proof]: false,
|
|
438
|
+
[GossipType.beacon_attestation]: false,
|
|
439
|
+
[GossipType.voluntary_exit]: false,
|
|
440
|
+
[GossipType.proposer_slashing]: false,
|
|
441
|
+
[GossipType.attester_slashing]: false,
|
|
442
|
+
[GossipType.sync_committee_contribution_and_proof]: false,
|
|
443
|
+
[GossipType.sync_committee]: false,
|
|
444
|
+
// light_client_finality_update and light_client_optimistic_update: non-mandatory route on most of the
|
|
445
|
+
// network as of Oct 2022, there may be no peer subscribed to the topic at all. Reason carried over from
|
|
446
|
+
// the handlers in network.ts, which used to swallow the error instead
|
|
447
|
+
[GossipType.light_client_finality_update]: true,
|
|
448
|
+
[GossipType.light_client_optimistic_update]: true,
|
|
449
|
+
[GossipType.bls_to_execution_change]: false,
|
|
450
|
+
[GossipType.execution_payload]: false,
|
|
451
|
+
[GossipType.payload_attestation_message]: false,
|
|
452
|
+
[GossipType.execution_payload_bid]: false,
|
|
453
|
+
[GossipType.proposer_preferences]: false,
|
|
454
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {getCiphers} from "node:crypto";
|
|
1
2
|
import {bootstrap} from "@libp2p/bootstrap";
|
|
2
3
|
import {identify} from "@libp2p/identify";
|
|
3
4
|
import type {PrivateKey} from "@libp2p/interface";
|
|
@@ -9,12 +10,20 @@ import {Libp2pInit, createLibp2p} from "libp2p";
|
|
|
9
10
|
import {Registry} from "prom-client";
|
|
10
11
|
import {ENR} from "@chainsafe/enr";
|
|
11
12
|
import {noise} from "@chainsafe/libp2p-noise";
|
|
12
|
-
import {defaultCrypto} from "@chainsafe/libp2p-noise/crypto";
|
|
13
|
+
import {asCrypto, defaultCrypto} from "@chainsafe/libp2p-noise/crypto";
|
|
13
14
|
import {quic} from "@chainsafe/libp2p-quic";
|
|
14
15
|
import {Libp2p, LodestarComponents} from "../interface.js";
|
|
15
16
|
import {NetworkOptions, defaultNetworkOptions} from "../options.js";
|
|
16
17
|
import {Eth2PeerDataStore} from "../peers/datastore.js";
|
|
17
18
|
|
|
19
|
+
const noiseCrypto = getCiphers().includes("chacha20-poly1305")
|
|
20
|
+
? defaultCrypto
|
|
21
|
+
: {
|
|
22
|
+
...defaultCrypto,
|
|
23
|
+
chaCha20Poly1305Encrypt: asCrypto.chaCha20Poly1305Encrypt,
|
|
24
|
+
chaCha20Poly1305Decrypt: asCrypto.chaCha20Poly1305Decrypt,
|
|
25
|
+
};
|
|
26
|
+
|
|
18
27
|
export type NodeJsLibp2pOpts = {
|
|
19
28
|
peerStoreDir?: string;
|
|
20
29
|
disablePeerDiscovery?: boolean;
|
|
@@ -122,7 +131,7 @@ export async function createNodeJsLibp2p(
|
|
|
122
131
|
listen: localMultiaddrs,
|
|
123
132
|
announce: [],
|
|
124
133
|
},
|
|
125
|
-
connectionEncrypters: [noise({crypto:
|
|
134
|
+
connectionEncrypters: [noise({crypto: noiseCrypto})],
|
|
126
135
|
transports,
|
|
127
136
|
streamMuxers: [mplex({disconnectThreshold})],
|
|
128
137
|
peerDiscovery,
|