@lodestar/beacon-node 1.35.0-dev.8689cc3545 → 1.35.0-dev.894daf8b44

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 (163) 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/config/constants.d.ts +9 -9
  5. package/lib/api/impl/config/constants.js +16 -9
  6. package/lib/api/impl/config/constants.js.map +1 -1
  7. package/lib/api/impl/lodestar/index.js +1 -1
  8. package/lib/api/impl/lodestar/index.js.map +1 -1
  9. package/lib/api/impl/validator/index.d.ts.map +1 -1
  10. package/lib/api/impl/validator/index.js +24 -33
  11. package/lib/api/impl/validator/index.js.map +1 -1
  12. package/lib/chain/archiveStore/historicalState/worker.js +1 -1
  13. package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
  14. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  15. package/lib/chain/blocks/blockInput/blockInput.js +3 -2
  16. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  17. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  18. package/lib/chain/blocks/importBlock.js +7 -6
  19. package/lib/chain/blocks/importBlock.js.map +1 -1
  20. package/lib/chain/blocks/verifyBlocksDataAvailability.d.ts.map +1 -1
  21. package/lib/chain/blocks/verifyBlocksDataAvailability.js +8 -1
  22. package/lib/chain/blocks/verifyBlocksDataAvailability.js.map +1 -1
  23. package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
  24. package/lib/chain/blocks/writeBlockInputToDb.js +1 -7
  25. package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
  26. package/lib/chain/chain.d.ts +1 -1
  27. package/lib/chain/chain.d.ts.map +1 -1
  28. package/lib/chain/chain.js +4 -6
  29. package/lib/chain/chain.js.map +1 -1
  30. package/lib/chain/emitter.d.ts +2 -2
  31. package/lib/chain/emitter.d.ts.map +1 -1
  32. package/lib/chain/lightClient/index.d.ts +2 -2
  33. package/lib/chain/lightClient/index.d.ts.map +1 -1
  34. package/lib/chain/lightClient/index.js +2 -0
  35. package/lib/chain/lightClient/index.js.map +1 -1
  36. package/lib/chain/opPools/attestationPool.d.ts +2 -3
  37. package/lib/chain/opPools/attestationPool.d.ts.map +1 -1
  38. package/lib/chain/opPools/attestationPool.js +3 -5
  39. package/lib/chain/opPools/attestationPool.js.map +1 -1
  40. package/lib/chain/opPools/syncCommitteeMessagePool.d.ts +3 -2
  41. package/lib/chain/opPools/syncCommitteeMessagePool.d.ts.map +1 -1
  42. package/lib/chain/opPools/syncCommitteeMessagePool.js +6 -5
  43. package/lib/chain/opPools/syncCommitteeMessagePool.js.map +1 -1
  44. package/lib/chain/opPools/types.d.ts +1 -1
  45. package/lib/chain/opPools/types.d.ts.map +1 -1
  46. package/lib/chain/opPools/types.js +1 -1
  47. package/lib/chain/opPools/types.js.map +1 -1
  48. package/lib/chain/prepareNextSlot.d.ts +3 -3
  49. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  50. package/lib/chain/prepareNextSlot.js +8 -8
  51. package/lib/chain/prepareNextSlot.js.map +1 -1
  52. package/lib/chain/produceBlock/produceBlockBody.d.ts +1 -4
  53. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  54. package/lib/chain/produceBlock/produceBlockBody.js +13 -4
  55. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  56. package/lib/chain/regen/interface.d.ts +1 -0
  57. package/lib/chain/regen/interface.d.ts.map +1 -1
  58. package/lib/chain/regen/interface.js +1 -0
  59. package/lib/chain/regen/interface.js.map +1 -1
  60. package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
  61. package/lib/chain/seenCache/seenGossipBlockInput.js +8 -1
  62. package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
  63. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  64. package/lib/chain/stateCache/persistentCheckpointsCache.js +9 -8
  65. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  66. package/lib/chain/validation/dataColumnSidecar.js +1 -1
  67. package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
  68. package/lib/chain/validation/lightClientFinalityUpdate.d.ts.map +1 -1
  69. package/lib/chain/validation/lightClientFinalityUpdate.js +4 -3
  70. package/lib/chain/validation/lightClientFinalityUpdate.js.map +1 -1
  71. package/lib/chain/validation/lightClientOptimisticUpdate.d.ts +6 -4
  72. package/lib/chain/validation/lightClientOptimisticUpdate.d.ts.map +1 -1
  73. package/lib/chain/validation/lightClientOptimisticUpdate.js +11 -11
  74. package/lib/chain/validation/lightClientOptimisticUpdate.js.map +1 -1
  75. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  76. package/lib/chain/validatorMonitor.js +21 -15
  77. package/lib/chain/validatorMonitor.js.map +1 -1
  78. package/lib/metrics/metrics/lodestar.d.ts +1 -1
  79. package/lib/metrics/metrics/lodestar.js +3 -3
  80. package/lib/metrics/metrics/lodestar.js.map +1 -1
  81. package/lib/network/gossip/gossipsub.js +1 -1
  82. package/lib/network/gossip/gossipsub.js.map +1 -1
  83. package/lib/network/gossip/scoringParameters.js +4 -4
  84. package/lib/network/gossip/scoringParameters.js.map +1 -1
  85. package/lib/network/network.d.ts +1 -1
  86. package/lib/network/network.d.ts.map +1 -1
  87. package/lib/network/network.js +9 -9
  88. package/lib/network/network.js.map +1 -1
  89. package/lib/network/peers/peerManager.d.ts.map +1 -1
  90. package/lib/network/peers/peerManager.js +2 -1
  91. package/lib/network/peers/peerManager.js.map +1 -1
  92. package/lib/network/processor/gossipHandlers.js +1 -1
  93. package/lib/network/processor/gossipHandlers.js.map +1 -1
  94. package/lib/network/processor/index.d.ts +1 -1
  95. package/lib/network/processor/index.d.ts.map +1 -1
  96. package/lib/network/processor/index.js +2 -3
  97. package/lib/network/processor/index.js.map +1 -1
  98. package/lib/network/subnets/attnetsService.d.ts.map +1 -1
  99. package/lib/network/subnets/attnetsService.js +1 -1
  100. package/lib/network/subnets/attnetsService.js.map +1 -1
  101. package/lib/node/notifier.js +1 -1
  102. package/lib/node/notifier.js.map +1 -1
  103. package/lib/sync/types.d.ts +0 -1
  104. package/lib/sync/types.d.ts.map +1 -1
  105. package/lib/sync/types.js.map +1 -1
  106. package/lib/sync/unknownBlock.d.ts +0 -1
  107. package/lib/sync/unknownBlock.d.ts.map +1 -1
  108. package/lib/sync/unknownBlock.js +18 -20
  109. package/lib/sync/unknownBlock.js.map +1 -1
  110. package/lib/sync/utils/downloadByRange.d.ts +2 -1
  111. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  112. package/lib/sync/utils/downloadByRange.js +8 -3
  113. package/lib/sync/utils/downloadByRange.js.map +1 -1
  114. package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
  115. package/lib/sync/utils/downloadByRoot.js +2 -1
  116. package/lib/sync/utils/downloadByRoot.js.map +1 -1
  117. package/lib/util/clock.d.ts +8 -3
  118. package/lib/util/clock.d.ts.map +1 -1
  119. package/lib/util/clock.js +8 -5
  120. package/lib/util/clock.js.map +1 -1
  121. package/lib/util/dataColumns.d.ts.map +1 -1
  122. package/lib/util/dataColumns.js +4 -2
  123. package/lib/util/dataColumns.js.map +1 -1
  124. package/package.json +14 -14
  125. package/src/api/impl/beacon/blocks/index.ts +11 -2
  126. package/src/api/impl/config/constants.ts +17 -9
  127. package/src/api/impl/lodestar/index.ts +1 -1
  128. package/src/api/impl/validator/index.ts +25 -37
  129. package/src/chain/archiveStore/historicalState/worker.ts +1 -1
  130. package/src/chain/blocks/blockInput/blockInput.ts +7 -4
  131. package/src/chain/blocks/importBlock.ts +8 -12
  132. package/src/chain/blocks/verifyBlocksDataAvailability.ts +10 -2
  133. package/src/chain/blocks/writeBlockInputToDb.ts +1 -9
  134. package/src/chain/chain.ts +3 -16
  135. package/src/chain/emitter.ts +2 -2
  136. package/src/chain/lightClient/index.ts +11 -3
  137. package/src/chain/opPools/attestationPool.ts +2 -3
  138. package/src/chain/opPools/syncCommitteeMessagePool.ts +5 -3
  139. package/src/chain/opPools/types.ts +1 -1
  140. package/src/chain/prepareNextSlot.ts +8 -8
  141. package/src/chain/produceBlock/produceBlockBody.ts +16 -14
  142. package/src/chain/regen/interface.ts +1 -0
  143. package/src/chain/seenCache/seenGossipBlockInput.ts +10 -2
  144. package/src/chain/stateCache/persistentCheckpointsCache.ts +10 -8
  145. package/src/chain/validation/dataColumnSidecar.ts +1 -1
  146. package/src/chain/validation/lightClientFinalityUpdate.ts +4 -3
  147. package/src/chain/validation/lightClientOptimisticUpdate.ts +12 -11
  148. package/src/chain/validatorMonitor.ts +28 -17
  149. package/src/metrics/metrics/lodestar.ts +3 -3
  150. package/src/network/gossip/gossipsub.ts +1 -1
  151. package/src/network/gossip/scoringParameters.ts +4 -4
  152. package/src/network/network.ts +9 -9
  153. package/src/network/peers/peerManager.ts +2 -1
  154. package/src/network/processor/gossipHandlers.ts +1 -1
  155. package/src/network/processor/index.ts +2 -3
  156. package/src/network/subnets/attnetsService.ts +3 -6
  157. package/src/node/notifier.ts +1 -1
  158. package/src/sync/types.ts +0 -2
  159. package/src/sync/unknownBlock.ts +19 -21
  160. package/src/sync/utils/downloadByRange.ts +12 -6
  161. package/src/sync/utils/downloadByRoot.ts +12 -4
  162. package/src/util/clock.ts +14 -6
  163. package/src/util/dataColumns.ts +11 -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
  }
