@lodestar/beacon-node 1.35.0-dev.21ba2777a9 → 1.35.0-dev.287e63792e

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 (142) 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/blocks/blockInput/blockInput.d.ts.map +1 -1
  10. package/lib/chain/blocks/blockInput/blockInput.js +3 -2
  11. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  12. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  13. package/lib/chain/blocks/importBlock.js +7 -6
  14. package/lib/chain/blocks/importBlock.js.map +1 -1
  15. package/lib/chain/blocks/verifyBlocksDataAvailability.d.ts.map +1 -1
  16. package/lib/chain/blocks/verifyBlocksDataAvailability.js +8 -1
  17. package/lib/chain/blocks/verifyBlocksDataAvailability.js.map +1 -1
  18. package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
  19. package/lib/chain/blocks/writeBlockInputToDb.js +1 -7
  20. package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
  21. package/lib/chain/chain.d.ts.map +1 -1
  22. package/lib/chain/chain.js +3 -4
  23. package/lib/chain/chain.js.map +1 -1
  24. package/lib/chain/lightClient/index.d.ts +2 -2
  25. package/lib/chain/lightClient/index.d.ts.map +1 -1
  26. package/lib/chain/lightClient/index.js +2 -0
  27. package/lib/chain/lightClient/index.js.map +1 -1
  28. package/lib/chain/opPools/attestationPool.d.ts +2 -3
  29. package/lib/chain/opPools/attestationPool.d.ts.map +1 -1
  30. package/lib/chain/opPools/attestationPool.js +3 -5
  31. package/lib/chain/opPools/attestationPool.js.map +1 -1
  32. package/lib/chain/opPools/syncCommitteeMessagePool.d.ts +3 -2
  33. package/lib/chain/opPools/syncCommitteeMessagePool.d.ts.map +1 -1
  34. package/lib/chain/opPools/syncCommitteeMessagePool.js +6 -5
  35. package/lib/chain/opPools/syncCommitteeMessagePool.js.map +1 -1
  36. package/lib/chain/opPools/types.d.ts +1 -1
  37. package/lib/chain/opPools/types.d.ts.map +1 -1
  38. package/lib/chain/opPools/types.js +1 -1
  39. package/lib/chain/opPools/types.js.map +1 -1
  40. package/lib/chain/prepareNextSlot.d.ts +3 -3
  41. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  42. package/lib/chain/prepareNextSlot.js +8 -8
  43. package/lib/chain/prepareNextSlot.js.map +1 -1
  44. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  45. package/lib/chain/produceBlock/produceBlockBody.js +10 -2
  46. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  47. package/lib/chain/regen/interface.d.ts +1 -0
  48. package/lib/chain/regen/interface.d.ts.map +1 -1
  49. package/lib/chain/regen/interface.js +1 -0
  50. package/lib/chain/regen/interface.js.map +1 -1
  51. package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
  52. package/lib/chain/seenCache/seenGossipBlockInput.js +8 -1
  53. package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
  54. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  55. package/lib/chain/stateCache/persistentCheckpointsCache.js +9 -8
  56. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  57. package/lib/chain/validation/dataColumnSidecar.js +1 -1
  58. package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
  59. package/lib/chain/validation/lightClientFinalityUpdate.d.ts.map +1 -1
  60. package/lib/chain/validation/lightClientFinalityUpdate.js +4 -3
  61. package/lib/chain/validation/lightClientFinalityUpdate.js.map +1 -1
  62. package/lib/chain/validation/lightClientOptimisticUpdate.d.ts +6 -4
  63. package/lib/chain/validation/lightClientOptimisticUpdate.d.ts.map +1 -1
  64. package/lib/chain/validation/lightClientOptimisticUpdate.js +11 -11
  65. package/lib/chain/validation/lightClientOptimisticUpdate.js.map +1 -1
  66. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  67. package/lib/chain/validatorMonitor.js +21 -15
  68. package/lib/chain/validatorMonitor.js.map +1 -1
  69. package/lib/metrics/metrics/lodestar.d.ts +1 -1
  70. package/lib/metrics/metrics/lodestar.js +3 -3
  71. package/lib/metrics/metrics/lodestar.js.map +1 -1
  72. package/lib/network/gossip/gossipsub.js +1 -1
  73. package/lib/network/gossip/gossipsub.js.map +1 -1
  74. package/lib/network/gossip/scoringParameters.js +4 -4
  75. package/lib/network/gossip/scoringParameters.js.map +1 -1
  76. package/lib/network/network.d.ts +1 -1
  77. package/lib/network/network.d.ts.map +1 -1
  78. package/lib/network/network.js +9 -9
  79. package/lib/network/network.js.map +1 -1
  80. package/lib/network/peers/peerManager.d.ts.map +1 -1
  81. package/lib/network/peers/peerManager.js +2 -1
  82. package/lib/network/peers/peerManager.js.map +1 -1
  83. package/lib/network/processor/gossipHandlers.js +1 -1
  84. package/lib/network/processor/gossipHandlers.js.map +1 -1
  85. package/lib/network/subnets/attnetsService.d.ts.map +1 -1
  86. package/lib/network/subnets/attnetsService.js +1 -1
  87. package/lib/network/subnets/attnetsService.js.map +1 -1
  88. package/lib/node/notifier.js +1 -1
  89. package/lib/node/notifier.js.map +1 -1
  90. package/lib/sync/unknownBlock.d.ts +0 -1
  91. package/lib/sync/unknownBlock.d.ts.map +1 -1
  92. package/lib/sync/unknownBlock.js +7 -6
  93. package/lib/sync/unknownBlock.js.map +1 -1
  94. package/lib/sync/utils/downloadByRange.d.ts +2 -1
  95. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  96. package/lib/sync/utils/downloadByRange.js +8 -3
  97. package/lib/sync/utils/downloadByRange.js.map +1 -1
  98. package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
  99. package/lib/sync/utils/downloadByRoot.js +2 -1
  100. package/lib/sync/utils/downloadByRoot.js.map +1 -1
  101. package/lib/util/clock.d.ts +8 -3
  102. package/lib/util/clock.d.ts.map +1 -1
  103. package/lib/util/clock.js +8 -5
  104. package/lib/util/clock.js.map +1 -1
  105. package/lib/util/dataColumns.d.ts.map +1 -1
  106. package/lib/util/dataColumns.js +4 -2
  107. package/lib/util/dataColumns.js.map +1 -1
  108. package/package.json +14 -14
  109. package/src/api/impl/beacon/blocks/index.ts +11 -2
  110. package/src/api/impl/lodestar/index.ts +1 -1
  111. package/src/api/impl/validator/index.ts +25 -28
  112. package/src/chain/blocks/blockInput/blockInput.ts +7 -4
  113. package/src/chain/blocks/importBlock.ts +8 -12
  114. package/src/chain/blocks/verifyBlocksDataAvailability.ts +10 -2
  115. package/src/chain/blocks/writeBlockInputToDb.ts +1 -9
  116. package/src/chain/chain.ts +3 -14
  117. package/src/chain/lightClient/index.ts +11 -3
  118. package/src/chain/opPools/attestationPool.ts +2 -3
  119. package/src/chain/opPools/syncCommitteeMessagePool.ts +5 -3
  120. package/src/chain/opPools/types.ts +1 -1
  121. package/src/chain/prepareNextSlot.ts +8 -8
  122. package/src/chain/produceBlock/produceBlockBody.ts +13 -3
  123. package/src/chain/regen/interface.ts +1 -0
  124. package/src/chain/seenCache/seenGossipBlockInput.ts +10 -2
  125. package/src/chain/stateCache/persistentCheckpointsCache.ts +10 -8
  126. package/src/chain/validation/dataColumnSidecar.ts +1 -1
  127. package/src/chain/validation/lightClientFinalityUpdate.ts +4 -3
  128. package/src/chain/validation/lightClientOptimisticUpdate.ts +12 -11
  129. package/src/chain/validatorMonitor.ts +28 -17
  130. package/src/metrics/metrics/lodestar.ts +3 -3
  131. package/src/network/gossip/gossipsub.ts +1 -1
  132. package/src/network/gossip/scoringParameters.ts +4 -4
  133. package/src/network/network.ts +9 -9
  134. package/src/network/peers/peerManager.ts +2 -1
  135. package/src/network/processor/gossipHandlers.ts +1 -1
  136. package/src/network/subnets/attnetsService.ts +3 -6
  137. package/src/node/notifier.ts +1 -1
  138. package/src/sync/unknownBlock.ts +7 -6
  139. package/src/sync/utils/downloadByRange.ts +12 -6
  140. package/src/sync/utils/downloadByRoot.ts +12 -4
  141. package/src/util/clock.ts +14 -6
  142. package/src/util/dataColumns.ts +11 -2
