@lodestar/beacon-node 1.40.0-dev.4acd3ce568 → 1.40.0-dev.9defa5c09b
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 +8 -18
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/debug/index.d.ts +1 -1
- package/lib/api/impl/debug/index.d.ts.map +1 -1
- package/lib/api/impl/debug/index.js +3 -6
- package/lib/api/impl/debug/index.js.map +1 -1
- package/lib/api/impl/lodestar/index.d.ts.map +1 -1
- package/lib/api/impl/lodestar/index.js +5 -2
- package/lib/api/impl/lodestar/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +9 -8
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +4 -0
- package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.d.ts +2 -0
- package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.js +6 -0
- package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +2 -6
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +0 -14
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +0 -2
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +0 -7
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.d.ts +1 -4
- package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.js +20 -28
- package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
- package/lib/chain/chain.d.ts +21 -4
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +178 -13
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/errors/attestationError.d.ts +14 -1
- package/lib/chain/errors/attestationError.d.ts.map +1 -1
- package/lib/chain/errors/attestationError.js +8 -0
- package/lib/chain/errors/attestationError.js.map +1 -1
- package/lib/chain/errors/executionPayloadBid.d.ts +48 -0
- package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -0
- package/lib/chain/errors/executionPayloadBid.js +15 -0
- package/lib/chain/errors/executionPayloadBid.js.map +1 -0
- package/lib/chain/errors/executionPayloadEnvelope.d.ts +48 -0
- package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -0
- package/lib/chain/errors/executionPayloadEnvelope.js +16 -0
- package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -0
- package/lib/chain/errors/index.d.ts +3 -0
- package/lib/chain/errors/index.d.ts.map +1 -1
- package/lib/chain/errors/index.js +3 -0
- package/lib/chain/errors/index.js.map +1 -1
- package/lib/chain/errors/payloadAttestation.d.ts +34 -0
- package/lib/chain/errors/payloadAttestation.d.ts.map +1 -0
- package/lib/chain/errors/payloadAttestation.js +13 -0
- package/lib/chain/errors/payloadAttestation.js.map +1 -0
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +18 -0
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +21 -3
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/opPools/executionPayloadBidPool.d.ts +21 -0
- package/lib/chain/opPools/executionPayloadBidPool.d.ts.map +1 -0
- package/lib/chain/opPools/executionPayloadBidPool.js +57 -0
- package/lib/chain/opPools/executionPayloadBidPool.js.map +1 -0
- package/lib/chain/opPools/index.d.ts +2 -0
- package/lib/chain/opPools/index.d.ts.map +1 -1
- package/lib/chain/opPools/index.js +2 -0
- package/lib/chain/opPools/index.js.map +1 -1
- package/lib/chain/opPools/payloadAttestationPool.d.ts +24 -0
- package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -0
- package/lib/chain/opPools/payloadAttestationPool.js +109 -0
- package/lib/chain/opPools/payloadAttestationPool.js.map +1 -0
- package/lib/chain/prepareNextSlot.js +6 -4
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +3 -2
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +5 -3
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +3 -8
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/interface.js +1 -1
- package/lib/chain/regen/interface.js.map +1 -1
- package/lib/chain/regen/queued.d.ts +1 -2
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +2 -16
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/regen/regen.d.ts +3 -7
- package/lib/chain/regen/regen.d.ts.map +1 -1
- package/lib/chain/regen/regen.js +3 -16
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/seenCache/index.d.ts +3 -1
- package/lib/chain/seenCache/index.d.ts.map +1 -1
- package/lib/chain/seenCache/index.js +3 -1
- package/lib/chain/seenCache/index.js.map +1 -1
- package/lib/chain/seenCache/seenAttesters.d.ts +5 -0
- package/lib/chain/seenCache/seenAttesters.d.ts.map +1 -1
- package/lib/chain/seenCache/seenAttesters.js +5 -0
- package/lib/chain/seenCache/seenAttesters.js.map +1 -1
- package/lib/chain/seenCache/seenExecutionPayloadBids.d.ts +12 -0
- package/lib/chain/seenCache/seenExecutionPayloadBids.d.ts.map +1 -0
- package/lib/chain/seenCache/seenExecutionPayloadBids.js +30 -0
- package/lib/chain/seenCache/seenExecutionPayloadBids.js.map +1 -0
- package/lib/chain/seenCache/seenExecutionPayloadEnvelope.d.ts +15 -0
- package/lib/chain/seenCache/seenExecutionPayloadEnvelope.d.ts.map +1 -0
- package/lib/chain/seenCache/seenExecutionPayloadEnvelope.js +28 -0
- package/lib/chain/seenCache/seenExecutionPayloadEnvelope.js.map +1 -0
- package/lib/chain/validation/aggregateAndProof.js +32 -10
- package/lib/chain/validation/aggregateAndProof.js.map +1 -1
- package/lib/chain/validation/attestation.d.ts.map +1 -1
- package/lib/chain/validation/attestation.js +23 -4
- package/lib/chain/validation/attestation.js.map +1 -1
- package/lib/chain/validation/blobSidecar.js +1 -1
- package/lib/chain/validation/blobSidecar.js.map +1 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +4 -3
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.js +1 -1
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts +5 -0
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -0
- package/lib/chain/validation/executionPayloadBid.js +103 -0
- package/lib/chain/validation/executionPayloadBid.js.map +1 -0
- package/lib/chain/validation/executionPayloadEnvelope.d.ts +5 -0
- package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -0
- package/lib/chain/validation/executionPayloadEnvelope.js +89 -0
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -0
- package/lib/chain/validation/payloadAttestationMessage.d.ts +9 -0
- package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -0
- package/lib/chain/validation/payloadAttestationMessage.js +72 -0
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -0
- package/lib/chain/validatorMonitor.d.ts +2 -0
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +42 -3
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/db/repositories/checkpointState.js +0 -1
- package/lib/db/repositories/checkpointState.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +27 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +64 -0
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/interface.d.ts +20 -2
- package/lib/network/gossip/interface.d.ts.map +1 -1
- package/lib/network/gossip/interface.js +3 -0
- package/lib/network/gossip/interface.js.map +1 -1
- package/lib/network/gossip/scoringParameters.d.ts.map +1 -1
- package/lib/network/gossip/scoringParameters.js +38 -2
- package/lib/network/gossip/scoringParameters.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +77 -1
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/gossip/topic.js +20 -0
- package/lib/network/gossip/topic.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +34 -3
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/gossipQueues/index.d.ts.map +1 -1
- package/lib/network/processor/gossipQueues/index.js +16 -0
- package/lib/network/processor/gossipQueues/index.js.map +1 -1
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +3 -0
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRange.js +2 -4
- package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRoot.d.ts +1 -2
- package/lib/network/reqresp/handlers/beaconBlocksByRoot.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRoot.js +5 -26
- package/lib/network/reqresp/handlers/beaconBlocksByRoot.js.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.d.ts +1 -2
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.js +5 -7
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +1 -2
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +1 -5
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js.map +1 -1
- package/lib/network/reqresp/handlers/index.js +2 -2
- package/lib/network/reqresp/handlers/index.js.map +1 -1
- package/lib/sync/range/chain.d.ts.map +1 -1
- package/lib/sync/range/chain.js +0 -1
- package/lib/sync/range/chain.js.map +1 -1
- package/lib/sync/range/range.d.ts.map +1 -1
- package/lib/sync/range/range.js +0 -3
- package/lib/sync/range/range.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +0 -3
- package/lib/sync/unknownBlock.js.map +1 -1
- package/package.json +15 -15
- package/src/api/impl/beacon/blocks/index.ts +8 -18
- package/src/api/impl/debug/index.ts +2 -6
- package/src/api/impl/lodestar/index.ts +6 -3
- package/src/api/impl/validator/index.ts +12 -11
- package/src/chain/archiveStore/utils/archiveBlocks.ts +4 -0
- package/src/chain/blocks/blockInput/blockInput.ts +8 -0
- package/src/chain/blocks/importBlock.ts +2 -6
- package/src/chain/blocks/index.ts +0 -19
- package/src/chain/blocks/types.ts +0 -2
- package/src/chain/blocks/verifyBlock.ts +0 -8
- package/src/chain/blocks/writeBlockInputToDb.ts +24 -30
- package/src/chain/chain.ts +203 -21
- package/src/chain/errors/attestationError.ts +11 -1
- package/src/chain/errors/executionPayloadBid.ts +35 -0
- package/src/chain/errors/executionPayloadEnvelope.ts +34 -0
- package/src/chain/errors/index.ts +3 -0
- package/src/chain/errors/payloadAttestation.ts +25 -0
- package/src/chain/forkChoice/index.ts +19 -0
- package/src/chain/interface.ts +32 -1
- package/src/chain/opPools/executionPayloadBidPool.ts +77 -0
- package/src/chain/opPools/index.ts +2 -0
- package/src/chain/opPools/payloadAttestationPool.ts +157 -0
- package/src/chain/prepareNextSlot.ts +6 -6
- package/src/chain/produceBlock/produceBlockBody.ts +7 -5
- package/src/chain/regen/interface.ts +2 -12
- package/src/chain/regen/queued.ts +3 -23
- package/src/chain/regen/regen.ts +4 -24
- package/src/chain/seenCache/index.ts +3 -1
- package/src/chain/seenCache/seenAttesters.ts +5 -0
- package/src/chain/seenCache/seenExecutionPayloadBids.ts +35 -0
- package/src/chain/seenCache/seenExecutionPayloadEnvelope.ts +34 -0
- package/src/chain/validation/aggregateAndProof.ts +33 -10
- package/src/chain/validation/attestation.ts +24 -3
- package/src/chain/validation/blobSidecar.ts +1 -1
- package/src/chain/validation/block.ts +4 -3
- package/src/chain/validation/dataColumnSidecar.ts +1 -1
- package/src/chain/validation/executionPayloadBid.ts +140 -0
- package/src/chain/validation/executionPayloadEnvelope.ts +122 -0
- package/src/chain/validation/payloadAttestationMessage.ts +109 -0
- package/src/chain/validatorMonitor.ts +52 -3
- package/src/db/repositories/checkpointState.ts +1 -1
- package/src/metrics/metrics/lodestar.ts +65 -0
- package/src/network/gossip/interface.ts +17 -0
- package/src/network/gossip/scoringParameters.ts +44 -2
- package/src/network/gossip/topic.ts +21 -0
- package/src/network/processor/gossipHandlers.ts +48 -3
- package/src/network/processor/gossipQueues/index.ts +16 -0
- package/src/network/processor/index.ts +3 -0
- package/src/network/reqresp/handlers/beaconBlocksByRange.ts +2 -4
- package/src/network/reqresp/handlers/beaconBlocksByRoot.ts +5 -32
- package/src/network/reqresp/handlers/blobSidecarsByRoot.ts +5 -9
- package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +5 -2
- package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +1 -5
- package/src/network/reqresp/handlers/index.ts +2 -2
- package/src/sync/range/chain.ts +0 -1
- package/src/sync/range/range.ts +0 -3
- package/src/sync/unknownBlock.ts +0 -3
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
altair,
|
|
25
25
|
deneb,
|
|
26
26
|
} from "@lodestar/types";
|
|
27
|
-
import {LogData, LogHandler, LogLevel, Logger, MapDef, MapDefMax, toRootHex} from "@lodestar/utils";
|
|
27
|
+
import {LogData, LogHandler, LogLevel, Logger, MapDef, MapDefMax, prettyPrintIndices, toRootHex} from "@lodestar/utils";
|
|
28
28
|
import {GENESIS_SLOT} from "../constants/constants.js";
|
|
29
29
|
import {RegistryMetricCreator} from "../metrics/index.js";
|
|
30
30
|
|
|
@@ -39,7 +39,8 @@ const MAX_CACHED_DISTINCT_TARGETS = 4;
|
|
|
39
39
|
const LATE_ATTESTATION_SUBMISSION_BPS = 5000;
|
|
40
40
|
const LATE_BLOCK_SUBMISSION_BPS = 2500;
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
/** Number of epochs to retain registered validators after their last registration */
|
|
43
|
+
const RETAIN_REGISTERED_VALIDATORS_EPOCHS = 2;
|
|
43
44
|
|
|
44
45
|
type Seconds = number;
|
|
45
46
|
export enum OpSource {
|
|
@@ -97,6 +98,8 @@ export type ValidatorMonitor = {
|
|
|
97
98
|
): void;
|
|
98
99
|
onceEveryEndOfEpoch(state: CachedBeaconStateAllForks): void;
|
|
99
100
|
scrapeMetrics(slotClock: Slot): void;
|
|
101
|
+
/** Returns the list of validator indices currently being monitored */
|
|
102
|
+
getMonitoredValidatorIndices(): ValidatorIndex[];
|
|
100
103
|
};
|
|
101
104
|
|
|
102
105
|
export type ValidatorMonitorOpts = {
|
|
@@ -284,6 +287,9 @@ export function createValidatorMonitor(
|
|
|
284
287
|
logger[logLevel](message, context);
|
|
285
288
|
};
|
|
286
289
|
|
|
290
|
+
// Calculate retain time dynamically based on slot duration (2 epochs)
|
|
291
|
+
const retainRegisteredValidatorsMs = SLOTS_PER_EPOCH * config.SLOT_DURATION_MS * RETAIN_REGISTERED_VALIDATORS_EPOCHS;
|
|
292
|
+
|
|
287
293
|
/** The validators that require additional monitoring. */
|
|
288
294
|
const validators = new MapDef<ValidatorIndex, MonitoredValidator>(() => ({
|
|
289
295
|
summaries: new Map<Epoch, EpochSummary>(),
|
|
@@ -306,11 +312,19 @@ export function createValidatorMonitor(
|
|
|
306
312
|
|
|
307
313
|
let lastRegisteredStatusEpoch = -1;
|
|
308
314
|
|
|
315
|
+
// Track validator additions/removals per epoch for logging
|
|
316
|
+
const addedValidatorsInEpoch: Set<ValidatorIndex> = new Set();
|
|
317
|
+
const removedValidatorsInEpoch: Set<ValidatorIndex> = new Set();
|
|
318
|
+
|
|
309
319
|
const validatorMonitorMetrics = metricsRegister ? createValidatorMonitorMetrics(metricsRegister) : null;
|
|
310
320
|
|
|
311
321
|
const validatorMonitor: ValidatorMonitor = {
|
|
312
322
|
registerLocalValidator(index) {
|
|
323
|
+
const isNewValidator = !validators.has(index);
|
|
313
324
|
validators.getOrDefault(index).lastRegisteredTimeMs = Date.now();
|
|
325
|
+
if (isNewValidator) {
|
|
326
|
+
addedValidatorsInEpoch.add(index);
|
|
327
|
+
}
|
|
314
328
|
},
|
|
315
329
|
|
|
316
330
|
registerLocalValidatorInSyncCommittee(index, untilEpoch) {
|
|
@@ -673,11 +687,29 @@ export function createValidatorMonitor(
|
|
|
673
687
|
|
|
674
688
|
// Prune validators not seen in a while
|
|
675
689
|
for (const [index, validator] of validators.entries()) {
|
|
676
|
-
if (Date.now() - validator.lastRegisteredTimeMs >
|
|
690
|
+
if (Date.now() - validator.lastRegisteredTimeMs > retainRegisteredValidatorsMs) {
|
|
677
691
|
validators.delete(index);
|
|
692
|
+
removedValidatorsInEpoch.add(index);
|
|
678
693
|
}
|
|
679
694
|
}
|
|
680
695
|
|
|
696
|
+
// Log validator monitor status every epoch
|
|
697
|
+
const allIndices = Array.from(validators.keys()).sort((a, b) => a - b);
|
|
698
|
+
const addedIndices = Array.from(addedValidatorsInEpoch).sort((a, b) => a - b);
|
|
699
|
+
const removedIndices = Array.from(removedValidatorsInEpoch).sort((a, b) => a - b);
|
|
700
|
+
|
|
701
|
+
log("Validator monitor status", {
|
|
702
|
+
epoch: computeEpochAtSlot(headState.slot),
|
|
703
|
+
added: addedIndices.length > 0 ? prettyPrintIndices(addedIndices) : "none",
|
|
704
|
+
removed: removedIndices.length > 0 ? prettyPrintIndices(removedIndices) : "none",
|
|
705
|
+
total: validators.size,
|
|
706
|
+
indices: prettyPrintIndices(allIndices),
|
|
707
|
+
});
|
|
708
|
+
|
|
709
|
+
// Clear tracking sets for next epoch
|
|
710
|
+
addedValidatorsInEpoch.clear();
|
|
711
|
+
removedValidatorsInEpoch.clear();
|
|
712
|
+
|
|
681
713
|
// Compute summaries of previous epoch attestation performance
|
|
682
714
|
const prevEpoch = computeEpochAtSlot(headState.slot) - 1;
|
|
683
715
|
|
|
@@ -736,6 +768,13 @@ export function createValidatorMonitor(
|
|
|
736
768
|
scrapeMetrics(slotClock) {
|
|
737
769
|
validatorMonitorMetrics?.validatorsConnected.set(validators.size);
|
|
738
770
|
|
|
771
|
+
// Update static metric with connected validator indices
|
|
772
|
+
if (validatorMonitorMetrics?.validatorsConnectedIndices) {
|
|
773
|
+
validatorMonitorMetrics.validatorsConnectedIndices.reset();
|
|
774
|
+
const allIndices = Array.from(validators.keys()).sort((a, b) => a - b);
|
|
775
|
+
validatorMonitorMetrics.validatorsConnectedIndices.set({indices: prettyPrintIndices(allIndices)}, 1);
|
|
776
|
+
}
|
|
777
|
+
|
|
739
778
|
const epoch = computeEpochAtSlot(slotClock);
|
|
740
779
|
const slotInEpoch = slotClock % SLOTS_PER_EPOCH;
|
|
741
780
|
|
|
@@ -815,6 +854,10 @@ export function createValidatorMonitor(
|
|
|
815
854
|
validatorMonitorMetrics?.prevEpochSyncCommitteeHits.set(prevEpochSyncCommitteeHits);
|
|
816
855
|
validatorMonitorMetrics?.prevEpochSyncCommitteeMisses.set(prevEpochSyncCommitteeMisses);
|
|
817
856
|
},
|
|
857
|
+
|
|
858
|
+
getMonitoredValidatorIndices() {
|
|
859
|
+
return Array.from(validators.keys()).sort((a, b) => a - b);
|
|
860
|
+
},
|
|
818
861
|
};
|
|
819
862
|
|
|
820
863
|
// Register a single collect() function to run all validatorMonitor metrics
|
|
@@ -1098,6 +1141,12 @@ function createValidatorMonitorMetrics(register: RegistryMetricCreator) {
|
|
|
1098
1141
|
help: "Count of validators that are specifically monitored by this beacon node",
|
|
1099
1142
|
}),
|
|
1100
1143
|
|
|
1144
|
+
validatorsConnectedIndices: register.gauge<{indices: string}>({
|
|
1145
|
+
name: "validator_monitor_indices",
|
|
1146
|
+
help: "Static metric with connected validator indices as label, value is always 1",
|
|
1147
|
+
labelNames: ["indices"],
|
|
1148
|
+
}),
|
|
1149
|
+
|
|
1101
1150
|
validatorsInSyncCommittee: register.gauge({
|
|
1102
1151
|
name: "validator_monitor_validators_in_sync_committee",
|
|
1103
1152
|
help: "Count of validators monitored by this beacon node that are part of sync committee",
|
|
@@ -9,7 +9,7 @@ import {Bucket, getBucketNameByValue} from "../buckets.js";
|
|
|
9
9
|
export class CheckpointStateRepository extends BinaryRepository<Uint8Array> {
|
|
10
10
|
constructor(config: ChainForkConfig, db: Db) {
|
|
11
11
|
const bucket = Bucket.allForks_checkpointState;
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
super(config, db, bucket, getBucketNameByValue(bucket));
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -212,6 +212,31 @@ export function createLodestarMetrics(
|
|
|
212
212
|
}),
|
|
213
213
|
},
|
|
214
214
|
|
|
215
|
+
unfinalizedBlockWritesQueue: {
|
|
216
|
+
length: register.gauge({
|
|
217
|
+
name: "lodestar_unfinalized_block_writes_queue_length",
|
|
218
|
+
help: "Count of total unfinalized block writes queue length",
|
|
219
|
+
}),
|
|
220
|
+
droppedJobs: register.gauge({
|
|
221
|
+
name: "lodestar_unfinalized_block_writes_queue_dropped_jobs_total",
|
|
222
|
+
help: "Count of total unfinalized block writes queue dropped jobs",
|
|
223
|
+
}),
|
|
224
|
+
jobTime: register.histogram({
|
|
225
|
+
name: "lodestar_unfinalized_block_writes_queue_job_time_seconds",
|
|
226
|
+
help: "Time to process unfinalized block writes queue job in seconds",
|
|
227
|
+
buckets: [0.01, 0.1, 1, 4, 12],
|
|
228
|
+
}),
|
|
229
|
+
jobWaitTime: register.histogram({
|
|
230
|
+
name: "lodestar_unfinalized_block_writes_queue_job_wait_time_seconds",
|
|
231
|
+
help: "Time from job added to the unfinalized block writes queue to starting in seconds",
|
|
232
|
+
buckets: [0.01, 0.1, 1, 4, 12],
|
|
233
|
+
}),
|
|
234
|
+
concurrency: register.gauge({
|
|
235
|
+
name: "lodestar_unfinalized_block_writes_queue_concurrency",
|
|
236
|
+
help: "Current concurrency of unfinalized block writes queue",
|
|
237
|
+
}),
|
|
238
|
+
},
|
|
239
|
+
|
|
215
240
|
engineHttpProcessorQueue: {
|
|
216
241
|
length: register.gauge({
|
|
217
242
|
name: "lodestar_engine_http_processor_queue_length",
|
|
@@ -1116,6 +1141,46 @@ export function createLodestarMetrics(
|
|
|
1116
1141
|
help: "Total number of empty returns in SyncContributionAndProofPool.getAggregate(slot, root)",
|
|
1117
1142
|
}),
|
|
1118
1143
|
},
|
|
1144
|
+
payloadAttestationPool: {
|
|
1145
|
+
size: register.gauge({
|
|
1146
|
+
name: "lodestar_oppool_payload_attestation_pool_size",
|
|
1147
|
+
help: "Current size of the PayloadAttestationPool = total payload attestations unique by data and slot",
|
|
1148
|
+
}),
|
|
1149
|
+
payloadAttDataPerSlot: register.gauge({
|
|
1150
|
+
name: "lodestar_oppool_payload_attestation_pool_payload_attestation_data_per_slot_total",
|
|
1151
|
+
help: "Total number of payload attestation data per slot in PayloadAttestationPool",
|
|
1152
|
+
}),
|
|
1153
|
+
gossipInsertOutcome: register.counter<{insertOutcome: InsertOutcome}>({
|
|
1154
|
+
name: "lodestar_oppool_payload_attestation_pool_gossip_insert_outcome_total",
|
|
1155
|
+
help: "Total number of InsertOutcome as a result of adding a payload attestation message from gossip to the pool",
|
|
1156
|
+
labelNames: ["insertOutcome"],
|
|
1157
|
+
}),
|
|
1158
|
+
apiInsertOutcome: register.counter<{insertOutcome: InsertOutcome}>({
|
|
1159
|
+
name: "lodestar_oppool_payload_attestation_pool_api_insert_outcome_total",
|
|
1160
|
+
help: "Total number of InsertOutcome as a result of adding a payload attestation message from api to the pool",
|
|
1161
|
+
labelNames: ["insertOutcome"],
|
|
1162
|
+
}),
|
|
1163
|
+
getPayloadAttestationsCacheMisses: register.counter({
|
|
1164
|
+
name: "lodestar_oppool_payload_attestation_pool_get_payload_attestations_cache_misses_total",
|
|
1165
|
+
help: "Total number of getPayloadAttestationsForBlock calls with no aggregate for slot and payload attestation data root",
|
|
1166
|
+
}),
|
|
1167
|
+
},
|
|
1168
|
+
executionPayloadBidPool: {
|
|
1169
|
+
size: register.gauge({
|
|
1170
|
+
name: "lodestar_oppool_execution_payload_bid_pool_size",
|
|
1171
|
+
help: "Current size of the ExecutionPayloadBidPool = total number of bids",
|
|
1172
|
+
}),
|
|
1173
|
+
gossipInsertOutcome: register.counter<{insertOutcome: InsertOutcome}>({
|
|
1174
|
+
name: "lodestar_oppool_execution_payload_bid_pool_gossip_insert_outcome_total",
|
|
1175
|
+
help: "Total number of InsertOutcome as a result of adding an execution payload bid from gossip to the pool",
|
|
1176
|
+
labelNames: ["insertOutcome"],
|
|
1177
|
+
}),
|
|
1178
|
+
apiInsertOutcome: register.counter<{insertOutcome: InsertOutcome}>({
|
|
1179
|
+
name: "lodestar_oppool_execution_payload_bid_pool_api_insert_outcome_total",
|
|
1180
|
+
help: "Total number of InsertOutcome as a result of adding an execution payload bid from api to the pool",
|
|
1181
|
+
labelNames: ["insertOutcome"],
|
|
1182
|
+
}),
|
|
1183
|
+
},
|
|
1119
1184
|
},
|
|
1120
1185
|
|
|
1121
1186
|
chain: {
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
capella,
|
|
16
16
|
deneb,
|
|
17
17
|
fulu,
|
|
18
|
+
gloas,
|
|
18
19
|
phase0,
|
|
19
20
|
} from "@lodestar/types";
|
|
20
21
|
import {Logger} from "@lodestar/utils";
|
|
@@ -37,6 +38,9 @@ export enum GossipType {
|
|
|
37
38
|
light_client_finality_update = "light_client_finality_update",
|
|
38
39
|
light_client_optimistic_update = "light_client_optimistic_update",
|
|
39
40
|
bls_to_execution_change = "bls_to_execution_change",
|
|
41
|
+
execution_payload = "execution_payload",
|
|
42
|
+
payload_attestation_message = "payload_attestation_message",
|
|
43
|
+
execution_payload_bid = "execution_payload_bid",
|
|
40
44
|
}
|
|
41
45
|
|
|
42
46
|
export type SequentialGossipType = Exclude<GossipType, GossipType.beacon_attestation>;
|
|
@@ -71,6 +75,9 @@ export type GossipTopicTypeMap = {
|
|
|
71
75
|
[GossipType.light_client_finality_update]: {type: GossipType.light_client_finality_update};
|
|
72
76
|
[GossipType.light_client_optimistic_update]: {type: GossipType.light_client_optimistic_update};
|
|
73
77
|
[GossipType.bls_to_execution_change]: {type: GossipType.bls_to_execution_change};
|
|
78
|
+
[GossipType.execution_payload]: {type: GossipType.execution_payload};
|
|
79
|
+
[GossipType.payload_attestation_message]: {type: GossipType.payload_attestation_message};
|
|
80
|
+
[GossipType.execution_payload_bid]: {type: GossipType.execution_payload_bid};
|
|
74
81
|
};
|
|
75
82
|
|
|
76
83
|
export type GossipTopicMap = {
|
|
@@ -100,6 +107,9 @@ export type GossipTypeMap = {
|
|
|
100
107
|
[GossipType.light_client_finality_update]: LightClientFinalityUpdate;
|
|
101
108
|
[GossipType.light_client_optimistic_update]: LightClientOptimisticUpdate;
|
|
102
109
|
[GossipType.bls_to_execution_change]: capella.SignedBLSToExecutionChange;
|
|
110
|
+
[GossipType.execution_payload]: gloas.SignedExecutionPayloadEnvelope;
|
|
111
|
+
[GossipType.payload_attestation_message]: gloas.PayloadAttestationMessage;
|
|
112
|
+
[GossipType.execution_payload_bid]: gloas.SignedExecutionPayloadBid;
|
|
103
113
|
};
|
|
104
114
|
|
|
105
115
|
export type GossipFnByType = {
|
|
@@ -124,6 +134,13 @@ export type GossipFnByType = {
|
|
|
124
134
|
[GossipType.bls_to_execution_change]: (
|
|
125
135
|
blsToExecutionChange: capella.SignedBLSToExecutionChange
|
|
126
136
|
) => Promise<void> | void;
|
|
137
|
+
[GossipType.execution_payload]: (
|
|
138
|
+
executionPayloadEnvelope: gloas.SignedExecutionPayloadEnvelope
|
|
139
|
+
) => Promise<void> | void;
|
|
140
|
+
[GossipType.payload_attestation_message]: (
|
|
141
|
+
payloadAttestationMessage: gloas.PayloadAttestationMessage
|
|
142
|
+
) => Promise<void> | void;
|
|
143
|
+
[GossipType.execution_payload_bid]: (executionPayloadBid: gloas.SignedExecutionPayloadBid) => Promise<void> | void;
|
|
127
144
|
};
|
|
128
145
|
|
|
129
146
|
export type GossipFn = GossipFnByType[keyof GossipFnByType];
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
defaultTopicScoreParams,
|
|
6
6
|
} from "@chainsafe/libp2p-gossipsub/score";
|
|
7
7
|
import {BeaconConfig} from "@lodestar/config";
|
|
8
|
-
import {ATTESTATION_SUBNET_COUNT, SLOTS_PER_EPOCH, TARGET_AGGREGATORS_PER_COMMITTEE} from "@lodestar/params";
|
|
8
|
+
import {ATTESTATION_SUBNET_COUNT, PTC_SIZE, SLOTS_PER_EPOCH, TARGET_AGGREGATORS_PER_COMMITTEE} from "@lodestar/params";
|
|
9
9
|
import {computeCommitteeCount} from "@lodestar/state-transition";
|
|
10
10
|
import {getActiveForkBoundaries} from "../forks.js";
|
|
11
11
|
import {Eth2Context} from "./gossipsub.js";
|
|
@@ -24,6 +24,9 @@ const VOLUNTARY_EXIT_WEIGHT = 0.05;
|
|
|
24
24
|
const PROPOSER_SLASHING_WEIGHT = 0.05;
|
|
25
25
|
const ATTESTER_SLASHING_WEIGHT = 0.05;
|
|
26
26
|
const BLS_TO_EXECUTION_CHANGE_WEIGHT = 0.05;
|
|
27
|
+
const EXECUTION_PAYLOAD_WEIGHT = 0.5;
|
|
28
|
+
const PAYLOAD_ATTESTATION_WEIGHT = 0.05;
|
|
29
|
+
const EXECUTION_PAYLOAD_BID_WEIGHT = 0.05;
|
|
27
30
|
|
|
28
31
|
const beaconAttestationSubnetWeight = 1 / ATTESTATION_SUBNET_COUNT;
|
|
29
32
|
const maxPositiveScore =
|
|
@@ -34,7 +37,10 @@ const maxPositiveScore =
|
|
|
34
37
|
VOLUNTARY_EXIT_WEIGHT +
|
|
35
38
|
PROPOSER_SLASHING_WEIGHT +
|
|
36
39
|
ATTESTER_SLASHING_WEIGHT +
|
|
37
|
-
BLS_TO_EXECUTION_CHANGE_WEIGHT
|
|
40
|
+
BLS_TO_EXECUTION_CHANGE_WEIGHT +
|
|
41
|
+
EXECUTION_PAYLOAD_WEIGHT +
|
|
42
|
+
PAYLOAD_ATTESTATION_WEIGHT +
|
|
43
|
+
EXECUTION_PAYLOAD_BID_WEIGHT);
|
|
38
44
|
|
|
39
45
|
/**
|
|
40
46
|
* The following params is implemented by Lighthouse at
|
|
@@ -172,6 +178,26 @@ function getAllTopicsScoreParams(
|
|
|
172
178
|
expectedMessageRate: 1 / 5 / SLOTS_PER_EPOCH,
|
|
173
179
|
firstMessageDecayTime: epochDurationMs * 100,
|
|
174
180
|
});
|
|
181
|
+
topicsParams[
|
|
182
|
+
stringifyGossipTopic(config, {
|
|
183
|
+
type: GossipType.payload_attestation_message,
|
|
184
|
+
boundary,
|
|
185
|
+
})
|
|
186
|
+
] = getTopicScoreParams(config, precomputedParams, {
|
|
187
|
+
topicWeight: PAYLOAD_ATTESTATION_WEIGHT,
|
|
188
|
+
expectedMessageRate: PTC_SIZE,
|
|
189
|
+
firstMessageDecayTime: epochDurationMs * 100,
|
|
190
|
+
});
|
|
191
|
+
topicsParams[
|
|
192
|
+
stringifyGossipTopic(config, {
|
|
193
|
+
type: GossipType.execution_payload_bid,
|
|
194
|
+
boundary,
|
|
195
|
+
})
|
|
196
|
+
] = getTopicScoreParams(config, precomputedParams, {
|
|
197
|
+
topicWeight: EXECUTION_PAYLOAD_BID_WEIGHT,
|
|
198
|
+
expectedMessageRate: 1024, // TODO GLOAS: Need an estimate for this
|
|
199
|
+
firstMessageDecayTime: epochDurationMs * 100,
|
|
200
|
+
});
|
|
175
201
|
|
|
176
202
|
// other topics
|
|
177
203
|
topicsParams[
|
|
@@ -190,6 +216,22 @@ function getAllTopicsScoreParams(
|
|
|
190
216
|
currentSlot: eth2Context.currentSlot,
|
|
191
217
|
},
|
|
192
218
|
});
|
|
219
|
+
topicsParams[
|
|
220
|
+
stringifyGossipTopic(config, {
|
|
221
|
+
type: GossipType.execution_payload,
|
|
222
|
+
boundary,
|
|
223
|
+
})
|
|
224
|
+
] = getTopicScoreParams(config, precomputedParams, {
|
|
225
|
+
topicWeight: EXECUTION_PAYLOAD_WEIGHT,
|
|
226
|
+
expectedMessageRate: 1,
|
|
227
|
+
firstMessageDecayTime: epochDurationMs * 20,
|
|
228
|
+
meshMessageInfo: {
|
|
229
|
+
decaySlots: SLOTS_PER_EPOCH * 5,
|
|
230
|
+
capFactor: 3,
|
|
231
|
+
activationWindow: epochDurationMs,
|
|
232
|
+
currentSlot: eth2Context.currentSlot,
|
|
233
|
+
},
|
|
234
|
+
});
|
|
193
235
|
|
|
194
236
|
const activeValidatorCount = eth2Context.activeValidatorCount;
|
|
195
237
|
const {aggregatorsPerslot, committeesPerSlot} = expectedAggregatorCountPerSlot(activeValidatorCount);
|
|
@@ -69,6 +69,9 @@ function stringifyGossipTopicType(topic: GossipTopic): string {
|
|
|
69
69
|
case GossipType.light_client_finality_update:
|
|
70
70
|
case GossipType.light_client_optimistic_update:
|
|
71
71
|
case GossipType.bls_to_execution_change:
|
|
72
|
+
case GossipType.execution_payload:
|
|
73
|
+
case GossipType.payload_attestation_message:
|
|
74
|
+
case GossipType.execution_payload_bid:
|
|
72
75
|
return topic.type;
|
|
73
76
|
case GossipType.beacon_attestation:
|
|
74
77
|
case GossipType.sync_committee:
|
|
@@ -114,6 +117,12 @@ export function getGossipSSZType(topic: GossipTopic) {
|
|
|
114
117
|
: ssz.altair.LightClientFinalityUpdate;
|
|
115
118
|
case GossipType.bls_to_execution_change:
|
|
116
119
|
return ssz.capella.SignedBLSToExecutionChange;
|
|
120
|
+
case GossipType.execution_payload:
|
|
121
|
+
return ssz.gloas.SignedExecutionPayloadEnvelope;
|
|
122
|
+
case GossipType.payload_attestation_message:
|
|
123
|
+
return ssz.gloas.PayloadAttestationMessage;
|
|
124
|
+
case GossipType.execution_payload_bid:
|
|
125
|
+
return ssz.gloas.SignedExecutionPayloadBid;
|
|
117
126
|
}
|
|
118
127
|
}
|
|
119
128
|
|
|
@@ -190,6 +199,9 @@ export function parseGossipTopic(forkDigestContext: ForkDigestContext, topicStr:
|
|
|
190
199
|
case GossipType.light_client_finality_update:
|
|
191
200
|
case GossipType.light_client_optimistic_update:
|
|
192
201
|
case GossipType.bls_to_execution_change:
|
|
202
|
+
case GossipType.execution_payload:
|
|
203
|
+
case GossipType.payload_attestation_message:
|
|
204
|
+
case GossipType.execution_payload_bid:
|
|
193
205
|
return {type: gossipTypeStr, boundary, encoding};
|
|
194
206
|
}
|
|
195
207
|
|
|
@@ -240,6 +252,12 @@ export function getCoreTopicsAtFork(
|
|
|
240
252
|
{type: GossipType.attester_slashing},
|
|
241
253
|
];
|
|
242
254
|
|
|
255
|
+
if (ForkSeq[fork] >= ForkSeq.gloas) {
|
|
256
|
+
topics.push({type: GossipType.execution_payload});
|
|
257
|
+
topics.push({type: GossipType.payload_attestation_message});
|
|
258
|
+
topics.push({type: GossipType.execution_payload_bid});
|
|
259
|
+
}
|
|
260
|
+
|
|
243
261
|
// After fulu also track data_column_sidecar_{index}
|
|
244
262
|
if (ForkSeq[fork] >= ForkSeq.fulu) {
|
|
245
263
|
topics.push(...getDataColumnSidecarTopics(networkConfig));
|
|
@@ -329,4 +347,7 @@ export const gossipTopicIgnoreDuplicatePublishError: Record<GossipType, boolean>
|
|
|
329
347
|
[GossipType.light_client_finality_update]: false,
|
|
330
348
|
[GossipType.light_client_optimistic_update]: false,
|
|
331
349
|
[GossipType.bls_to_execution_change]: true,
|
|
350
|
+
[GossipType.execution_payload]: true,
|
|
351
|
+
[GossipType.payload_attestation_message]: true,
|
|
352
|
+
[GossipType.execution_payload_bid]: true,
|
|
332
353
|
};
|
|
@@ -48,6 +48,8 @@ import {
|
|
|
48
48
|
import {IBeaconChain} from "../../chain/interface.js";
|
|
49
49
|
import {validateGossipBlobSidecar} from "../../chain/validation/blobSidecar.js";
|
|
50
50
|
import {validateGossipDataColumnSidecar} from "../../chain/validation/dataColumnSidecar.js";
|
|
51
|
+
import {validateGossipExecutionPayloadBid} from "../../chain/validation/executionPayloadBid.js";
|
|
52
|
+
import {validateGossipExecutionPayloadEnvelope} from "../../chain/validation/executionPayloadEnvelope.js";
|
|
51
53
|
import {
|
|
52
54
|
AggregateAndProofValidationResult,
|
|
53
55
|
GossipAttestation,
|
|
@@ -64,6 +66,7 @@ import {
|
|
|
64
66
|
} from "../../chain/validation/index.js";
|
|
65
67
|
import {validateLightClientFinalityUpdate} from "../../chain/validation/lightClientFinalityUpdate.js";
|
|
66
68
|
import {validateLightClientOptimisticUpdate} from "../../chain/validation/lightClientOptimisticUpdate.js";
|
|
69
|
+
import {validateGossipPayloadAttestationMessage} from "../../chain/validation/payloadAttestationMessage.js";
|
|
67
70
|
import {OpSource} from "../../chain/validatorMonitor.js";
|
|
68
71
|
import {Metrics} from "../../metrics/index.js";
|
|
69
72
|
import {kzgCommitmentToVersionedHash} from "../../util/blobs.js";
|
|
@@ -436,14 +439,11 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
436
439
|
blsVerifyOnMainThread: true,
|
|
437
440
|
// to track block process steps
|
|
438
441
|
seenTimestampSec,
|
|
439
|
-
// gossip block is validated, we want to process it asap
|
|
440
|
-
eagerPersistBlock: true,
|
|
441
442
|
})
|
|
442
443
|
.then(() => {
|
|
443
444
|
// Returns the delay between the start of `block.slot` and `current time`
|
|
444
445
|
const delaySec = chain.clock.secFromSlot(slot);
|
|
445
446
|
metrics?.gossipBlock.elapsedTimeTillProcessed.observe(delaySec);
|
|
446
|
-
chain.seenBlockInputCache.prune(blockInput.blockRootHex);
|
|
447
447
|
})
|
|
448
448
|
.catch((e) => {
|
|
449
449
|
// Adjust verbosity based on error type
|
|
@@ -818,6 +818,51 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
818
818
|
|
|
819
819
|
chain.emitter.emit(routes.events.EventType.blsToExecutionChange, blsToExecutionChange);
|
|
820
820
|
},
|
|
821
|
+
[GossipType.execution_payload]: async ({
|
|
822
|
+
gossipData,
|
|
823
|
+
topic,
|
|
824
|
+
}: GossipHandlerParamGeneric<GossipType.execution_payload>) => {
|
|
825
|
+
const {serializedData} = gossipData;
|
|
826
|
+
const executionPayloadEnvelope = sszDeserialize(topic, serializedData);
|
|
827
|
+
await validateGossipExecutionPayloadEnvelope(chain, executionPayloadEnvelope);
|
|
828
|
+
|
|
829
|
+
// TODO GLOAS: Handle valid envelope. Need an import flow that calls `processExecutionPayloadEnvelope` and fork choice
|
|
830
|
+
},
|
|
831
|
+
[GossipType.payload_attestation_message]: async ({
|
|
832
|
+
gossipData,
|
|
833
|
+
topic,
|
|
834
|
+
}: GossipHandlerParamGeneric<GossipType.payload_attestation_message>) => {
|
|
835
|
+
const {serializedData} = gossipData;
|
|
836
|
+
const payloadAttestationMessage = sszDeserialize(topic, serializedData);
|
|
837
|
+
const validationResult = await validateGossipPayloadAttestationMessage(chain, payloadAttestationMessage);
|
|
838
|
+
|
|
839
|
+
try {
|
|
840
|
+
const insertOutcome = chain.payloadAttestationPool.add(
|
|
841
|
+
payloadAttestationMessage,
|
|
842
|
+
validationResult.attDataRootHex,
|
|
843
|
+
validationResult.validatorCommitteeIndex
|
|
844
|
+
);
|
|
845
|
+
metrics?.opPool.payloadAttestationPool.gossipInsertOutcome.inc({insertOutcome});
|
|
846
|
+
} catch (e) {
|
|
847
|
+
logger.error("Error adding to payloadAttestation pool", {}, e as Error);
|
|
848
|
+
}
|
|
849
|
+
},
|
|
850
|
+
[GossipType.execution_payload_bid]: async ({
|
|
851
|
+
gossipData,
|
|
852
|
+
topic,
|
|
853
|
+
}: GossipHandlerParamGeneric<GossipType.execution_payload_bid>) => {
|
|
854
|
+
const {serializedData} = gossipData;
|
|
855
|
+
const executionPayloadBid = sszDeserialize(topic, serializedData);
|
|
856
|
+
await validateGossipExecutionPayloadBid(chain, executionPayloadBid);
|
|
857
|
+
|
|
858
|
+
// Handle valid payload bid by storing in a bid pool
|
|
859
|
+
try {
|
|
860
|
+
const insertOutcome = chain.executionPayloadBidPool.add(executionPayloadBid.message);
|
|
861
|
+
metrics?.opPool.executionPayloadBidPool.gossipInsertOutcome.inc({insertOutcome});
|
|
862
|
+
} catch (e) {
|
|
863
|
+
logger.error("Error adding to executionPayloadBid pool", {}, e as Error);
|
|
864
|
+
}
|
|
865
|
+
},
|
|
821
866
|
};
|
|
822
867
|
}
|
|
823
868
|
|
|
@@ -67,6 +67,22 @@ const linearGossipQueueOpts: {
|
|
|
67
67
|
type: QueueType.FIFO,
|
|
68
68
|
dropOpts: {type: DropType.count, count: 1},
|
|
69
69
|
},
|
|
70
|
+
[GossipType.execution_payload]: {
|
|
71
|
+
maxLength: 1024,
|
|
72
|
+
type: QueueType.FIFO,
|
|
73
|
+
dropOpts: {type: DropType.count, count: 1},
|
|
74
|
+
},
|
|
75
|
+
[GossipType.payload_attestation_message]: {
|
|
76
|
+
maxLength: 1024,
|
|
77
|
+
type: QueueType.FIFO,
|
|
78
|
+
dropOpts: {type: DropType.count, count: 1},
|
|
79
|
+
},
|
|
80
|
+
// TODO GLOAS: It is hard to predict how many bids are there. Put 1024 for max length for now
|
|
81
|
+
[GossipType.execution_payload_bid]: {
|
|
82
|
+
maxLength: 1024,
|
|
83
|
+
type: QueueType.FIFO,
|
|
84
|
+
dropOpts: {type: DropType.count, count: 1},
|
|
85
|
+
},
|
|
70
86
|
};
|
|
71
87
|
|
|
72
88
|
const indexedGossipQueueOpts: {
|
|
@@ -78,6 +78,9 @@ const executeGossipWorkOrderObj: Record<GossipType, WorkOpts> = {
|
|
|
78
78
|
[GossipType.sync_committee]: {},
|
|
79
79
|
[GossipType.light_client_finality_update]: {},
|
|
80
80
|
[GossipType.light_client_optimistic_update]: {},
|
|
81
|
+
[GossipType.execution_payload]: {bypassQueue: true},
|
|
82
|
+
[GossipType.payload_attestation_message]: {},
|
|
83
|
+
[GossipType.execution_payload_bid]: {},
|
|
81
84
|
};
|
|
82
85
|
const executeGossipWorkOrder = Object.keys(executeGossipWorkOrderObj) as (keyof typeof executeGossipWorkOrderObj)[];
|
|
83
86
|
|
|
@@ -4,7 +4,6 @@ import {GENESIS_SLOT, isForkPostDeneb, isForkPostFulu} from "@lodestar/params";
|
|
|
4
4
|
import {RespStatus, ResponseError, ResponseOutgoing} from "@lodestar/reqresp";
|
|
5
5
|
import {computeEpochAtSlot} from "@lodestar/state-transition";
|
|
6
6
|
import {deneb, phase0} from "@lodestar/types";
|
|
7
|
-
import {fromHex} from "@lodestar/utils";
|
|
8
7
|
import {IBeaconChain} from "../../../chain/index.js";
|
|
9
8
|
import {IBeaconDb} from "../../../db/index.js";
|
|
10
9
|
import {prettyPrintPeerId} from "../../util.ts";
|
|
@@ -22,7 +21,6 @@ export async function* onBeaconBlocksByRange(
|
|
|
22
21
|
const endSlot = startSlot + count;
|
|
23
22
|
|
|
24
23
|
const finalized = db.blockArchive;
|
|
25
|
-
const unfinalized = db.block;
|
|
26
24
|
// in the case of initializing from a non-finalized state, we don't have the finalized block so this api does not work
|
|
27
25
|
// chain.forkChoice.getFinalizeBlock().slot
|
|
28
26
|
const finalizedSlot = chain.forkChoice.getFinalizedCheckpointSlot();
|
|
@@ -65,7 +63,7 @@ export async function* onBeaconBlocksByRange(
|
|
|
65
63
|
// re-org there's no need to abort the request
|
|
66
64
|
// Spec: https://github.com/ethereum/consensus-specs/blob/a1e46d1ae47dd9d097725801575b46907c12a1f8/specs/eip4844/p2p-interface.md#blobssidecarsbyrange-v1
|
|
67
65
|
|
|
68
|
-
const blockBytes = await
|
|
66
|
+
const blockBytes = await chain.getSerializedBlockByRoot(block.blockRoot);
|
|
69
67
|
if (!blockBytes) {
|
|
70
68
|
throw new ResponseError(
|
|
71
69
|
RespStatus.SERVER_ERROR,
|
|
@@ -74,7 +72,7 @@ export async function* onBeaconBlocksByRange(
|
|
|
74
72
|
}
|
|
75
73
|
|
|
76
74
|
yield {
|
|
77
|
-
data: blockBytes,
|
|
75
|
+
data: blockBytes.block,
|
|
78
76
|
boundary: chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(block.slot)),
|
|
79
77
|
};
|
|
80
78
|
}
|
|
@@ -1,48 +1,21 @@
|
|
|
1
1
|
import {ResponseOutgoing} from "@lodestar/reqresp";
|
|
2
2
|
import {computeEpochAtSlot} from "@lodestar/state-transition";
|
|
3
|
-
import {Slot} from "@lodestar/types";
|
|
4
3
|
import {toRootHex} from "@lodestar/utils";
|
|
5
4
|
import {IBeaconChain} from "../../../chain/index.js";
|
|
6
|
-
import {IBeaconDb} from "../../../db/index.js";
|
|
7
|
-
import {getSlotFromSignedBeaconBlockSerialized} from "../../../util/sszBytes.js";
|
|
8
5
|
import {BeaconBlocksByRootRequest} from "../../../util/types.js";
|
|
9
6
|
|
|
10
7
|
export async function* onBeaconBlocksByRoot(
|
|
11
8
|
requestBody: BeaconBlocksByRootRequest,
|
|
12
|
-
chain: IBeaconChain
|
|
13
|
-
db: IBeaconDb
|
|
9
|
+
chain: IBeaconChain
|
|
14
10
|
): AsyncIterable<ResponseOutgoing> {
|
|
15
11
|
for (const blockRoot of requestBody) {
|
|
16
12
|
const root = blockRoot;
|
|
17
|
-
const
|
|
18
|
-
let blockBytes: Uint8Array | null = null;
|
|
19
|
-
|
|
20
|
-
// finalized block has summary in forkchoice but it stays in blockArchive db
|
|
21
|
-
if (summary) {
|
|
22
|
-
blockBytes = await db.block.getBinary(root);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
let slot: Slot | undefined = undefined;
|
|
26
|
-
if (!blockBytes) {
|
|
27
|
-
const blockEntry = await db.blockArchive.getBinaryEntryByRoot(root);
|
|
28
|
-
if (blockEntry) {
|
|
29
|
-
slot = blockEntry.key;
|
|
30
|
-
blockBytes = blockEntry.value;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (blockBytes) {
|
|
35
|
-
if (slot === undefined) {
|
|
36
|
-
const slotFromBytes = getSlotFromSignedBeaconBlockSerialized(blockBytes);
|
|
37
|
-
if (slotFromBytes === null) {
|
|
38
|
-
throw Error(`Invalid block bytes for block root ${toRootHex(root)}`);
|
|
39
|
-
}
|
|
40
|
-
slot = slotFromBytes;
|
|
41
|
-
}
|
|
13
|
+
const block = await chain.getSerializedBlockByRoot(toRootHex(root));
|
|
42
14
|
|
|
15
|
+
if (block) {
|
|
43
16
|
yield {
|
|
44
|
-
data:
|
|
45
|
-
boundary: chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(slot)),
|
|
17
|
+
data: block.block,
|
|
18
|
+
boundary: chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(block.slot)),
|
|
46
19
|
};
|
|
47
20
|
}
|
|
48
21
|
}
|
|
@@ -2,16 +2,13 @@ import {BLOB_SIDECAR_FIXED_SIZE} from "@lodestar/params";
|
|
|
2
2
|
import {RespStatus, ResponseError, ResponseOutgoing} from "@lodestar/reqresp";
|
|
3
3
|
import {computeEpochAtSlot} from "@lodestar/state-transition";
|
|
4
4
|
import {RootHex} from "@lodestar/types";
|
|
5
|
-
import {
|
|
5
|
+
import {toRootHex} from "@lodestar/utils";
|
|
6
6
|
import {IBeaconChain} from "../../../chain/index.js";
|
|
7
|
-
import {IBeaconDb} from "../../../db/index.js";
|
|
8
|
-
import {BLOB_SIDECARS_IN_WRAPPER_INDEX} from "../../../db/repositories/blobSidecars.js";
|
|
9
7
|
import {BlobSidecarsByRootRequest} from "../../../util/types.js";
|
|
10
8
|
|
|
11
9
|
export async function* onBlobSidecarsByRoot(
|
|
12
10
|
requestBody: BlobSidecarsByRootRequest,
|
|
13
|
-
chain: IBeaconChain
|
|
14
|
-
db: IBeaconDb
|
|
11
|
+
chain: IBeaconChain
|
|
15
12
|
): AsyncIterable<ResponseOutgoing> {
|
|
16
13
|
const finalizedSlot = chain.forkChoice.getFinalizedBlock().slot;
|
|
17
14
|
|
|
@@ -34,14 +31,13 @@ export async function* onBlobSidecarsByRoot(
|
|
|
34
31
|
|
|
35
32
|
// Check if we need to load sidecars for a new block root
|
|
36
33
|
if (lastFetchedSideCars === null || lastFetchedSideCars.blockRoot !== blockRootHex) {
|
|
37
|
-
const
|
|
38
|
-
if (!
|
|
34
|
+
const blobSidecarsBytes = await chain.getSerializedBlobSidecars(block.slot, blockRootHex);
|
|
35
|
+
if (!blobSidecarsBytes) {
|
|
39
36
|
// Handle the same to onBeaconBlocksByRange
|
|
40
37
|
throw new ResponseError(RespStatus.SERVER_ERROR, `No item for root ${block.blockRoot} slot ${block.slot}`);
|
|
41
38
|
}
|
|
42
|
-
const blobSideCarsBytes = blobSideCarsBytesWrapped.slice(BLOB_SIDECARS_IN_WRAPPER_INDEX);
|
|
43
39
|
|
|
44
|
-
lastFetchedSideCars = {blockRoot: blockRootHex, bytes:
|
|
40
|
+
lastFetchedSideCars = {blockRoot: blockRootHex, bytes: blobSidecarsBytes};
|
|
45
41
|
}
|
|
46
42
|
|
|
47
43
|
const blobSidecarBytes = lastFetchedSideCars.bytes.slice(
|
|
@@ -38,7 +38,6 @@ export async function* onDataColumnSidecarsByRange(
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
const finalized = db.dataColumnSidecarArchive;
|
|
41
|
-
const unfinalized = db.dataColumnSidecar;
|
|
42
41
|
const finalizedSlot = chain.forkChoice.getFinalizedBlock().slot;
|
|
43
42
|
|
|
44
43
|
// Finalized range of columns
|
|
@@ -92,7 +91,11 @@ export async function* onDataColumnSidecarsByRange(
|
|
|
92
91
|
// at the time of the start of the request. Spec is clear the chain of columns must be consistent, but on
|
|
93
92
|
// re-org there's no need to abort the request
|
|
94
93
|
// Spec: https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/specs/fulu/p2p-interface.md#L425-L429
|
|
95
|
-
const dataColumnSidecars = await
|
|
94
|
+
const dataColumnSidecars = await chain.getSerializedDataColumnSidecars(
|
|
95
|
+
block.slot,
|
|
96
|
+
block.blockRoot,
|
|
97
|
+
availableColumns
|
|
98
|
+
);
|
|
96
99
|
|
|
97
100
|
const unavailableColumnIndices: ColumnIndex[] = [];
|
|
98
101
|
for (let i = 0; i < dataColumnSidecars.length; i++) {
|