package/src/util/clock.ts CHANGED
@@ -9,12 +9,12 @@ import {MAXIMUM_GOSSIP_CLOCK_DISPARITY} from "../constants/constants.js";
9
9
  export enum ClockEvent {
10
10
  /**
11
11
  * This event signals the start of a new slot, and that subsequent calls to `clock.currentSlot` will equal `slot`.
12
- * This event is guaranteed to be emitted every `SECONDS_PER_SLOT` seconds.
12
+ * This event is guaranteed to be emitted every `SLOT_DURATION_MS` milliseconds.
13
13
  */
14
14
  slot = "clock:slot",
15
15
  /**
16
16
  * This event signals the start of a new epoch, and that subsequent calls to `clock.currentEpoch` will return `epoch`.
17
- * This event is guaranteed to be emitted every `SECONDS_PER_SLOT * SLOTS_PER_EPOCH` seconds.
17
+ * This event is guaranteed to be emitted every `SLOT_DURATION_MS * SLOTS_PER_EPOCH` milliseconds.
18
18
  */
19
19
  epoch = "clock:epoch",
20
20
  }
@@ -29,7 +29,7 @@ export type ClockEvents = {
29
29
  *
30
30
  * The time is dependent on:
31
31
  * - `state.genesisTime` - the genesis time
32
- * - `SECONDS_PER_SLOT` - # of seconds per slot
32
+ * - `SLOT_DURATION_MS` - # of milliseconds per slot
33
33
  * - `SLOTS_PER_EPOCH` - # of slots per epoch
34
34
  */
35
35
  export type IClock = StrictEventEmitter<EventEmitter, ClockEvents> & {
@@ -58,6 +58,10 @@ export type IClock = StrictEventEmitter<EventEmitter, ClockEvents> & {
58
58
  * Return second from a slot to either toSec or now.
59
59
  */
60
60
  secFromSlot(slot: Slot, toSec?: number): number;
61
+ /**
62
+ * Return milliseconds from a slot to either toMs or now.
63
+ */
64
+ msFromSlot(slot: Slot, toMs?: number): number;
61
65
  };
62
66
 
63
67
  /**
@@ -170,12 +174,16 @@ export class Clock extends EventEmitter implements IClock {
170
174
  }
171
175
 
172
176
  secFromSlot(slot: Slot, toSec = Date.now() / 1000): number {
173
- return toSec - (this.genesisTime + slot * this.config.SECONDS_PER_SLOT);
177
+ return toSec - computeTimeAtSlot(this.config, slot, this.genesisTime);
178
+ }
179
+
180
+ msFromSlot(slot: Slot, toMs = Date.now()): number {
181
+ return toMs - computeTimeAtSlot(this.config, slot, this.genesisTime) * 1000;
174
182
  }
175
183
 
176
184
  private onNextSlot = (slot?: Slot): void => {
177
185
  const clockSlot = slot ?? getCurrentSlot(this.config, this.genesisTime);
178
- // process multiple clock slots in the case the main thread has been saturated for > SECONDS_PER_SLOT
186
+ // process multiple clock slots in the case the main thread has been saturated for > SLOT_DURATION_MS
179
187
  while (this._currentSlot < clockSlot && !this.signal.aborted) {
180
188
  const previousSlot = this._currentSlot;
181
189
  this._currentSlot++;
@@ -197,7 +205,7 @@ export class Clock extends EventEmitter implements IClock {
197
205
  };
198
206
 
199
207
  private msUntilNextSlot(): number {
200
- const milliSecondsPerSlot = this.config.SECONDS_PER_SLOT * 1000;
208
+ const milliSecondsPerSlot = this.config.SLOT_DURATION_MS;
201
209
  const diffInMilliSeconds = Date.now() - this.genesisTime * 1000;
202
210
  return milliSecondsPerSlot - (diffInMilliSeconds % milliSecondsPerSlot);
203
211
  }
@@ -1,7 +1,14 @@
1
1
  import {digest} from "@chainsafe/as-sha256";
2
2
  import {Tree} from "@chainsafe/persistent-merkle-tree";
3
3
  import {ChainForkConfig} from "@lodestar/config";
4
- import {ForkAll, ForkName, ForkPostFulu, KZG_COMMITMENTS_GINDEX, NUMBER_OF_COLUMNS} from "@lodestar/params";
4
+ import {
5
+ ForkAll,
6
+ ForkName,
7
+ ForkPostFulu,
8
+ ForkPreGloas,
9
+ KZG_COMMITMENTS_GINDEX,
10
+ NUMBER_OF_COLUMNS,
11
+ } from "@lodestar/params";
5
12
  import {signedBlockToSignedHeader} from "@lodestar/state-transition";
6
13
  import {
7
14
  BeaconBlockBody,
@@ -303,7 +310,9 @@ export function getDataColumnSidecarsFromBlock(
303
310
  signedBlock: SignedBeaconBlock<ForkPostFulu>,
304
311
  cellsAndKzgProofs: {cells: Uint8Array[]; proofs: Uint8Array[]}[]
305
312
  ): fulu.DataColumnSidecars {
306
- const blobKzgCommitments = signedBlock.message.body.blobKzgCommitments;
313
+ // TODO GLOAS: Need to get blobKzgCommitments from somewhere else
314
+ const blobKzgCommitments = (signedBlock.message.body as BeaconBlockBody<ForkPostFulu & ForkPreGloas>)
315
+ .blobKzgCommitments;
307
316
 
308
317
  // No need to create data column sidecars if there are no blobs
309
318
  if (blobKzgCommitments.length === 0) {