@@ -4,9 +4,11 @@ import {
4
4
  ForkPostBellatrix,
5
5
  ForkPostDeneb,
6
6
  ForkPostFulu,
7
+ ForkPreGloas,
7
8
  ForkSeq,
8
9
  isForkPostAltair,
9
10
  isForkPostBellatrix,
11
+ isForkPostGloas,
10
12
  } from "@lodestar/params";
11
13
  import {
12
14
  CachedBeaconStateAllForks,
@@ -182,7 +184,14 @@ export async function produceBlockBody<T extends BlockType>(
182
184
  };
183
185
  this.logger.verbose("Producing beacon block body", logMeta);
184
186
 
185
- if (isForkPostBellatrix(fork)) {
187
+ if (isForkPostGloas(fork)) {
188
+ // TODO GLOAS: Set body.signedExecutionPayloadBid and body.payloadAttestation
189
+ const commonBlockBody = await commonBlockBodyPromise;
190
+ blockBody = Object.assign({}, commonBlockBody) as AssembledBodyType<T>;
191
+ executionPayloadValue = BigInt(0);
192
+
193
+ // We don't deal with blinded blocks, execution engine, blobs and execution requests post-gloas
194
+ } else if (isForkPostBellatrix(fork)) {
186
195
  const safeBlockHash = this.forkChoice.getJustifiedBlock().executionPayloadBlockHash ?? ZERO_HASH_HEX;
187
196
  const finalizedBlockHash = this.forkChoice.getFinalizedBlock().executionPayloadBlockHash ?? ZERO_HASH_HEX;
188
197
  const feeRecipient = requestedFeeRecipient ?? this.beaconProposerCache.getOrDefault(proposerIndex);
@@ -307,6 +316,7 @@ export async function produceBlockBody<T extends BlockType>(
307
316
 
308
317
  // blockType === BlockType.Full
309
318
  else {
319
+ // enginePromise only supports pre-gloas
310
320
  const enginePromise = (async () => {
311
321
  const endExecutionPayload = this.metrics?.executionBlockProductionTimeSteps.startTimer();
312
322
 
@@ -384,13 +394,13 @@ export async function produceBlockBody<T extends BlockType>(
384
394
  blockBody = Object.assign({}, commonBlockBody) as AssembledBodyType<BlockType.Blinded>;
385
395
 
386
396
  if (engineRes.isPremerge) {
387
- (blockBody as BeaconBlockBody<ForkPostBellatrix>).executionPayload = engineRes.executionPayload;
397
+ (blockBody as BeaconBlockBody<ForkPostBellatrix & ForkPreGloas>).executionPayload = engineRes.executionPayload;
388
398
  executionPayloadValue = engineRes.executionPayloadValue;
389
399
  } else {
390
400
  const {prepType, payloadId, executionPayload, blobsBundle, executionRequests} = engineRes;
391
401
  shouldOverrideBuilder = engineRes.shouldOverrideBuilder;
392
402
 
393
- (blockBody as BeaconBlockBody<ForkPostBellatrix>).executionPayload = executionPayload;
403
+ (blockBody as BeaconBlockBody<ForkPostBellatrix & ForkPreGloas>).executionPayload = executionPayload;
394
404
  (produceResult as ProduceFullBellatrix).executionPayload = executionPayload;
395
405
  executionPayloadValue = engineRes.executionPayloadValue;
396
406
  Object.assign(logMeta, {transactions: executionPayload.transactions.length, shouldOverrideBuilder});
@@ -10,6 +10,7 @@ export enum RegenCaller {
10
10
  produceBlock = "produceBlock",
11
11
  validateGossipBlock = "validateGossipBlock",
12
12
  validateGossipBlob = "validateGossipBlob",
13
+ validateGossipDataColumn = "validateGossipDataColumn",
13
14
  precomputeEpoch = "precomputeEpoch",
14
15
  predictProposerHead = "predictProposerHead",
15
16
  produceAttestationData = "produceAttestationData",
@@ -1,6 +1,6 @@
1
1
  import {ChainForkConfig} from "@lodestar/config";
2
2
  import {CheckpointWithHex} from "@lodestar/fork-choice";
3
- import {ForkName, ForkPostFulu, isForkPostDeneb, isForkPostFulu} from "@lodestar/params";
3
+ import {ForkName, ForkPostFulu, ForkPreGloas, isForkPostDeneb, isForkPostFulu, isForkPostGloas} from "@lodestar/params";
4
4
  import {computeStartSlotAtEpoch} from "@lodestar/state-transition";
5
5
  import {RootHex, SignedBeaconBlock, Slot, deneb, fulu} from "@lodestar/types";
6
6
  import {LodestarError, Logger} from "@lodestar/utils";
@@ -155,6 +155,12 @@ export class SeenBlockInput {
155
155
  let blockInput = this.blockInputs.get(blockRootHex) as IBlockInput;
156
156
  if (!blockInput) {
157
157
  const {forkName, daOutOfRange} = this.buildCommonProps(block.message.slot);
158
+
159
+ // TODO GLOAS: Implement
160
+ if (isForkPostGloas(forkName)) {
161
+ throw Error("Not implemented");
162
+ }
163
+ // Pre-deneb
158
164
  if (!isForkPostDeneb(forkName)) {
159
165
  blockInput = BlockInputPreData.createFromBlock({
160
166
  block,
@@ -165,9 +171,10 @@ export class SeenBlockInput {
165
171
  seenTimestampSec,
166
172
  peerIdStr,
167
173
  });
174
+ // Fulu Only
168
175
  } else if (isForkPostFulu(forkName)) {
169
176
  blockInput = BlockInputColumns.createFromBlock({
170
- block: block as SignedBeaconBlock<ForkPostFulu>,
177
+ block: block as SignedBeaconBlock<ForkPostFulu & ForkPreGloas>,
171
178
  blockRootHex,
172
179
  daOutOfRange,
173
180
  forkName,
@@ -177,6 +184,7 @@ export class SeenBlockInput {
177
184
  seenTimestampSec,
178
185
  peerIdStr,
179
186
  });
187
+ // Deneb and Electra
180
188
  } else {
181
189
  blockInput = BlockInputBlobs.createFromBlock({
182
190
  block: block as SignedBeaconBlock<ForkBlobsDA>,
@@ -1,5 +1,4 @@
1
1
  import {routes} from "@lodestar/api";
2
- import {INTERVALS_PER_SLOT} from "@lodestar/params";
3
2
  import {
4
3
  CachedBeaconStateAllForks,
5
4
  computeStartSlotAtEpoch,
@@ -59,6 +58,9 @@ type LoadedStateBytesData = {persistedKey: DatastoreKey; stateBytes: Uint8Array}
59
58
  */
60
59
  export const DEFAULT_MAX_CP_STATE_EPOCHS_IN_MEMORY = 3;
61
60
 
61
+ // TODO GLOAS: re-evaluate this timing
62
+ const PROCESS_CHECKPOINT_STATES_BPS = 6667;
63
+
62
64
  /**
63
65
  * An implementation of CheckpointStateCache that keep up to n epoch checkpoint states in memory and persist the rest to disk
64
66
  * - If it's more than `maxEpochsInMemory` epochs old, it will persist n last epochs to disk based on the view of the block
@@ -464,14 +466,14 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
464
466
  }
465
467
 
466
468
  const blockSlot = state.slot;
467
- const twoThirdsSlot = (2 * state.config.SECONDS_PER_SLOT) / INTERVALS_PER_SLOT;
469
+ const processCPStatesTimeMs = state.config.getSlotComponentDurationMs(PROCESS_CHECKPOINT_STATES_BPS);
468
470
  // we always have clock in production, fallback value is only for test
469
- const secFromSlot = this.clock?.secFromSlot(blockSlot) ?? twoThirdsSlot;
470
- const secToTwoThirdsSlot = twoThirdsSlot - secFromSlot;
471
- if (secToTwoThirdsSlot > 0) {
472
- // 2/3 of slot is the most free time of every slot, take that chance to persist checkpoint states
473
- // normally it should only persist checkpoint states at 2/3 of slot 0 of epoch
474
- await sleep(secToTwoThirdsSlot * 1000, this.signal);
471
+ const msFromSlot = this.clock?.msFromSlot(blockSlot) ?? processCPStatesTimeMs;
472
+ const msToProcessCPStates = processCPStatesTimeMs - msFromSlot;
473
+ if (msToProcessCPStates > 0) {
474
+ // At ~67% of slot is the most free time of every slot, take that chance to persist checkpoint states
475
+ // normally it should only persist checkpoint states at ~67% of slot 0 of epoch
476
+ await sleep(msToProcessCPStates, this.signal);
475
477
  }
476
478
  // at syncing time, it's critical to persist checkpoint states as soon as possible to avoid OOM during unfinality time
477
479
  // if node is synced this is not a hot time because block comes late, we'll likely miss attestation already, or the block is orphaned
@@ -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()) {
@@ -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 =
@@ -1,6 +1,7 @@
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 {computeTimeAtSlot} from "@lodestar/state-transition";
4
5
  import {RootHex} from "@lodestar/types";
5
6
  import {Logger, prettyPrintIndices, pruneSetToMax, sleep} from "@lodestar/utils";
6
7
  import {isBlockInputBlobs, isBlockInputColumns} from "../chain/blocks/blockInput/blockInput.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) {
@@ -331,7 +330,7 @@ export class BlockInputSync {
331
330
  this.pendingBlocks.set(pending.blockInput.blockRootHex, pending);
332
331
  const blockSlot = pending.blockInput.slot;
333
332
  const finalizedSlot = this.chain.forkChoice.getFinalizedBlock().slot;
334
- 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);
335
334
  this.metrics?.blockInputSync.elapsedTimeTillReceived.observe(delaySec);
336
335
 
337
336
  const parentInForkChoice = this.chain.forkChoice.hasBlockHex(pending.blockInput.parentRootHex);
@@ -396,8 +395,10 @@ export class BlockInputSync {
396
395
  // this prevents unbundling attack
397
396
  // see https://lighthouse-blog.sigmaprime.io/mev-unbundling-rpc.html
398
397
  const {slot: blockSlot, proposerIndex} = pendingBlock.blockInput.getBlock().message;
398
+ const fork = this.config.getForkName(blockSlot);
399
+ const proposerBoostWindowMs = this.config.getAttestationDueMs(fork);
399
400
  if (
400
- this.chain.clock.secFromSlot(blockSlot) < this.proposerBoostSecWindow &&
401
+ this.chain.clock.msFromSlot(blockSlot) < proposerBoostWindowMs &&
401
402
  this.chain.seenBlockProposers.isKnown(blockSlot, proposerIndex)
402
403
  ) {
403
404
  // proposer is known by a gossip block already, wait a bit to make sure this block is not
@@ -407,7 +408,7 @@ export class BlockInputSync {
407
408
  root: pendingBlock.blockInput.blockRootHex,
408
409
  proposerIndex,
409
410
  });
410
- await sleep(this.proposerBoostSecWindow * 1000);
411
+ await sleep(proposerBoostWindowMs);
411
412
  }
412
413
  // At gossip time, it's critical to keep a good number of mesh peers.
413
414
  // To do that, the Gossip Job Wait Time should be consistently <3s to avoid the behavior penalties in gossip
@@ -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
  }