@lodestar/beacon-node 1.35.0-dev.8689cc3545 → 1.35.0-dev.8961b06c11
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 -2
- package/lib/api/impl/beacon/blocks/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/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +22 -26
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/worker.js +1 -1
- package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.js +3 -2
- 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 +7 -6
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.js +8 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.js.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.js +1 -7
- package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +3 -4
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +2 -2
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/lightClient/index.d.ts +2 -2
- package/lib/chain/lightClient/index.d.ts.map +1 -1
- package/lib/chain/lightClient/index.js +2 -0
- package/lib/chain/lightClient/index.js.map +1 -1
- package/lib/chain/opPools/attestationPool.d.ts +2 -3
- package/lib/chain/opPools/attestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/attestationPool.js +3 -5
- package/lib/chain/opPools/attestationPool.js.map +1 -1
- package/lib/chain/opPools/syncCommitteeMessagePool.d.ts +3 -2
- package/lib/chain/opPools/syncCommitteeMessagePool.d.ts.map +1 -1
- package/lib/chain/opPools/syncCommitteeMessagePool.js +6 -5
- package/lib/chain/opPools/syncCommitteeMessagePool.js.map +1 -1
- package/lib/chain/opPools/types.d.ts +1 -1
- package/lib/chain/opPools/types.d.ts.map +1 -1
- package/lib/chain/opPools/types.js +1 -1
- package/lib/chain/opPools/types.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts +3 -3
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +8 -8
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +10 -2
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +1 -0
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/interface.js +1 -0
- package/lib/chain/regen/interface.js.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js +8 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +9 -8
- package/lib/chain/stateCache/persistentCheckpointsCache.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/lightClientFinalityUpdate.d.ts.map +1 -1
- package/lib/chain/validation/lightClientFinalityUpdate.js +4 -3
- package/lib/chain/validation/lightClientFinalityUpdate.js.map +1 -1
- package/lib/chain/validation/lightClientOptimisticUpdate.d.ts +6 -4
- package/lib/chain/validation/lightClientOptimisticUpdate.d.ts.map +1 -1
- package/lib/chain/validation/lightClientOptimisticUpdate.js +11 -11
- package/lib/chain/validation/lightClientOptimisticUpdate.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +21 -15
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +1 -1
- package/lib/metrics/metrics/lodestar.js +3 -3
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/gossipsub.js +1 -1
- package/lib/network/gossip/gossipsub.js.map +1 -1
- package/lib/network/gossip/scoringParameters.js +4 -4
- package/lib/network/gossip/scoringParameters.js.map +1 -1
- package/lib/network/network.d.ts +1 -1
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +9 -9
- package/lib/network/network.js.map +1 -1
- package/lib/network/peers/peerManager.d.ts.map +1 -1
- package/lib/network/peers/peerManager.js +2 -1
- package/lib/network/peers/peerManager.js.map +1 -1
- package/lib/network/processor/gossipHandlers.js +1 -1
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/index.d.ts +1 -1
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +2 -3
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/subnets/attnetsService.d.ts.map +1 -1
- package/lib/network/subnets/attnetsService.js +1 -1
- package/lib/network/subnets/attnetsService.js.map +1 -1
- package/lib/node/notifier.js +1 -1
- package/lib/node/notifier.js.map +1 -1
- package/lib/sync/types.d.ts +0 -1
- package/lib/sync/types.d.ts.map +1 -1
- package/lib/sync/types.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts +0 -1
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +18 -20
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts +2 -1
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +8 -3
- 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 +2 -1
- package/lib/sync/utils/downloadByRoot.js.map +1 -1
- package/lib/util/clock.d.ts +8 -3
- package/lib/util/clock.d.ts.map +1 -1
- package/lib/util/clock.js +8 -5
- package/lib/util/clock.js.map +1 -1
- package/lib/util/dataColumns.d.ts.map +1 -1
- package/lib/util/dataColumns.js +4 -2
- package/lib/util/dataColumns.js.map +1 -1
- package/package.json +14 -14
- package/src/api/impl/beacon/blocks/index.ts +11 -2
- package/src/api/impl/lodestar/index.ts +1 -1
- package/src/api/impl/validator/index.ts +25 -28
- package/src/chain/archiveStore/historicalState/worker.ts +1 -1
- package/src/chain/blocks/blockInput/blockInput.ts +7 -4
- package/src/chain/blocks/importBlock.ts +8 -12
- package/src/chain/blocks/verifyBlocksDataAvailability.ts +10 -2
- package/src/chain/blocks/writeBlockInputToDb.ts +1 -9
- package/src/chain/chain.ts +3 -14
- package/src/chain/emitter.ts +2 -2
- package/src/chain/lightClient/index.ts +11 -3
- package/src/chain/opPools/attestationPool.ts +2 -3
- package/src/chain/opPools/syncCommitteeMessagePool.ts +5 -3
- package/src/chain/opPools/types.ts +1 -1
- package/src/chain/prepareNextSlot.ts +8 -8
- package/src/chain/produceBlock/produceBlockBody.ts +13 -3
- package/src/chain/regen/interface.ts +1 -0
- package/src/chain/seenCache/seenGossipBlockInput.ts +10 -2
- package/src/chain/stateCache/persistentCheckpointsCache.ts +10 -8
- package/src/chain/validation/dataColumnSidecar.ts +1 -1
- package/src/chain/validation/lightClientFinalityUpdate.ts +4 -3
- package/src/chain/validation/lightClientOptimisticUpdate.ts +12 -11
- package/src/chain/validatorMonitor.ts +28 -17
- package/src/metrics/metrics/lodestar.ts +3 -3
- package/src/network/gossip/gossipsub.ts +1 -1
- package/src/network/gossip/scoringParameters.ts +4 -4
- package/src/network/network.ts +9 -9
- package/src/network/peers/peerManager.ts +2 -1
- package/src/network/processor/gossipHandlers.ts +1 -1
- package/src/network/processor/index.ts +2 -3
- package/src/network/subnets/attnetsService.ts +3 -6
- package/src/node/notifier.ts +1 -1
- package/src/sync/types.ts +0 -2
- package/src/sync/unknownBlock.ts +19 -21
- package/src/sync/utils/downloadByRange.ts +12 -6
- package/src/sync/utils/downloadByRoot.ts +12 -4
- package/src/util/clock.ts +14 -6
- package/src/util/dataColumns.ts +11 -2
|
@@ -99,7 +99,7 @@ export async function validateGossipDataColumnSidecar(
|
|
|
99
99
|
// this is something we should change this in the future to make the code airtight to the spec.
|
|
100
100
|
// 7) [REJECT] The sidecar's block's parent passes validation.
|
|
101
101
|
const blockState = await chain.regen
|
|
102
|
-
.getBlockSlotState(parentRoot, blockHeader.slot, {dontTransferCache: true}, RegenCaller.
|
|
102
|
+
.getBlockSlotState(parentRoot, blockHeader.slot, {dontTransferCache: true}, RegenCaller.validateGossipDataColumn)
|
|
103
103
|
.catch(() => {
|
|
104
104
|
throw new DataColumnSidecarGossipError(GossipAction.IGNORE, {
|
|
105
105
|
code: DataColumnSidecarErrorCode.PARENT_UNKNOWN,
|
|
@@ -25,9 +25,10 @@ export function validateLightClientFinalityUpdate(
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
// [IGNORE] The finality_update is received after the block at signature_slot was given enough time to propagate
|
|
28
|
-
// through the network -- i.e. validate that
|
|
29
|
-
// (
|
|
30
|
-
|
|
28
|
+
// through the network -- i.e. validate that `get_sync_message_due_ms(epoch)`
|
|
29
|
+
// milliseconds (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) has
|
|
30
|
+
// transpired since the start of `signature_slot`.
|
|
31
|
+
if (updateReceivedTooEarly(config, chain.clock, gossipedFinalityUpdate)) {
|
|
31
32
|
throw new LightClientError(GossipAction.IGNORE, {
|
|
32
33
|
code: LightClientErrorCode.FINALITY_UPDATE_RECEIVED_TOO_EARLY,
|
|
33
34
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {computeTimeAtSlot} from "@lodestar/state-transition";
|
|
3
2
|
import {LightClientOptimisticUpdate} from "@lodestar/types";
|
|
4
3
|
import {MAXIMUM_GOSSIP_CLOCK_DISPARITY} from "../../constants/index.js";
|
|
5
4
|
import {assertLightClientServer} from "../../node/utils/lightclient.js";
|
|
5
|
+
import {IClock} from "../../util/clock.js";
|
|
6
6
|
import {GossipAction} from "../errors/index.js";
|
|
7
7
|
import {LightClientError, LightClientErrorCode} from "../errors/lightClientError.js";
|
|
8
8
|
import {IBeaconChain} from "../interface.js";
|
|
@@ -26,9 +26,10 @@ export function validateLightClientOptimisticUpdate(
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// [IGNORE] The optimistic_update is received after the block at signature_slot was given enough time to propagate
|
|
29
|
-
// through the network -- i.e. validate that
|
|
30
|
-
// (
|
|
31
|
-
|
|
29
|
+
// through the network -- i.e. validate that `get_sync_message_due_ms(epoch)`
|
|
30
|
+
// milliseconds (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) has
|
|
31
|
+
// transpired since the start of `signature_slot`.
|
|
32
|
+
if (updateReceivedTooEarly(config, chain.clock, gossipedOptimisticUpdate)) {
|
|
32
33
|
throw new LightClientError(GossipAction.IGNORE, {
|
|
33
34
|
code: LightClientErrorCode.OPTIMISTIC_UPDATE_RECEIVED_TOO_EARLY,
|
|
34
35
|
});
|
|
@@ -48,20 +49,20 @@ export function validateLightClientOptimisticUpdate(
|
|
|
48
49
|
/**
|
|
49
50
|
* Returns true, if the spec condition below triggers an IGNORE.
|
|
50
51
|
*
|
|
51
|
-
* Sig +
|
|
52
|
+
* Sig + SYNC_MESSAGE_DUE_BPS time
|
|
52
53
|
* -----|-----
|
|
53
54
|
* xxx|------- (x is not okay)
|
|
54
55
|
*
|
|
55
56
|
* [IGNORE] The *update is received after the block at signature_slot was given enough time to propagate
|
|
56
|
-
* through the network -- i.e. validate that
|
|
57
|
-
* (
|
|
57
|
+
* through the network -- i.e. validate that `get_sync_message_due_ms(epoch)`
|
|
58
|
+
* milliseconds (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) has
|
|
59
|
+
* transpired since the start of `signature_slot`.
|
|
58
60
|
*/
|
|
59
61
|
export function updateReceivedTooEarly(
|
|
60
62
|
config: ChainForkConfig,
|
|
61
|
-
|
|
63
|
+
clock: IClock,
|
|
62
64
|
update: Pick<LightClientOptimisticUpdate, "signatureSlot">
|
|
63
65
|
): boolean {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
return Date.now() < earliestAllowedTimestampMs;
|
|
66
|
+
const fork = config.getForkName(update.signatureSlot);
|
|
67
|
+
return clock.msFromSlot(update.signatureSlot) < config.getSyncMessageDueMs(fork) - MAXIMUM_GOSSIP_CLOCK_DISPARITY;
|
|
67
68
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {ForkSeq,
|
|
1
|
+
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
+
import {ForkSeq, MIN_ATTESTATION_INCLUSION_DELAY, SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
3
3
|
import {
|
|
4
4
|
CachedBeaconStateAllForks,
|
|
5
5
|
CachedBeaconStateAltair,
|
|
6
6
|
ParticipationFlags,
|
|
7
7
|
computeEpochAtSlot,
|
|
8
8
|
computeStartSlotAtEpoch,
|
|
9
|
+
computeTimeAtSlot,
|
|
9
10
|
getBlockRootAtSlot,
|
|
10
11
|
getCurrentSlot,
|
|
11
12
|
parseAttesterFlags,
|
|
@@ -34,8 +35,9 @@ const MAX_CACHED_EPOCHS = 4;
|
|
|
34
35
|
|
|
35
36
|
const MAX_CACHED_DISTINCT_TARGETS = 4;
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
const
|
|
38
|
+
// TODO GLOAS: re-evaluate these timings
|
|
39
|
+
const LATE_ATTESTATION_SUBMISSION_BPS = 5000;
|
|
40
|
+
const LATE_BLOCK_SUBMISSION_BPS = 2500;
|
|
39
41
|
|
|
40
42
|
const RETAIN_REGISTERED_VALIDATORS_MS = 1 * 3600 * 1000; // 1 hour
|
|
41
43
|
|
|
@@ -450,8 +452,11 @@ export function createValidatorMonitor(
|
|
|
450
452
|
|
|
451
453
|
onPoolSubmitUnaggregatedAttestation(seenTimestampSec, indexedAttestation, subnet, sentPeers) {
|
|
452
454
|
const data = indexedAttestation.data;
|
|
453
|
-
|
|
454
|
-
|
|
455
|
+
const fork = config.getForkName(data.slot);
|
|
456
|
+
// Returns the duration between when the attestation `data` could be produced (ATTESTATION_DUE_BPS through the slot) and `seenTimestamp`.
|
|
457
|
+
const delaySec =
|
|
458
|
+
seenTimestampSec -
|
|
459
|
+
(computeTimeAtSlot(config, data.slot, genesisTime) + config.getAttestationDueMs(fork) / 1000);
|
|
455
460
|
for (const index of indexedAttestation.attestingIndices) {
|
|
456
461
|
const validator = validators.get(index);
|
|
457
462
|
if (validator) {
|
|
@@ -483,8 +488,11 @@ export function createValidatorMonitor(
|
|
|
483
488
|
const src = OpSource.gossip;
|
|
484
489
|
const data = indexedAttestation.data;
|
|
485
490
|
const epoch = computeEpochAtSlot(data.slot);
|
|
486
|
-
|
|
487
|
-
|
|
491
|
+
const fork = config.getForkName(data.slot);
|
|
492
|
+
// Returns the duration between when the attestation `data` could be produced (ATTESTATION_DUE_BPS through the slot) and `seenTimestamp`.
|
|
493
|
+
const delaySec =
|
|
494
|
+
seenTimestampSec -
|
|
495
|
+
(computeTimeAtSlot(config, data.slot, genesisTime) + config.getAttestationDueMs(fork) / 1000);
|
|
488
496
|
|
|
489
497
|
for (const index of indexedAttestation.attestingIndices) {
|
|
490
498
|
const validator = validators.get(index);
|
|
@@ -500,8 +508,10 @@ export function createValidatorMonitor(
|
|
|
500
508
|
|
|
501
509
|
onPoolSubmitAggregatedAttestation(seenTimestampSec, indexedAttestation, sentPeers) {
|
|
502
510
|
const data = indexedAttestation.data;
|
|
503
|
-
|
|
504
|
-
|
|
511
|
+
const fork = config.getForkName(data.slot);
|
|
512
|
+
// Returns the duration between when a `AggregateAndproof` with `data` could be produced (AGGREGATE_DUE_BPS through the slot) and `seenTimestamp`.
|
|
513
|
+
const delaySec =
|
|
514
|
+
seenTimestampSec - (computeTimeAtSlot(config, data.slot, genesisTime) + config.getAggregateDueMs(fork) / 1000);
|
|
505
515
|
|
|
506
516
|
for (const index of indexedAttestation.attestingIndices) {
|
|
507
517
|
const validator = validators.get(index);
|
|
@@ -527,8 +537,10 @@ export function createValidatorMonitor(
|
|
|
527
537
|
const src = OpSource.gossip;
|
|
528
538
|
const data = indexedAttestation.data;
|
|
529
539
|
const epoch = computeEpochAtSlot(data.slot);
|
|
530
|
-
|
|
531
|
-
|
|
540
|
+
const fork = config.getForkName(data.slot);
|
|
541
|
+
// Returns the duration between when a `AggregateAndproof` with `data` could be produced (AGGREGATE_DUE_BPS through the slot) and `seenTimestamp`.
|
|
542
|
+
const delaySec =
|
|
543
|
+
seenTimestampSec - (computeTimeAtSlot(config, data.slot, genesisTime) + config.getAggregateDueMs(fork) / 1000);
|
|
532
544
|
|
|
533
545
|
const aggregatorIndex = signedAggregateAndProof.message.aggregatorIndex;
|
|
534
546
|
const validatorAggregator = validators.get(aggregatorIndex);
|
|
@@ -822,7 +834,7 @@ export function createValidatorMonitor(
|
|
|
822
834
|
* - Was the attestation seen in a block?
|
|
823
835
|
*/
|
|
824
836
|
function renderAttestationSummary(
|
|
825
|
-
config:
|
|
837
|
+
config: ChainForkConfig,
|
|
826
838
|
rootCache: RootHexCache,
|
|
827
839
|
summary: AttestationSummary | undefined,
|
|
828
840
|
flags: ParticipationFlags
|
|
@@ -925,8 +937,7 @@ function renderAttestationSummary(
|
|
|
925
937
|
}
|
|
926
938
|
|
|
927
939
|
const submittedLate =
|
|
928
|
-
summary.poolSubmitDelayMinSec >
|
|
929
|
-
(INTERVALS_LATE_ATTESTATION_SUBMISSION * config.SECONDS_PER_SLOT) / INTERVALS_PER_SLOT;
|
|
940
|
+
summary.poolSubmitDelayMinSec > config.getSlotComponentDurationMs(LATE_ATTESTATION_SUBMISSION_BPS) / 1000;
|
|
930
941
|
|
|
931
942
|
const aggregateInclusion = summary.aggregateInclusionDelaysSec.length > 0;
|
|
932
943
|
|
|
@@ -1030,7 +1041,7 @@ function isMissedSlot(rootCache: RootHexCache, slot: Slot): boolean {
|
|
|
1030
1041
|
}
|
|
1031
1042
|
|
|
1032
1043
|
function renderBlockProposalSummary(
|
|
1033
|
-
config:
|
|
1044
|
+
config: ChainForkConfig,
|
|
1034
1045
|
rootCache: RootHexCache,
|
|
1035
1046
|
summary: EpochSummary | undefined,
|
|
1036
1047
|
proposalSlot: Slot
|
|
@@ -1053,7 +1064,7 @@ function renderBlockProposalSummary(
|
|
|
1053
1064
|
|
|
1054
1065
|
if (
|
|
1055
1066
|
proposal.poolSubmitDelaySec !== null &&
|
|
1056
|
-
proposal.poolSubmitDelaySec >
|
|
1067
|
+
proposal.poolSubmitDelaySec > config.getSlotComponentDurationMs(LATE_BLOCK_SUBMISSION_BPS) / 1000
|
|
1057
1068
|
) {
|
|
1058
1069
|
out += "_late";
|
|
1059
1070
|
}
|
|
@@ -862,9 +862,9 @@ export function createLodestarMetrics(
|
|
|
862
862
|
help: "Time elapsed between block slot time and the time block becomes head",
|
|
863
863
|
buckets: [0.5, 1, 2, 4, 6, 12],
|
|
864
864
|
}),
|
|
865
|
-
|
|
866
|
-
name: "
|
|
867
|
-
help: "Total times an imported block is set as head after the
|
|
865
|
+
setHeadAfterCutoff: register.gauge({
|
|
866
|
+
name: "lodestar_import_block_set_head_after_cutoff_total",
|
|
867
|
+
help: "Total times an imported block is set as head after ATTESTATION_DUE_BPS of the slot",
|
|
868
868
|
}),
|
|
869
869
|
bySource: register.gauge<{source: BlockInputSource}>({
|
|
870
870
|
name: "lodestar_import_block_by_source_total",
|
|
@@ -105,7 +105,7 @@ export class Eth2Gossipsub extends GossipSub {
|
|
|
105
105
|
mcacheLength: 6,
|
|
106
106
|
mcacheGossip: 3,
|
|
107
107
|
// this should be in ms
|
|
108
|
-
seenTTL: config.
|
|
108
|
+
seenTTL: config.SLOT_DURATION_MS * SLOTS_PER_EPOCH * 2,
|
|
109
109
|
scoreParams,
|
|
110
110
|
scoreThresholds: gossipScoreThresholds,
|
|
111
111
|
// For a single stream, await processing each RPC before processing the next
|
|
@@ -84,10 +84,10 @@ export function computeGossipPeerScoreParams({
|
|
|
84
84
|
config: BeaconConfig;
|
|
85
85
|
eth2Context: Eth2Context;
|
|
86
86
|
}): Partial<PeerScoreParams> {
|
|
87
|
-
const decayIntervalMs = config.
|
|
87
|
+
const decayIntervalMs = config.SLOT_DURATION_MS;
|
|
88
88
|
const decayToZero = 0.01;
|
|
89
|
-
const epochDurationMs = config.
|
|
90
|
-
const slotDurationMs = config.
|
|
89
|
+
const epochDurationMs = config.SLOT_DURATION_MS * SLOTS_PER_EPOCH;
|
|
90
|
+
const slotDurationMs = config.SLOT_DURATION_MS;
|
|
91
91
|
const scoreParameterDecayFn = (decayTimeMs: number): number => {
|
|
92
92
|
return scoreParameterDecayWithBase(decayTimeMs, decayIntervalMs, decayToZero);
|
|
93
93
|
};
|
|
@@ -265,7 +265,7 @@ function getTopicScoreParams(
|
|
|
265
265
|
|
|
266
266
|
if (meshMessageInfo) {
|
|
267
267
|
const {decaySlots, capFactor, activationWindow, currentSlot} = meshMessageInfo;
|
|
268
|
-
const decayTimeMs = config.
|
|
268
|
+
const decayTimeMs = config.SLOT_DURATION_MS * decaySlots;
|
|
269
269
|
params.meshMessageDeliveriesDecay = scoreParameterDecayFn(decayTimeMs);
|
|
270
270
|
params.meshMessageDeliveriesThreshold = threshold(params.meshMessageDeliveriesDecay, expectedMessageRate / 50);
|
|
271
271
|
params.meshMessageDeliveriesCap = Math.max(capFactor * params.meshMessageDeliveriesThreshold, 2);
|
package/src/network/network.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {BeaconConfig} from "@lodestar/config";
|
|
|
7
7
|
import {LoggerNode} from "@lodestar/logger/node";
|
|
8
8
|
import {ForkSeq} from "@lodestar/params";
|
|
9
9
|
import {ResponseIncoming} from "@lodestar/reqresp";
|
|
10
|
-
import {computeEpochAtSlot
|
|
10
|
+
import {computeEpochAtSlot} from "@lodestar/state-transition";
|
|
11
11
|
import {
|
|
12
12
|
AttesterSlashing,
|
|
13
13
|
LightClientBootstrap,
|
|
@@ -689,9 +689,9 @@ export class Network implements INetwork {
|
|
|
689
689
|
// TODO: Review is OK to remove if (this.hasAttachedSyncCommitteeMember())
|
|
690
690
|
|
|
691
691
|
try {
|
|
692
|
-
// messages SHOULD be broadcast after
|
|
692
|
+
// messages SHOULD be broadcast after SYNC_MESSAGE_DUE_BPS of slot has transpired
|
|
693
693
|
// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/p2p-interface.md#sync-committee
|
|
694
|
-
await this.
|
|
694
|
+
await this.waitForSyncMessageCutoff(finalityUpdate.signatureSlot);
|
|
695
695
|
await this.publishLightClientFinalityUpdate(finalityUpdate);
|
|
696
696
|
} catch (e) {
|
|
697
697
|
// Non-mandatory route on most of network as of Oct 2022. May not have found any peers on topic yet
|
|
@@ -706,9 +706,9 @@ export class Network implements INetwork {
|
|
|
706
706
|
// TODO: Review is OK to remove if (this.hasAttachedSyncCommitteeMember())
|
|
707
707
|
|
|
708
708
|
try {
|
|
709
|
-
// messages SHOULD be broadcast after
|
|
709
|
+
// messages SHOULD be broadcast after SYNC_MESSAGE_DUE_BPS of slot has transpired
|
|
710
710
|
// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/p2p-interface.md#sync-committee
|
|
711
|
-
await this.
|
|
711
|
+
await this.waitForSyncMessageCutoff(optimisticUpdate.signatureSlot);
|
|
712
712
|
await this.publishLightClientOptimisticUpdate(optimisticUpdate);
|
|
713
713
|
} catch (e) {
|
|
714
714
|
// Non-mandatory route on most of network as of Oct 2022. May not have found any peers on topic yet
|
|
@@ -719,10 +719,10 @@ export class Network implements INetwork {
|
|
|
719
719
|
}
|
|
720
720
|
};
|
|
721
721
|
|
|
722
|
-
private
|
|
723
|
-
const
|
|
724
|
-
const
|
|
725
|
-
await sleep(
|
|
722
|
+
private waitForSyncMessageCutoff = async (slot: number): Promise<void> => {
|
|
723
|
+
const fork = this.config.getForkName(slot);
|
|
724
|
+
const msToCutoffTime = this.config.getSyncMessageDueMs(fork) - this.chain.clock.msFromSlot(slot);
|
|
725
|
+
await sleep(msToCutoffTime, this.controller.signal);
|
|
726
726
|
};
|
|
727
727
|
|
|
728
728
|
private onHead = async (): Promise<void> => {
|
|
@@ -3,6 +3,7 @@ import {BitArray} from "@chainsafe/ssz";
|
|
|
3
3
|
import {BeaconConfig} from "@lodestar/config";
|
|
4
4
|
import {LoggerNode} from "@lodestar/logger/node";
|
|
5
5
|
import {ForkSeq, SLOTS_PER_EPOCH, SYNC_COMMITTEE_SUBNET_COUNT} from "@lodestar/params";
|
|
6
|
+
import {computeTimeAtSlot} from "@lodestar/state-transition";
|
|
6
7
|
import {Metadata, Status, altair, fulu, phase0} from "@lodestar/types";
|
|
7
8
|
import {prettyPrintIndices, toHex, withTimeout} from "@lodestar/utils";
|
|
8
9
|
import {GOODBYE_KNOWN_CODES, GoodByeReasonCode, Libp2pEvent} from "../../constants/index.js";
|
|
@@ -599,7 +600,7 @@ export class PeerManager {
|
|
|
599
600
|
subnet: query.subnet,
|
|
600
601
|
type,
|
|
601
602
|
maxPeersToDiscover: query.maxPeersToDiscover,
|
|
602
|
-
toUnixMs:
|
|
603
|
+
toUnixMs: computeTimeAtSlot(this.config, query.toSlot, this.clock.genesisTime) * 1000,
|
|
603
604
|
});
|
|
604
605
|
}
|
|
605
606
|
|
|
@@ -379,7 +379,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
379
379
|
|
|
380
380
|
// Handler - MUST NOT `await`, to allow validation result to be propagated
|
|
381
381
|
|
|
382
|
-
const delaySec = seenTimestampSec - (
|
|
382
|
+
const delaySec = seenTimestampSec - computeTimeAtSlot(config, slot, chain.genesisTime);
|
|
383
383
|
metrics?.gossipBlock.elapsedTimeTillReceived.observe({source: OpSource.gossip}, delaySec);
|
|
384
384
|
chain.validatorMonitor?.registerBeaconBlock(OpSource.gossip, delaySec, signedBlock.message);
|
|
385
385
|
if (!blockInput.hasBlockAndAllData()) {
|
|
@@ -230,14 +230,13 @@ export class NetworkProcessor {
|
|
|
230
230
|
return queue.getAll();
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
-
searchUnknownSlotRoot(
|
|
234
|
-
const {slot, root} = slotRoot;
|
|
233
|
+
searchUnknownSlotRoot({slot, root}: SlotRootHex, source: BlockInputSource, peer?: PeerIdStr): void {
|
|
235
234
|
if (this.chain.seenBlock(root) || this.unknownRootsBySlot.getOrDefault(slot).has(root)) {
|
|
236
235
|
return;
|
|
237
236
|
}
|
|
238
237
|
// Search for the unknown block
|
|
239
238
|
this.unknownRootsBySlot.getOrDefault(slot).add(root);
|
|
240
|
-
this.chain.emitter.emit(ChainEvent.unknownBlockRoot, {
|
|
239
|
+
this.chain.emitter.emit(ChainEvent.unknownBlockRoot, {rootHex: root, peer, source});
|
|
241
240
|
}
|
|
242
241
|
|
|
243
242
|
private onPendingGossipsubMessage(message: PendingGossipsubMessage): void {
|
|
@@ -163,12 +163,9 @@ export class AttnetsService implements IAttnetsService {
|
|
|
163
163
|
*/
|
|
164
164
|
private onSlot = (clockSlot: Slot): void => {
|
|
165
165
|
try {
|
|
166
|
-
setTimeout(
|
|
167
|
-
()
|
|
168
|
-
|
|
169
|
-
},
|
|
170
|
-
this.config.SECONDS_PER_SLOT * 0.5 * 1000
|
|
171
|
-
);
|
|
166
|
+
setTimeout(() => {
|
|
167
|
+
this.onHalfSlot(clockSlot);
|
|
168
|
+
}, this.config.SLOT_DURATION_MS * 0.5);
|
|
172
169
|
|
|
173
170
|
for (const [dutiedSlot, dutiedInfo] of this.aggregatorSlotSubnet.entries()) {
|
|
174
171
|
if (dutiedSlot === clockSlot + this.opts.slotsToSubscribeBeforeAggregatorDuty) {
|
package/src/node/notifier.ts
CHANGED
|
@@ -157,7 +157,7 @@ export async function runNodeNotifier(modules: NodeNotifierModules): Promise<voi
|
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
function timeToNextHalfSlot(config: BeaconConfig, chain: IBeaconChain, isFirstTime: boolean): number {
|
|
160
|
-
const msPerSlot = config.
|
|
160
|
+
const msPerSlot = config.SLOT_DURATION_MS;
|
|
161
161
|
const msPerHalfSlot = msPerSlot / 2;
|
|
162
162
|
const msFromGenesis = Date.now() - chain.genesisTime * 1000;
|
|
163
163
|
const msToNextSlot =
|
package/src/sync/types.ts
CHANGED
|
@@ -37,8 +37,6 @@ export type PendingBlockInput = {
|
|
|
37
37
|
export type PendingRootHex = {
|
|
38
38
|
status: PendingBlockInputStatus.pending | PendingBlockInputStatus.fetching;
|
|
39
39
|
rootHex: RootHex;
|
|
40
|
-
// optional because we may not know the slot of parent_unknown event
|
|
41
|
-
slot?: Slot;
|
|
42
40
|
timeAddedSec: number;
|
|
43
41
|
timeSyncedSec?: number;
|
|
44
42
|
peerIdStrings: Set<string>;
|
package/src/sync/unknownBlock.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {ForkSeq
|
|
2
|
+
import {ForkSeq} from "@lodestar/params";
|
|
3
3
|
import {RequestError, RequestErrorCode} from "@lodestar/reqresp";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import {computeTimeAtSlot} from "@lodestar/state-transition";
|
|
5
|
+
import {RootHex} from "@lodestar/types";
|
|
6
|
+
import {Logger, prettyPrintIndices, pruneSetToMax, sleep} from "@lodestar/utils";
|
|
6
7
|
import {isBlockInputBlobs, isBlockInputColumns} from "../chain/blocks/blockInput/blockInput.js";
|
|
7
8
|
import {BlockInputSource, IBlockInput} from "../chain/blocks/blockInput/types.js";
|
|
8
9
|
import {BlockError, BlockErrorCode} from "../chain/errors/index.js";
|
|
@@ -78,7 +79,6 @@ export class BlockInputSync {
|
|
|
78
79
|
*/
|
|
79
80
|
private readonly pendingBlocks = new Map<RootHex, BlockInputSyncCacheItem>();
|
|
80
81
|
private readonly knownBadBlocks = new Set<RootHex>();
|
|
81
|
-
private readonly proposerBoostSecWindow: number;
|
|
82
82
|
private readonly maxPendingBlocks;
|
|
83
83
|
private subscribedToNetworkEvents = false;
|
|
84
84
|
private peerBalancer: UnknownBlockPeerBalancer;
|
|
@@ -92,7 +92,6 @@ export class BlockInputSync {
|
|
|
92
92
|
private readonly opts?: SyncOptions
|
|
93
93
|
) {
|
|
94
94
|
this.maxPendingBlocks = opts?.maxPendingBlocks ?? MAX_PENDING_BLOCKS;
|
|
95
|
-
this.proposerBoostSecWindow = this.config.SECONDS_PER_SLOT / INTERVALS_PER_SLOT;
|
|
96
95
|
this.peerBalancer = new UnknownBlockPeerBalancer();
|
|
97
96
|
|
|
98
97
|
if (metrics) {
|
|
@@ -146,8 +145,7 @@ export class BlockInputSync {
|
|
|
146
145
|
*/
|
|
147
146
|
private onUnknownBlockRoot = (data: ChainEventData[ChainEvent.unknownBlockRoot]): void => {
|
|
148
147
|
try {
|
|
149
|
-
|
|
150
|
-
this.addByRootHex(root, slot, data.peer);
|
|
148
|
+
this.addByRootHex(data.rootHex, data.peer);
|
|
151
149
|
this.triggerUnknownBlockSearch();
|
|
152
150
|
this.metrics?.blockInputSync.requests.inc({type: PendingBlockType.UNKNOWN_BLOCK_ROOT});
|
|
153
151
|
this.metrics?.blockInputSync.source.inc({source: data.source});
|
|
@@ -175,8 +173,7 @@ export class BlockInputSync {
|
|
|
175
173
|
*/
|
|
176
174
|
private onUnknownParent = (data: ChainEventData[ChainEvent.unknownParent]): void => {
|
|
177
175
|
try {
|
|
178
|
-
|
|
179
|
-
this.addByRootHex(data.blockInput.parentRootHex, undefined, data.peer);
|
|
176
|
+
this.addByRootHex(data.blockInput.parentRootHex, data.peer);
|
|
180
177
|
this.addByBlockInput(data.blockInput, data.peer);
|
|
181
178
|
this.triggerUnknownBlockSearch();
|
|
182
179
|
this.metrics?.blockInputSync.requests.inc({type: PendingBlockType.UNKNOWN_PARENT});
|
|
@@ -186,12 +183,11 @@ export class BlockInputSync {
|
|
|
186
183
|
}
|
|
187
184
|
};
|
|
188
185
|
|
|
189
|
-
private addByRootHex = (rootHex: RootHex,
|
|
186
|
+
private addByRootHex = (rootHex: RootHex, peerIdStr?: PeerIdStr): void => {
|
|
190
187
|
let pendingBlock = this.pendingBlocks.get(rootHex);
|
|
191
188
|
if (!pendingBlock) {
|
|
192
189
|
pendingBlock = {
|
|
193
190
|
status: PendingBlockInputStatus.pending,
|
|
194
|
-
slot,
|
|
195
191
|
rootHex: rootHex,
|
|
196
192
|
peerIdStrings: new Set(),
|
|
197
193
|
timeAddedSec: Date.now() / 1000,
|
|
@@ -199,7 +195,7 @@ export class BlockInputSync {
|
|
|
199
195
|
this.pendingBlocks.set(rootHex, pendingBlock);
|
|
200
196
|
|
|
201
197
|
this.logger.verbose("Added new rootHex to BlockInputSync.pendingBlocks", {
|
|
202
|
-
|
|
198
|
+
root: pendingBlock.rootHex,
|
|
203
199
|
peerIdStr: peerIdStr ?? "unknown peer",
|
|
204
200
|
});
|
|
205
201
|
}
|
|
@@ -318,7 +314,7 @@ export class BlockInputSync {
|
|
|
318
314
|
const rootHex = getBlockInputSyncCacheItemRootHex(block);
|
|
319
315
|
const logCtx = {
|
|
320
316
|
slot: getBlockInputSyncCacheItemSlot(block),
|
|
321
|
-
|
|
317
|
+
root: rootHex,
|
|
322
318
|
pendingBlocks: this.pendingBlocks.size,
|
|
323
319
|
};
|
|
324
320
|
|
|
@@ -334,7 +330,7 @@ export class BlockInputSync {
|
|
|
334
330
|
this.pendingBlocks.set(pending.blockInput.blockRootHex, pending);
|
|
335
331
|
const blockSlot = pending.blockInput.slot;
|
|
336
332
|
const finalizedSlot = this.chain.forkChoice.getFinalizedBlock().slot;
|
|
337
|
-
const delaySec = Date.now() / 1000 - (this.
|
|
333
|
+
const delaySec = Date.now() / 1000 - computeTimeAtSlot(this.config, blockSlot, this.chain.genesisTime);
|
|
338
334
|
this.metrics?.blockInputSync.elapsedTimeTillReceived.observe(delaySec);
|
|
339
335
|
|
|
340
336
|
const parentInForkChoice = this.chain.forkChoice.hasBlockHex(pending.blockInput.parentRootHex);
|
|
@@ -362,7 +358,7 @@ export class BlockInputSync {
|
|
|
362
358
|
});
|
|
363
359
|
this.removeAndDownScoreAllDescendants(block);
|
|
364
360
|
} else {
|
|
365
|
-
this.onUnknownBlockRoot({
|
|
361
|
+
this.onUnknownBlockRoot({rootHex: pending.blockInput.parentRootHex, source: BlockInputSource.byRoot});
|
|
366
362
|
}
|
|
367
363
|
} else {
|
|
368
364
|
this.metrics?.blockInputSync.downloadedBlocksError.inc();
|
|
@@ -399,18 +395,20 @@ export class BlockInputSync {
|
|
|
399
395
|
// this prevents unbundling attack
|
|
400
396
|
// see https://lighthouse-blog.sigmaprime.io/mev-unbundling-rpc.html
|
|
401
397
|
const {slot: blockSlot, proposerIndex} = pendingBlock.blockInput.getBlock().message;
|
|
398
|
+
const fork = this.config.getForkName(blockSlot);
|
|
399
|
+
const proposerBoostWindowMs = this.config.getAttestationDueMs(fork);
|
|
402
400
|
if (
|
|
403
|
-
this.chain.clock.
|
|
401
|
+
this.chain.clock.msFromSlot(blockSlot) < proposerBoostWindowMs &&
|
|
404
402
|
this.chain.seenBlockProposers.isKnown(blockSlot, proposerIndex)
|
|
405
403
|
) {
|
|
406
404
|
// proposer is known by a gossip block already, wait a bit to make sure this block is not
|
|
407
405
|
// eligible for proposer boost to prevent unbundling attack
|
|
408
406
|
this.logger.verbose("Avoid proposer boost for this block of known proposer", {
|
|
409
407
|
slot: blockSlot,
|
|
410
|
-
|
|
408
|
+
root: pendingBlock.blockInput.blockRootHex,
|
|
411
409
|
proposerIndex,
|
|
412
410
|
});
|
|
413
|
-
await sleep(
|
|
411
|
+
await sleep(proposerBoostWindowMs);
|
|
414
412
|
}
|
|
415
413
|
// At gossip time, it's critical to keep a good number of mesh peers.
|
|
416
414
|
// To do that, the Gossip Job Wait Time should be consistently <3s to avoid the behavior penalties in gossip
|
|
@@ -500,7 +498,7 @@ export class BlockInputSync {
|
|
|
500
498
|
: null;
|
|
501
499
|
|
|
502
500
|
const fetchStartSec = Date.now() / 1000;
|
|
503
|
-
let slot = isPendingBlockInput(cacheItem) ? cacheItem.blockInput.slot :
|
|
501
|
+
let slot = isPendingBlockInput(cacheItem) ? cacheItem.blockInput.slot : undefined;
|
|
504
502
|
if (slot !== undefined) {
|
|
505
503
|
this.metrics?.blockInputSync.fetchBegin.observe(this.chain.clock.secFromSlot(slot, fetchStartSec));
|
|
506
504
|
}
|
|
@@ -515,7 +513,7 @@ export class BlockInputSync {
|
|
|
515
513
|
const peerMeta = this.peerBalancer.bestPeerForPendingColumns(pendingColumns, excludedPeers);
|
|
516
514
|
if (peerMeta === null) {
|
|
517
515
|
// no more peer with needed columns to try, throw error
|
|
518
|
-
let message = `Error fetching UnknownBlockRoot slot=${slot}
|
|
516
|
+
let message = `Error fetching UnknownBlockRoot slot=${slot} root=${rootHex} after ${i}: cannot find peer`;
|
|
519
517
|
if (pendingColumns) {
|
|
520
518
|
message += ` with needed columns=${prettyPrintIndices(Array.from(pendingColumns))}`;
|
|
521
519
|
}
|
|
@@ -605,7 +603,7 @@ export class BlockInputSync {
|
|
|
605
603
|
}
|
|
606
604
|
} // end while loop over peers
|
|
607
605
|
|
|
608
|
-
const message = `Error fetching BlockInput with slot=${slot}
|
|
606
|
+
const message = `Error fetching BlockInput with slot=${slot} root=${rootHex} after ${i - 1} attempts.`;
|
|
609
607
|
|
|
610
608
|
if (!isPendingBlockInput(cacheItem)) {
|
|
611
609
|
throw Error(`${message} No block and no data was found.`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {ForkPostDeneb, ForkPostFulu} from "@lodestar/params";
|
|
2
|
+
import {ForkPostDeneb, ForkPostFulu, ForkPreFulu, ForkPreGloas} from "@lodestar/params";
|
|
3
3
|
import {SignedBeaconBlock, Slot, deneb, fulu, phase0} from "@lodestar/types";
|
|
4
4
|
import {LodestarError, Logger, fromHex, prettyBytes, prettyPrintIndices, toRootHex} from "@lodestar/utils";
|
|
5
5
|
import {
|
|
@@ -458,14 +458,16 @@ export function validateBlockByRangeResponse(
|
|
|
458
458
|
}
|
|
459
459
|
|
|
460
460
|
/**
|
|
461
|
-
* Should not be called directly. Only exported for unit testing purposes
|
|
461
|
+
* Should not be called directly. Only exported for unit testing purposes.
|
|
462
|
+
* This is used only in Deneb and Electra
|
|
462
463
|
*/
|
|
463
464
|
export async function validateBlobsByRangeResponse(
|
|
464
465
|
dataRequestBlocks: ValidatedBlock[],
|
|
465
466
|
blobSidecars: deneb.BlobSidecars
|
|
466
467
|
): Promise<ValidatedBlobSidecars[]> {
|
|
467
468
|
const expectedBlobCount = dataRequestBlocks.reduce(
|
|
468
|
-
(acc, {block}) =>
|
|
469
|
+
(acc, {block}) =>
|
|
470
|
+
(block as SignedBeaconBlock<ForkPostDeneb & ForkPreFulu>).message.body.blobKzgCommitments.length + acc,
|
|
469
471
|
0
|
|
470
472
|
);
|
|
471
473
|
if (blobSidecars.length > expectedBlobCount) {
|
|
@@ -492,7 +494,8 @@ export async function validateBlobsByRangeResponse(
|
|
|
492
494
|
const validateSidecarsPromises: Promise<ValidatedBlobSidecars>[] = [];
|
|
493
495
|
for (let blockIndex = 0, blobSidecarIndex = 0; blockIndex < dataRequestBlocks.length; blockIndex++) {
|
|
494
496
|
const {block, blockRoot} = dataRequestBlocks[blockIndex];
|
|
495
|
-
const blockKzgCommitments = (block as SignedBeaconBlock<ForkPostDeneb>).message.body
|
|
497
|
+
const blockKzgCommitments = (block as SignedBeaconBlock<ForkPostDeneb & ForkPreFulu>).message.body
|
|
498
|
+
.blobKzgCommitments;
|
|
496
499
|
if (blockKzgCommitments.length === 0) {
|
|
497
500
|
continue;
|
|
498
501
|
}
|
|
@@ -532,8 +535,9 @@ export async function validateColumnsByRangeResponse(
|
|
|
532
535
|
columnSidecars: fulu.DataColumnSidecars
|
|
533
536
|
): Promise<WarnResult<ValidatedColumnSidecars[], DownloadByRangeError>> {
|
|
534
537
|
// Expected column count considering currently-validated batch blocks
|
|
538
|
+
// TODO GLOAS: Post-gloas's blobKzgCommitments is not in beacon block body. Need to source it from somewhere else.
|
|
535
539
|
const expectedColumnCount = dataRequestBlocks.reduce((acc, {block}) => {
|
|
536
|
-
return (block as SignedBeaconBlock<ForkPostDeneb>).message.body.blobKzgCommitments.length > 0
|
|
540
|
+
return (block as SignedBeaconBlock<ForkPostDeneb & ForkPreGloas>).message.body.blobKzgCommitments.length > 0
|
|
537
541
|
? request.columns.length + acc
|
|
538
542
|
: acc;
|
|
539
543
|
}, 0);
|
|
@@ -566,7 +570,9 @@ export async function validateColumnsByRangeResponse(
|
|
|
566
570
|
const {block, blockRoot} = dataRequestBlocks[blockIndex];
|
|
567
571
|
const slot = block.message.slot;
|
|
568
572
|
const blockRootHex = toRootHex(blockRoot);
|
|
569
|
-
|
|
573
|
+
// TODO GLOAS: Post-gloas's blobKzgCommitments is not in beacon block body. Need to source it from somewhere else.
|
|
574
|
+
const blockKzgCommitments = (block as SignedBeaconBlock<ForkPostFulu & ForkPreGloas>).message.body
|
|
575
|
+
.blobKzgCommitments;
|
|
570
576
|
const expectedColumns = blockKzgCommitments.length ? request.columns.length : 0;
|
|
571
577
|
|
|
572
578
|
if (expectedColumns === 0) {
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
2
|
import {ChainForkConfig} from "@lodestar/config";
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
ForkPostDeneb,
|
|
5
|
+
ForkPostFulu,
|
|
6
|
+
ForkPreFulu,
|
|
7
|
+
ForkPreGloas,
|
|
8
|
+
isForkPostDeneb,
|
|
9
|
+
isForkPostFulu,
|
|
10
|
+
} from "@lodestar/params";
|
|
11
|
+
import {BeaconBlockBody, BlobIndex, ColumnIndex, SignedBeaconBlock, Slot, deneb, fulu} from "@lodestar/types";
|
|
5
12
|
import {LodestarError, fromHex, prettyBytes, prettyPrintIndices, toHex, toRootHex} from "@lodestar/utils";
|
|
6
13
|
import {isBlockInputBlobs, isBlockInputColumns} from "../../chain/blocks/blockInput/blockInput.js";
|
|
7
14
|
import {BlockInputSource, IBlockInput} from "../../chain/blocks/blockInput/types.js";
|
|
@@ -269,7 +276,7 @@ export async function fetchByRoot({
|
|
|
269
276
|
missing: network.custodyConfig.sampledColumns,
|
|
270
277
|
});
|
|
271
278
|
} else if (isForkPostDeneb(forkName)) {
|
|
272
|
-
const commitments = (block as SignedBeaconBlock<ForkPostDeneb>).message.body.blobKzgCommitments;
|
|
279
|
+
const commitments = (block as SignedBeaconBlock<ForkPostDeneb & ForkPreFulu>).message.body.blobKzgCommitments;
|
|
273
280
|
const blobCount = commitments.length;
|
|
274
281
|
blobSidecars = await fetchAndValidateBlobs({
|
|
275
282
|
config,
|
|
@@ -369,7 +376,8 @@ export async function fetchAndValidateColumns({
|
|
|
369
376
|
}: FetchByRootAndValidateColumnsProps): Promise<WarnResult<fulu.DataColumnSidecars, DownloadByRootError>> {
|
|
370
377
|
const {peerId: peerIdStr} = peerMeta;
|
|
371
378
|
const slot = block.message.slot;
|
|
372
|
-
|
|
379
|
+
// TODO GLOAS: Get blob count from somewhere else since blobKzgCommitments is absent from block body
|
|
380
|
+
const blobCount = (block.message.body as BeaconBlockBody<ForkPostFulu & ForkPreGloas>).blobKzgCommitments.length;
|
|
373
381
|
if (blobCount === 0) {
|
|
374
382
|
return {result: [], warnings: null};
|
|
375
383
|
}
|