@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.
Files changed (157) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +8 -2
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/lodestar/index.js +1 -1
  5. package/lib/api/impl/lodestar/index.js.map +1 -1
  6. package/lib/api/impl/validator/index.d.ts.map +1 -1
  7. package/lib/api/impl/validator/index.js +22 -26
  8. package/lib/api/impl/validator/index.js.map +1 -1
  9. package/lib/chain/archiveStore/historicalState/worker.js +1 -1
  10. package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
  11. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  12. package/lib/chain/blocks/blockInput/blockInput.js +3 -2
  13. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  14. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  15. package/lib/chain/blocks/importBlock.js +7 -6
  16. package/lib/chain/blocks/importBlock.js.map +1 -1
  17. package/lib/chain/blocks/verifyBlocksDataAvailability.d.ts.map +1 -1
  18. package/lib/chain/blocks/verifyBlocksDataAvailability.js +8 -1
  19. package/lib/chain/blocks/verifyBlocksDataAvailability.js.map +1 -1
  20. package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
  21. package/lib/chain/blocks/writeBlockInputToDb.js +1 -7
  22. package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
  23. package/lib/chain/chain.d.ts.map +1 -1
  24. package/lib/chain/chain.js +3 -4
  25. package/lib/chain/chain.js.map +1 -1
  26. package/lib/chain/emitter.d.ts +2 -2
  27. package/lib/chain/emitter.d.ts.map +1 -1
  28. package/lib/chain/lightClient/index.d.ts +2 -2
  29. package/lib/chain/lightClient/index.d.ts.map +1 -1
  30. package/lib/chain/lightClient/index.js +2 -0
  31. package/lib/chain/lightClient/index.js.map +1 -1
  32. package/lib/chain/opPools/attestationPool.d.ts +2 -3
  33. package/lib/chain/opPools/attestationPool.d.ts.map +1 -1
  34. package/lib/chain/opPools/attestationPool.js +3 -5
  35. package/lib/chain/opPools/attestationPool.js.map +1 -1
  36. package/lib/chain/opPools/syncCommitteeMessagePool.d.ts +3 -2
  37. package/lib/chain/opPools/syncCommitteeMessagePool.d.ts.map +1 -1
  38. package/lib/chain/opPools/syncCommitteeMessagePool.js +6 -5
  39. package/lib/chain/opPools/syncCommitteeMessagePool.js.map +1 -1
  40. package/lib/chain/opPools/types.d.ts +1 -1
  41. package/lib/chain/opPools/types.d.ts.map +1 -1
  42. package/lib/chain/opPools/types.js +1 -1
  43. package/lib/chain/opPools/types.js.map +1 -1
  44. package/lib/chain/prepareNextSlot.d.ts +3 -3
  45. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  46. package/lib/chain/prepareNextSlot.js +8 -8
  47. package/lib/chain/prepareNextSlot.js.map +1 -1
  48. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  49. package/lib/chain/produceBlock/produceBlockBody.js +10 -2
  50. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  51. package/lib/chain/regen/interface.d.ts +1 -0
  52. package/lib/chain/regen/interface.d.ts.map +1 -1
  53. package/lib/chain/regen/interface.js +1 -0
  54. package/lib/chain/regen/interface.js.map +1 -1
  55. package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
  56. package/lib/chain/seenCache/seenGossipBlockInput.js +8 -1
  57. package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
  58. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  59. package/lib/chain/stateCache/persistentCheckpointsCache.js +9 -8
  60. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  61. package/lib/chain/validation/dataColumnSidecar.js +1 -1
  62. package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
  63. package/lib/chain/validation/lightClientFinalityUpdate.d.ts.map +1 -1
  64. package/lib/chain/validation/lightClientFinalityUpdate.js +4 -3
  65. package/lib/chain/validation/lightClientFinalityUpdate.js.map +1 -1
  66. package/lib/chain/validation/lightClientOptimisticUpdate.d.ts +6 -4
  67. package/lib/chain/validation/lightClientOptimisticUpdate.d.ts.map +1 -1
  68. package/lib/chain/validation/lightClientOptimisticUpdate.js +11 -11
  69. package/lib/chain/validation/lightClientOptimisticUpdate.js.map +1 -1
  70. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  71. package/lib/chain/validatorMonitor.js +21 -15
  72. package/lib/chain/validatorMonitor.js.map +1 -1
  73. package/lib/metrics/metrics/lodestar.d.ts +1 -1
  74. package/lib/metrics/metrics/lodestar.js +3 -3
  75. package/lib/metrics/metrics/lodestar.js.map +1 -1
  76. package/lib/network/gossip/gossipsub.js +1 -1
  77. package/lib/network/gossip/gossipsub.js.map +1 -1
  78. package/lib/network/gossip/scoringParameters.js +4 -4
  79. package/lib/network/gossip/scoringParameters.js.map +1 -1
  80. package/lib/network/network.d.ts +1 -1
  81. package/lib/network/network.d.ts.map +1 -1
  82. package/lib/network/network.js +9 -9
  83. package/lib/network/network.js.map +1 -1
  84. package/lib/network/peers/peerManager.d.ts.map +1 -1
  85. package/lib/network/peers/peerManager.js +2 -1
  86. package/lib/network/peers/peerManager.js.map +1 -1
  87. package/lib/network/processor/gossipHandlers.js +1 -1
  88. package/lib/network/processor/gossipHandlers.js.map +1 -1
  89. package/lib/network/processor/index.d.ts +1 -1
  90. package/lib/network/processor/index.d.ts.map +1 -1
  91. package/lib/network/processor/index.js +2 -3
  92. package/lib/network/processor/index.js.map +1 -1
  93. package/lib/network/subnets/attnetsService.d.ts.map +1 -1
  94. package/lib/network/subnets/attnetsService.js +1 -1
  95. package/lib/network/subnets/attnetsService.js.map +1 -1
  96. package/lib/node/notifier.js +1 -1
  97. package/lib/node/notifier.js.map +1 -1
  98. package/lib/sync/types.d.ts +0 -1
  99. package/lib/sync/types.d.ts.map +1 -1
  100. package/lib/sync/types.js.map +1 -1
  101. package/lib/sync/unknownBlock.d.ts +0 -1
  102. package/lib/sync/unknownBlock.d.ts.map +1 -1
  103. package/lib/sync/unknownBlock.js +18 -20
  104. package/lib/sync/unknownBlock.js.map +1 -1
  105. package/lib/sync/utils/downloadByRange.d.ts +2 -1
  106. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  107. package/lib/sync/utils/downloadByRange.js +8 -3
  108. package/lib/sync/utils/downloadByRange.js.map +1 -1
  109. package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
  110. package/lib/sync/utils/downloadByRoot.js +2 -1
  111. package/lib/sync/utils/downloadByRoot.js.map +1 -1
  112. package/lib/util/clock.d.ts +8 -3
  113. package/lib/util/clock.d.ts.map +1 -1
  114. package/lib/util/clock.js +8 -5
  115. package/lib/util/clock.js.map +1 -1
  116. package/lib/util/dataColumns.d.ts.map +1 -1
  117. package/lib/util/dataColumns.js +4 -2
  118. package/lib/util/dataColumns.js.map +1 -1
  119. package/package.json +14 -14
  120. package/src/api/impl/beacon/blocks/index.ts +11 -2
  121. package/src/api/impl/lodestar/index.ts +1 -1
  122. package/src/api/impl/validator/index.ts +25 -28
  123. package/src/chain/archiveStore/historicalState/worker.ts +1 -1
  124. package/src/chain/blocks/blockInput/blockInput.ts +7 -4
  125. package/src/chain/blocks/importBlock.ts +8 -12
  126. package/src/chain/blocks/verifyBlocksDataAvailability.ts +10 -2
  127. package/src/chain/blocks/writeBlockInputToDb.ts +1 -9
  128. package/src/chain/chain.ts +3 -14
  129. package/src/chain/emitter.ts +2 -2
  130. package/src/chain/lightClient/index.ts +11 -3
  131. package/src/chain/opPools/attestationPool.ts +2 -3
  132. package/src/chain/opPools/syncCommitteeMessagePool.ts +5 -3
  133. package/src/chain/opPools/types.ts +1 -1
  134. package/src/chain/prepareNextSlot.ts +8 -8
  135. package/src/chain/produceBlock/produceBlockBody.ts +13 -3
  136. package/src/chain/regen/interface.ts +1 -0
  137. package/src/chain/seenCache/seenGossipBlockInput.ts +10 -2
  138. package/src/chain/stateCache/persistentCheckpointsCache.ts +10 -8
  139. package/src/chain/validation/dataColumnSidecar.ts +1 -1
  140. package/src/chain/validation/lightClientFinalityUpdate.ts +4 -3
  141. package/src/chain/validation/lightClientOptimisticUpdate.ts +12 -11
  142. package/src/chain/validatorMonitor.ts +28 -17
  143. package/src/metrics/metrics/lodestar.ts +3 -3
  144. package/src/network/gossip/gossipsub.ts +1 -1
  145. package/src/network/gossip/scoringParameters.ts +4 -4
  146. package/src/network/network.ts +9 -9
  147. package/src/network/peers/peerManager.ts +2 -1
  148. package/src/network/processor/gossipHandlers.ts +1 -1
  149. package/src/network/processor/index.ts +2 -3
  150. package/src/network/subnets/attnetsService.ts +3 -6
  151. package/src/node/notifier.ts +1 -1
  152. package/src/sync/types.ts +0 -2
  153. package/src/sync/unknownBlock.ts +19 -21
  154. package/src/sync/utils/downloadByRange.ts +12 -6
  155. package/src/sync/utils/downloadByRoot.ts +12 -4
  156. package/src/util/clock.ts +14 -6
  157. 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.validateGossipBlock)
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 one-third of finality_update.signature_slot has transpired
29
- // (SECONDS_PER_SLOT / INTERVALS_PER_SLOT seconds after the start of the slot, with a MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance)
30
- if (updateReceivedTooEarly(config, chain.genesisTime, gossipedFinalityUpdate)) {
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 one-third of optimistic_update.signature_slot has transpired
30
- // (SECONDS_PER_SLOT / INTERVALS_PER_SLOT seconds after the start of the slot, with a MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance)
31
- if (updateReceivedTooEarly(config, chain.genesisTime, gossipedOptimisticUpdate)) {
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 +1/3 time
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 one-third of *update.signature_slot has transpired
57
- * (SECONDS_PER_SLOT / INTERVALS_PER_SLOT seconds after the start of the slot, with a MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance)
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
- genesisTime: number,
63
+ clock: IClock,
62
64
  update: Pick<LightClientOptimisticUpdate, "signatureSlot">
63
65
  ): boolean {
64
- const signatureSlot13TimestampMs = computeTimeAtSlot(config, update.signatureSlot + 1 / 3, genesisTime) * 1000;
65
- const earliestAllowedTimestampMs = signatureSlot13TimestampMs - MAXIMUM_GOSSIP_CLOCK_DISPARITY;
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 {ChainConfig, ChainForkConfig} from "@lodestar/config";
2
- import {ForkSeq, INTERVALS_PER_SLOT, MIN_ATTESTATION_INCLUSION_DELAY, SLOTS_PER_EPOCH} from "@lodestar/params";
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
- const INTERVALS_LATE_ATTESTATION_SUBMISSION = 1.5;
38
- const INTERVALS_LATE_BLOCK_SUBMISSION = 0.75;
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
- // Returns the duration between when the attestation `data` could be produced (1/3rd through the slot) and `seenTimestamp`.
454
- const delaySec = seenTimestampSec - (genesisTime + (data.slot + 1 / 3) * config.SECONDS_PER_SLOT);
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
- // Returns the duration between when the attestation `data` could be produced (1/3rd through the slot) and `seenTimestamp`.
487
- const delaySec = seenTimestampSec - (genesisTime + (data.slot + 1 / 3) * config.SECONDS_PER_SLOT);
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
- // Returns the duration between when a `AggregateAndproof` with `data` could be produced (2/3rd through the slot) and `seenTimestamp`.
504
- const delaySec = seenTimestampSec - (genesisTime + (data.slot + 2 / 3) * config.SECONDS_PER_SLOT);
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
- // Returns the duration between when a `AggregateAndProof` with `data` could be produced (2/3rd through the slot) and `seenTimestamp`.
531
- const delaySec = seenTimestampSec - (genesisTime + (data.slot + 2 / 3) * config.SECONDS_PER_SLOT);
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: ChainConfig,
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: ChainConfig,
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 > (INTERVALS_LATE_BLOCK_SUBMISSION * config.SECONDS_PER_SLOT) / INTERVALS_PER_SLOT
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
- setHeadAfterFirstInterval: register.gauge({
866
- name: "lodestar_import_block_set_head_after_first_interval_total",
867
- help: "Total times an imported block is set as head after the first slot interval",
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.SECONDS_PER_SLOT * SLOTS_PER_EPOCH * 2 * 1000,
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.SECONDS_PER_SLOT * 1000;
87
+ const decayIntervalMs = config.SLOT_DURATION_MS;
88
88
  const decayToZero = 0.01;
89
- const epochDurationMs = config.SECONDS_PER_SLOT * SLOTS_PER_EPOCH * 1000;
90
- const slotDurationMs = config.SECONDS_PER_SLOT * 1000;
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.SECONDS_PER_SLOT * decaySlots * 1000;
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);
@@ -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, computeTimeAtSlot} from "@lodestar/state-transition";
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 one-third of slot has transpired
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.waitOneThirdOfSlot(finalityUpdate.signatureSlot);
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 one-third of slot has transpired
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.waitOneThirdOfSlot(optimisticUpdate.signatureSlot);
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 waitOneThirdOfSlot = async (slot: number): Promise<void> => {
723
- const secAtSlot = computeTimeAtSlot(this.config, slot + 1 / 3, this.chain.genesisTime);
724
- const msToSlot = secAtSlot * 1000 - Date.now();
725
- await sleep(msToSlot, this.controller.signal);
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: 1000 * (this.clock.genesisTime + query.toSlot * this.config.SECONDS_PER_SLOT),
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 - (chain.genesisTime + slot * config.SECONDS_PER_SLOT);
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(slotRoot: SlotRootHex, source: BlockInputSource, peer?: PeerIdStr): void {
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, {rootSlot: slotRoot, peer, source});
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
- this.onHalfSlot(clockSlot);
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) {
@@ -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.SECONDS_PER_SLOT * 1000;
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>;
@@ -1,8 +1,9 @@
1
1
  import {ChainForkConfig} from "@lodestar/config";
2
- import {ForkSeq, INTERVALS_PER_SLOT} from "@lodestar/params";
2
+ import {ForkSeq} from "@lodestar/params";
3
3
  import {RequestError, RequestErrorCode} from "@lodestar/reqresp";
4
- import {RootHex, Slot} from "@lodestar/types";
5
- import {Logger, prettyBytes, prettyPrintIndices, pruneSetToMax, sleep} from "@lodestar/utils";
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
- const {root, slot} = data.rootSlot;
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
- // we don't know the slot of parent, hence make it undefined
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, slot?: Slot, peerIdStr?: PeerIdStr): void => {
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
- rootHex: prettyBytes(pendingBlock.rootHex),
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
- blockRoot: prettyBytes(rootHex),
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.chain.genesisTime + blockSlot * this.config.SECONDS_PER_SLOT);
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({rootSlot: {root: pending.blockInput.parentRootHex}, source: BlockInputSource.byRoot});
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.secFromSlot(blockSlot) < this.proposerBoostSecWindow &&
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
- blockRoot: prettyBytes(pendingBlock.blockInput.blockRootHex),
408
+ root: pendingBlock.blockInput.blockRootHex,
411
409
  proposerIndex,
412
410
  });
413
- await sleep(this.proposerBoostSecWindow * 1000);
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 : cacheItem.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} blockRoot=${prettyBytes(rootHex)} after ${i}: cannot find peer`;
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} blockRoot=${prettyBytes(rootHex)} after ${i - 1} attempts.`;
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}) => (block as SignedBeaconBlock<ForkPostDeneb>).message.body.blobKzgCommitments.length + acc,
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.blobKzgCommitments;
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
- const blockKzgCommitments = (block as SignedBeaconBlock<ForkPostFulu>).message.body.blobKzgCommitments;
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 {ForkPostDeneb, ForkPostFulu, ForkPreFulu, isForkPostDeneb, isForkPostFulu} from "@lodestar/params";
4
- import {BlobIndex, ColumnIndex, SignedBeaconBlock, Slot, deneb, fulu} from "@lodestar/types";
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
- const blobCount = block.message.body.blobKzgCommitments.length;
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
  }