@lodestar/beacon-node 1.50.0-dev.90ea92ca6e → 1.50.0-dev.9203d3d7da

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 (235) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +7 -2
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/beacon/state/index.d.ts.map +1 -1
  5. package/lib/api/impl/beacon/state/index.js +6 -4
  6. package/lib/api/impl/beacon/state/index.js.map +1 -1
  7. package/lib/api/impl/validator/index.d.ts.map +1 -1
  8. package/lib/api/impl/validator/index.js +57 -17
  9. package/lib/api/impl/validator/index.js.map +1 -1
  10. package/lib/chain/ColumnReconstructionTracker.d.ts +0 -2
  11. package/lib/chain/ColumnReconstructionTracker.d.ts.map +1 -1
  12. package/lib/chain/ColumnReconstructionTracker.js +4 -5
  13. package/lib/chain/ColumnReconstructionTracker.js.map +1 -1
  14. package/lib/chain/beaconProposerCache.d.ts +6 -0
  15. package/lib/chain/beaconProposerCache.d.ts.map +1 -1
  16. package/lib/chain/beaconProposerCache.js +16 -0
  17. package/lib/chain/beaconProposerCache.js.map +1 -1
  18. package/lib/chain/blocks/blockInput/blockInput.d.ts +1 -1
  19. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  20. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  21. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  22. package/lib/chain/blocks/importBlock.js +13 -8
  23. package/lib/chain/blocks/importBlock.js.map +1 -1
  24. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  25. package/lib/chain/blocks/verifyBlock.js +6 -6
  26. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  27. package/lib/chain/chain.d.ts +1 -0
  28. package/lib/chain/chain.d.ts.map +1 -1
  29. package/lib/chain/chain.js +52 -17
  30. package/lib/chain/chain.js.map +1 -1
  31. package/lib/chain/interface.d.ts +3 -1
  32. package/lib/chain/interface.d.ts.map +1 -1
  33. package/lib/chain/opPools/opPool.d.ts.map +1 -1
  34. package/lib/chain/opPools/opPool.js +1 -23
  35. package/lib/chain/opPools/opPool.js.map +1 -1
  36. package/lib/chain/opPools/proposerPreferencesPool.d.ts +4 -0
  37. package/lib/chain/opPools/proposerPreferencesPool.d.ts.map +1 -1
  38. package/lib/chain/opPools/proposerPreferencesPool.js +13 -1
  39. package/lib/chain/opPools/proposerPreferencesPool.js.map +1 -1
  40. package/lib/chain/opPools/utils.d.ts +11 -0
  41. package/lib/chain/opPools/utils.d.ts.map +1 -1
  42. package/lib/chain/opPools/utils.js +22 -0
  43. package/lib/chain/opPools/utils.js.map +1 -1
  44. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  45. package/lib/chain/prepareNextSlot.js +15 -6
  46. package/lib/chain/prepareNextSlot.js.map +1 -1
  47. package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
  48. package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
  49. package/lib/chain/produceBlock/produceBlockBody.d.ts +8 -0
  50. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  51. package/lib/chain/produceBlock/produceBlockBody.js +48 -34
  52. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  53. package/lib/chain/reprocess.d.ts +2 -1
  54. package/lib/chain/reprocess.d.ts.map +1 -1
  55. package/lib/chain/reprocess.js +2 -1
  56. package/lib/chain/reprocess.js.map +1 -1
  57. package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
  58. package/lib/chain/seenCache/seenGossipBlockInput.js +1 -1
  59. package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
  60. package/lib/chain/shufflingCache.d.ts +17 -8
  61. package/lib/chain/shufflingCache.d.ts.map +1 -1
  62. package/lib/chain/shufflingCache.js +68 -18
  63. package/lib/chain/shufflingCache.js.map +1 -1
  64. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  65. package/lib/chain/stateCache/persistentCheckpointsCache.js +1 -1
  66. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  67. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  68. package/lib/chain/validatorMonitor.js +6 -4
  69. package/lib/chain/validatorMonitor.js.map +1 -1
  70. package/lib/constants/constants.d.ts +1 -0
  71. package/lib/constants/constants.d.ts.map +1 -1
  72. package/lib/constants/constants.js +1 -0
  73. package/lib/constants/constants.js.map +1 -1
  74. package/lib/db/beacon.d.ts +2 -1
  75. package/lib/db/beacon.d.ts.map +1 -1
  76. package/lib/db/beacon.js +3 -1
  77. package/lib/db/beacon.js.map +1 -1
  78. package/lib/db/buckets.d.ts +2 -1
  79. package/lib/db/buckets.d.ts.map +1 -1
  80. package/lib/db/buckets.js +1 -0
  81. package/lib/db/buckets.js.map +1 -1
  82. package/lib/db/interface.d.ts +2 -1
  83. package/lib/db/interface.d.ts.map +1 -1
  84. package/lib/db/repositories/blockArchive.js +2 -2
  85. package/lib/db/repositories/blockArchive.js.map +1 -1
  86. package/lib/db/repositories/blockArchiveIndex.d.ts +3 -3
  87. package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
  88. package/lib/db/repositories/blockArchiveIndex.js +1 -2
  89. package/lib/db/repositories/blockArchiveIndex.js.map +1 -1
  90. package/lib/db/repositories/index.d.ts +1 -0
  91. package/lib/db/repositories/index.d.ts.map +1 -1
  92. package/lib/db/repositories/index.js +1 -0
  93. package/lib/db/repositories/index.js.map +1 -1
  94. package/lib/db/repositories/proposerPreferences.d.ts +14 -0
  95. package/lib/db/repositories/proposerPreferences.d.ts.map +1 -0
  96. package/lib/db/repositories/proposerPreferences.js +21 -0
  97. package/lib/db/repositories/proposerPreferences.js.map +1 -0
  98. package/lib/execution/engine/blobVersionedHashes.d.ts +9 -0
  99. package/lib/execution/engine/blobVersionedHashes.d.ts.map +1 -0
  100. package/lib/execution/engine/blobVersionedHashes.js +74 -0
  101. package/lib/execution/engine/blobVersionedHashes.js.map +1 -0
  102. package/lib/execution/engine/http.d.ts +45 -13
  103. package/lib/execution/engine/http.d.ts.map +1 -1
  104. package/lib/execution/engine/http.js +236 -198
  105. package/lib/execution/engine/http.js.map +1 -1
  106. package/lib/execution/engine/index.d.ts +3 -2
  107. package/lib/execution/engine/index.d.ts.map +1 -1
  108. package/lib/execution/engine/index.js +33 -8
  109. package/lib/execution/engine/index.js.map +1 -1
  110. package/lib/execution/engine/interface.d.ts +1 -1
  111. package/lib/execution/engine/interface.d.ts.map +1 -1
  112. package/lib/execution/engine/jsonRpcTransport.d.ts +25 -0
  113. package/lib/execution/engine/jsonRpcTransport.d.ts.map +1 -0
  114. package/lib/execution/engine/jsonRpcTransport.js +158 -0
  115. package/lib/execution/engine/jsonRpcTransport.js.map +1 -0
  116. package/lib/execution/engine/restHttpClient.d.ts +71 -0
  117. package/lib/execution/engine/restHttpClient.d.ts.map +1 -0
  118. package/lib/execution/engine/restHttpClient.js +201 -0
  119. package/lib/execution/engine/restHttpClient.js.map +1 -0
  120. package/lib/execution/engine/restTransport.d.ts +46 -0
  121. package/lib/execution/engine/restTransport.d.ts.map +1 -0
  122. package/lib/execution/engine/restTransport.js +399 -0
  123. package/lib/execution/engine/restTransport.js.map +1 -0
  124. package/lib/execution/engine/sszTypes.d.ts +1261 -0
  125. package/lib/execution/engine/sszTypes.d.ts.map +1 -0
  126. package/lib/execution/engine/sszTypes.js +216 -0
  127. package/lib/execution/engine/sszTypes.js.map +1 -0
  128. package/lib/execution/engine/transport.d.ts +39 -0
  129. package/lib/execution/engine/transport.d.ts.map +1 -0
  130. package/lib/execution/engine/transport.js +2 -0
  131. package/lib/execution/engine/transport.js.map +1 -0
  132. package/lib/execution/engine/types.d.ts +2 -0
  133. package/lib/execution/engine/types.d.ts.map +1 -1
  134. package/lib/execution/engine/types.js +24 -57
  135. package/lib/execution/engine/types.js.map +1 -1
  136. package/lib/execution/engine/utils.d.ts.map +1 -1
  137. package/lib/execution/engine/utils.js +9 -2
  138. package/lib/execution/engine/utils.js.map +1 -1
  139. package/lib/metrics/metrics/lodestar.d.ts +9 -0
  140. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  141. package/lib/metrics/metrics/lodestar.js +18 -0
  142. package/lib/metrics/metrics/lodestar.js.map +1 -1
  143. package/lib/network/core/events.d.ts +5 -1
  144. package/lib/network/core/events.d.ts.map +1 -1
  145. package/lib/network/core/events.js +8 -0
  146. package/lib/network/core/events.js.map +1 -1
  147. package/lib/network/gossip/topic.d.ts +0 -14
  148. package/lib/network/gossip/topic.d.ts.map +1 -1
  149. package/lib/network/processor/gossipHandlers.js +1 -1
  150. package/lib/network/processor/gossipHandlers.js.map +1 -1
  151. package/lib/network/processor/index.js +3 -3
  152. package/lib/network/processor/index.js.map +1 -1
  153. package/lib/network/reqresp/rateLimit.js +2 -2
  154. package/lib/network/reqresp/rateLimit.js.map +1 -1
  155. package/lib/network/subnets/attnetsService.d.ts.map +1 -1
  156. package/lib/network/subnets/attnetsService.js +3 -1
  157. package/lib/network/subnets/attnetsService.js.map +1 -1
  158. package/lib/node/notifier.d.ts.map +1 -1
  159. package/lib/node/notifier.js +12 -13
  160. package/lib/node/notifier.js.map +1 -1
  161. package/lib/node/options.d.ts +3 -2
  162. package/lib/node/options.d.ts.map +1 -1
  163. package/lib/node/options.js +2 -2
  164. package/lib/node/options.js.map +1 -1
  165. package/lib/sync/unknownBlock.d.ts.map +1 -1
  166. package/lib/sync/unknownBlock.js +3 -2
  167. package/lib/sync/unknownBlock.js.map +1 -1
  168. package/lib/util/asyncIterableToEvents.d.ts +10 -2
  169. package/lib/util/asyncIterableToEvents.d.ts.map +1 -1
  170. package/lib/util/asyncIterableToEvents.js +29 -3
  171. package/lib/util/asyncIterableToEvents.js.map +1 -1
  172. package/lib/util/clock.d.ts.map +1 -1
  173. package/lib/util/clock.js +3 -4
  174. package/lib/util/clock.js.map +1 -1
  175. package/lib/util/metadata.d.ts.map +1 -1
  176. package/lib/util/metadata.js +2 -1
  177. package/lib/util/metadata.js.map +1 -1
  178. package/lib/util/sszBytes.d.ts +2 -2
  179. package/lib/util/sszBytes.d.ts.map +1 -1
  180. package/lib/util/sszBytes.js +22 -14
  181. package/lib/util/sszBytes.js.map +1 -1
  182. package/package.json +16 -15
  183. package/src/api/impl/beacon/blocks/index.ts +10 -3
  184. package/src/api/impl/beacon/state/index.ts +13 -4
  185. package/src/api/impl/validator/index.ts +78 -19
  186. package/src/chain/ColumnReconstructionTracker.ts +4 -6
  187. package/src/chain/beaconProposerCache.ts +19 -1
  188. package/src/chain/blocks/blockInput/blockInput.ts +1 -1
  189. package/src/chain/blocks/importBlock.ts +15 -7
  190. package/src/chain/blocks/verifyBlock.ts +7 -6
  191. package/src/chain/chain.ts +62 -17
  192. package/src/chain/interface.ts +4 -1
  193. package/src/chain/opPools/opPool.ts +1 -31
  194. package/src/chain/opPools/proposerPreferencesPool.ts +20 -1
  195. package/src/chain/opPools/utils.ts +31 -0
  196. package/src/chain/prepareNextSlot.ts +22 -6
  197. package/src/chain/produceBlock/computeNewStateRoot.ts +9 -2
  198. package/src/chain/produceBlock/produceBlockBody.ts +78 -39
  199. package/src/chain/reprocess.ts +2 -1
  200. package/src/chain/seenCache/seenGossipBlockInput.ts +2 -1
  201. package/src/chain/shufflingCache.ts +79 -22
  202. package/src/chain/stateCache/persistentCheckpointsCache.ts +4 -1
  203. package/src/chain/validatorMonitor.ts +7 -4
  204. package/src/constants/constants.ts +1 -0
  205. package/src/db/beacon.ts +3 -0
  206. package/src/db/buckets.ts +1 -0
  207. package/src/db/interface.ts +2 -0
  208. package/src/db/repositories/blockArchive.ts +2 -2
  209. package/src/db/repositories/blockArchiveIndex.ts +2 -3
  210. package/src/db/repositories/index.ts +1 -0
  211. package/src/db/repositories/proposerPreferences.ts +23 -0
  212. package/src/execution/engine/blobVersionedHashes.ts +72 -0
  213. package/src/execution/engine/http.ts +304 -271
  214. package/src/execution/engine/index.ts +41 -7
  215. package/src/execution/engine/interface.ts +1 -1
  216. package/src/execution/engine/jsonRpcTransport.ts +247 -0
  217. package/src/execution/engine/restHttpClient.ts +269 -0
  218. package/src/execution/engine/restTransport.ts +544 -0
  219. package/src/execution/engine/sszTypes.ts +354 -0
  220. package/src/execution/engine/transport.ts +61 -0
  221. package/src/execution/engine/types.ts +34 -74
  222. package/src/execution/engine/utils.ts +12 -2
  223. package/src/metrics/metrics/lodestar.ts +19 -0
  224. package/src/network/core/events.ts +16 -1
  225. package/src/network/processor/gossipHandlers.ts +1 -1
  226. package/src/network/processor/index.ts +3 -3
  227. package/src/network/reqresp/rateLimit.ts +2 -2
  228. package/src/network/subnets/attnetsService.ts +8 -3
  229. package/src/node/notifier.ts +14 -13
  230. package/src/node/options.ts +10 -1
  231. package/src/sync/unknownBlock.ts +3 -2
  232. package/src/util/asyncIterableToEvents.ts +44 -5
  233. package/src/util/clock.ts +3 -4
  234. package/src/util/metadata.ts +2 -1
  235. package/src/util/sszBytes.ts +25 -12
@@ -1,21 +1,30 @@
1
1
  import EventEmitter from "node:events";
2
2
  import {ResponseIncoming, ResponseOutgoing} from "@lodestar/reqresp";
3
- import {AsyncIterableEventBus, IteratorEvent, RequestEvent} from "../../util/asyncIterableToEvents.js";
3
+ import {
4
+ AsyncIterableEventBus,
5
+ IteratorEvent,
6
+ RequestCancelEvent,
7
+ RequestEvent,
8
+ } from "../../util/asyncIterableToEvents.js";
4
9
  import {StrictEventEmitterSingleArg} from "../../util/strictEvents.js";
5
10
  import {EventDirection} from "../events.js";
6
11
  import {IncomingRequestArgs, OutgoingRequestArgs} from "../reqresp/types.js";
7
12
 
8
13
  export enum ReqRespBridgeEvent {
9
14
  outgoingRequest = "reqresp.outgoingRequest",
15
+ outgoingRequestCancel = "reqresp.outgoingRequestCancel",
10
16
  outgoingResponse = "reqresp.outgoingResponse",
11
17
  incomingRequest = "reqresp.incomingRequest",
18
+ incomingRequestCancel = "reqresp.incomingRequestCancel",
12
19
  incomingResponse = "reqresp.incomingResponse",
13
20
  }
14
21
 
15
22
  export type ReqRespBridgeEventData = {
16
23
  [ReqRespBridgeEvent.outgoingRequest]: RequestEvent<OutgoingRequestArgs>;
24
+ [ReqRespBridgeEvent.outgoingRequestCancel]: RequestCancelEvent;
17
25
  [ReqRespBridgeEvent.outgoingResponse]: IteratorEvent<ResponseOutgoing>;
18
26
  [ReqRespBridgeEvent.incomingRequest]: RequestEvent<IncomingRequestArgs>;
27
+ [ReqRespBridgeEvent.incomingRequestCancel]: RequestCancelEvent;
19
28
  [ReqRespBridgeEvent.incomingResponse]: IteratorEvent<ResponseIncoming>;
20
29
  };
21
30
 
@@ -26,8 +35,10 @@ export class ReqRespBridgeEventBus extends (EventEmitter as {new (): IReqRespBri
26
35
  // NOTE: If the same event is on this two arrays it can create an infinite cycle
27
36
  export const reqRespBridgeEventDirection: Record<ReqRespBridgeEvent, EventDirection> = {
28
37
  [ReqRespBridgeEvent.outgoingRequest]: EventDirection.mainToWorker,
38
+ [ReqRespBridgeEvent.outgoingRequestCancel]: EventDirection.mainToWorker,
29
39
  [ReqRespBridgeEvent.outgoingResponse]: EventDirection.mainToWorker,
30
40
  [ReqRespBridgeEvent.incomingRequest]: EventDirection.workerToMain,
41
+ [ReqRespBridgeEvent.incomingRequestCancel]: EventDirection.workerToMain,
31
42
  [ReqRespBridgeEvent.incomingResponse]: EventDirection.workerToMain,
32
43
  };
33
44
 
@@ -36,8 +47,10 @@ export function getReqRespBridgeReqEvents(
36
47
  ): AsyncIterableEventBus<OutgoingRequestArgs, ResponseIncoming> {
37
48
  return {
38
49
  emitRequest: (data) => events.emit(ReqRespBridgeEvent.outgoingRequest, data),
50
+ emitRequestCancel: (data) => events.emit(ReqRespBridgeEvent.outgoingRequestCancel, data),
39
51
  emitResponse: (data) => events.emit(ReqRespBridgeEvent.incomingResponse, data),
40
52
  onRequest: (cb) => events.on(ReqRespBridgeEvent.outgoingRequest, cb),
53
+ onRequestCancel: (cb) => events.on(ReqRespBridgeEvent.outgoingRequestCancel, cb),
41
54
  onResponse: (cb) => events.on(ReqRespBridgeEvent.incomingResponse, cb),
42
55
  };
43
56
  }
@@ -47,8 +60,10 @@ export function getReqRespBridgeRespEvents(
47
60
  ): AsyncIterableEventBus<IncomingRequestArgs, ResponseOutgoing> {
48
61
  return {
49
62
  emitRequest: (data) => events.emit(ReqRespBridgeEvent.incomingRequest, data),
63
+ emitRequestCancel: (data) => events.emit(ReqRespBridgeEvent.incomingRequestCancel, data),
50
64
  emitResponse: (data) => events.emit(ReqRespBridgeEvent.outgoingResponse, data),
51
65
  onRequest: (cb) => events.on(ReqRespBridgeEvent.incomingRequest, cb),
66
+ onRequestCancel: (cb) => events.on(ReqRespBridgeEvent.incomingRequestCancel, cb),
52
67
  onResponse: (cb) => events.on(ReqRespBridgeEvent.outgoingResponse, cb),
53
68
  };
54
69
  }
@@ -1395,7 +1395,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
1395
1395
  const delaySec = chain.clock.secFromSlot(payloadAttestationMessage.data.slot, seenTimestampSec);
1396
1396
  metrics?.gossipPayloadAttestationMessage.elapsedTimeTillReceived.observe({source: OpSource.gossip}, delaySec);
1397
1397
  const nextSlotProposer = chain.getHeadState().getBeaconProposer(payloadAttestationMessage.data.slot + 1);
1398
- const isNextSlotProposer = chain.beaconProposerCache.get(nextSlotProposer) !== undefined;
1398
+ const isNextSlotProposer = chain.beaconProposerCache.has(nextSlotProposer);
1399
1399
 
1400
1400
  if (isNextSlotProposer) {
1401
1401
  try {
@@ -1,6 +1,6 @@
1
1
  import {TopicValidatorResult} from "@libp2p/gossipsub";
2
2
  import {routes} from "@lodestar/api";
3
- import {ForkSeq, NUMBER_OF_COLUMNS} from "@lodestar/params";
3
+ import {ForkSeq, NUMBER_OF_COLUMNS, isForkPostGloas} from "@lodestar/params";
4
4
  import {computeStartSlotAtEpoch} from "@lodestar/state-transition";
5
5
  import {RootHex, Slot, SlotRootHex} from "@lodestar/types";
6
6
  import {Logger, MapDef, mapValues, sleep} from "@lodestar/utils";
@@ -528,9 +528,9 @@ export class NetworkProcessor {
528
528
  const parentRoot = getParentRootFromSignedBeaconBlockSerialized(message.msg.data);
529
529
  if (parentRoot) {
530
530
  let search: SearchUnknownRootTarget | null = null;
531
- if (ForkSeq[fork] >= ForkSeq.gloas) {
531
+ if (isForkPostGloas(fork)) {
532
532
  // GLOAS: also check parent envelope, same logic as execution_payload_bid
533
- const parentBlockHash = getParentBlockHashFromGloasSignedBeaconBlockSerialized(message.msg.data);
533
+ const parentBlockHash = getParentBlockHashFromGloasSignedBeaconBlockSerialized(message.msg.data, fork);
534
534
  if (parentBlockHash && !this.chain.forkChoice.getBlockHexAndBlockHash(parentRoot, parentBlockHash)) {
535
535
  const protoBlock = this.chain.forkChoice.getBlockHexDefaultStatus(parentRoot);
536
536
  if (protoBlock === null) {
@@ -107,12 +107,12 @@ export const rateLimitQuotas: (fork: ForkName, config: BeaconConfig) => Record<R
107
107
  [ReqRespMethod.LightClientFinalityUpdate]: {
108
108
  // Finality updates should not be requested more than once per epoch.
109
109
  // Allow 2 per slot and a very safe bound until there's more testing of real usage.
110
- byPeer: {quota: 2, quotaTimeMs: 12_000},
110
+ byPeer: {quota: 2, quotaTimeMs: config.getSlotDurationMs(fork)},
111
111
  },
112
112
  [ReqRespMethod.LightClientOptimisticUpdate]: {
113
113
  // Optimistic updates should not be requested more than once per slot.
114
114
  // Allow 2 per slot and a very safe bound until there's more testing of real usage.
115
- byPeer: {quota: 2, quotaTimeMs: 12_000},
115
+ byPeer: {quota: 2, quotaTimeMs: config.getSlotDurationMs(fork)},
116
116
  },
117
117
  });
118
118
 
@@ -3,6 +3,7 @@ import {ATTESTATION_SUBNET_COUNT, SLOTS_PER_EPOCH} from "@lodestar/params";
3
3
  import {computeEpochAtSlot} from "@lodestar/state-transition";
4
4
  import {Epoch, Slot, SubnetID, ssz} from "@lodestar/types";
5
5
  import {Logger, MapDef} from "@lodestar/utils";
6
+ import {HALF_SLOT_BPS} from "../../constants/index.js";
6
7
  import {ClockEvent, IClock} from "../../util/clock.js";
7
8
  import {NetworkCoreMetrics} from "../core/metrics.js";
8
9
  import {getActiveForkBoundaries} from "../forks.js";
@@ -163,9 +164,13 @@ export class AttnetsService implements IAttnetsService {
163
164
  */
164
165
  private onSlot = (clockSlot: Slot): void => {
165
166
  try {
166
- setTimeout(() => {
167
- this.onHalfSlot(clockSlot);
168
- }, this.config.SLOT_DURATION_MS * 0.5);
167
+ const fork = this.config.getForkName(clockSlot);
168
+ setTimeout(
169
+ () => {
170
+ this.onHalfSlot(clockSlot);
171
+ },
172
+ this.config.getSlotComponentDurationMs(fork, HALF_SLOT_BPS)
173
+ );
169
174
 
170
175
  for (const [dutiedSlot, dutiedInfo] of this.aggregatorSlotSubnet.entries()) {
171
176
  if (dutiedSlot === clockSlot + this.opts.slotsToSubscribeBeforeAggregatorDuty) {
@@ -5,6 +5,7 @@ import {
5
5
  IBeaconStateView,
6
6
  computeEpochAtSlot,
7
7
  computeStartSlotAtEpoch,
8
+ computeTimeAtSlot,
8
9
  isStatePostBellatrix,
9
10
  } from "@lodestar/state-transition";
10
11
  import {Epoch} from "@lodestar/types";
@@ -140,21 +141,21 @@ export async function runNodeNotifier(modules: NodeNotifierModules): Promise<voi
140
141
  }
141
142
 
142
143
  function timeToNextHalfSlot(config: BeaconConfig, chain: IBeaconChain, isFirstTime: boolean): number {
143
- const msPerSlot = config.SLOT_DURATION_MS;
144
- const msPerHalfSlot = msPerSlot / 2;
145
- const msFromGenesis = Date.now() - chain.genesisTime * 1000;
146
- const msToNextSlot =
147
- msFromGenesis < 0
148
- ? // For future genesis time, calculate time left in the slot
149
- -msFromGenesis % msPerSlot
150
- : // For past genesis time, calculate time until the next slot
151
- msPerSlot - (msFromGenesis % msPerSlot);
144
+ const currentSlot = chain.clock.currentSlot;
145
+ const nextSlotTimeSec = computeTimeAtSlot(config, currentSlot + 1, chain.genesisTime);
146
+ const nowMs = Date.now();
147
+
152
148
  if (isFirstTime) {
153
- // at the 1st time we may miss middle of the current clock slot
154
- return msToNextSlot > msPerHalfSlot ? msToNextSlot - msPerHalfSlot : msToNextSlot + msPerHalfSlot;
149
+ const currentSlotTimeSec = computeTimeAtSlot(config, currentSlot, chain.genesisTime);
150
+ const currentMidpointMs = ((currentSlotTimeSec + nextSlotTimeSec) / 2) * 1000;
151
+ if (currentMidpointMs > nowMs) {
152
+ return currentMidpointMs - nowMs;
153
+ }
155
154
  }
156
- // after the 1st time always wait until middle of next clock slot
157
- return msToNextSlot + msPerHalfSlot;
155
+
156
+ const nextSlotEndTimeSec = computeTimeAtSlot(config, currentSlot + 2, chain.genesisTime);
157
+ const nextMidpointMs = ((nextSlotTimeSec + nextSlotEndTimeSec) / 2) * 1000;
158
+ return Math.max(0, nextMidpointMs - nowMs);
158
159
  }
159
160
 
160
161
  function getHeadExecutionInfo(
@@ -3,12 +3,14 @@ import {ArchiveMode, DEFAULT_ARCHIVE_MODE, IChainOptions, defaultChainOptions} f
3
3
  import {ValidatorMonitorOpts, defaultValidatorMonitorOpts} from "../chain/validatorMonitor.js";
4
4
  import {DatabaseOptions, defaultDbOptions} from "../db/options.js";
5
5
  import {
6
+ EngineApiMode,
6
7
  ExecutionBuilderOpts,
7
8
  ExecutionEngineOpts,
8
9
  defaultExecutionBuilderHttpOpts,
9
10
  defaultExecutionBuilderOpts,
10
11
  defaultExecutionEngineHttpOpts,
11
12
  defaultExecutionEngineOpts,
13
+ engineApiModes,
12
14
  } from "../execution/index.js";
13
15
  import {MetricsOptions, defaultMetricsOptions} from "../metrics/options.js";
14
16
  import {MonitoringOptions, defaultMonitoringOptions} from "../monitoring/options.js";
@@ -19,7 +21,14 @@ import {SyncOptions, defaultSyncOptions} from "../sync/options.js";
19
21
  export {allNamespaces} from "../api/rest/index.js";
20
22
 
21
23
  // Re-export to use as default values in CLI args
22
- export {defaultExecutionEngineHttpOpts, defaultExecutionBuilderHttpOpts, ArchiveMode, DEFAULT_ARCHIVE_MODE};
24
+ export {
25
+ defaultExecutionEngineHttpOpts,
26
+ defaultExecutionBuilderHttpOpts,
27
+ engineApiModes,
28
+ ArchiveMode,
29
+ DEFAULT_ARCHIVE_MODE,
30
+ };
31
+ export type {EngineApiMode};
23
32
 
24
33
  export interface IBeaconNodeOptions {
25
34
  api: ApiOptions;
@@ -918,16 +918,17 @@ export class BlockInputSync {
918
918
  * Poll unknown payloads of the current slot.
919
919
  */
920
920
  private async pollPayloadsAtSlot(slot: Slot, signal: AbortSignal): Promise<void> {
921
+ const fork = this.config.getForkName(slot);
921
922
  // fixed tick count so the loop cannot outlive its slot: for mainnet, it's 6 ticks
922
923
  const tickCount = Math.floor(
923
- (this.config.SLOT_DURATION_MS - this.config.getPayloadDueMs()) / PAYLOAD_POLL_INTERVAL_MS
924
+ (this.config.getSlotDurationMs(fork) - this.config.getPayloadDueMs(fork)) / PAYLOAD_POLL_INTERVAL_MS
924
925
  );
925
926
  // a root still missing on several ticks is searched on each of them, recorded once
926
927
  const searchedRoots = new Set<RootHex>();
927
928
  let polls = 0;
928
929
 
929
930
  try {
930
- await sleep(Math.max(0, this.config.getPayloadDueMs() - this.chain.clock.msFromSlot(slot)), signal);
931
+ await sleep(Math.max(0, this.config.getPayloadDueMs(fork) - this.chain.clock.msFromSlot(slot)), signal);
931
932
 
932
933
  for (polls = 0; polls < tickCount; polls++) {
933
934
  let importedCount = 0;
@@ -6,6 +6,10 @@ export type RequestEvent<T> = {
6
6
  id: number;
7
7
  };
8
8
 
9
+ export type RequestCancelEvent = {
10
+ id: number;
11
+ };
12
+
9
13
  export enum IteratorEventType {
10
14
  next = "iterator.next",
11
15
  done = "iterator.done",
@@ -19,8 +23,10 @@ export type IteratorEvent<V> =
19
23
 
20
24
  export type AsyncIterableEventBus<Args, Item> = {
21
25
  emitRequest(data: RequestEvent<Args>): void;
26
+ emitRequestCancel(data: RequestCancelEvent): void;
22
27
  emitResponse(data: IteratorEvent<Item>): void;
23
28
  onRequest(handler: (data: RequestEvent<Args>) => void): void;
29
+ onRequestCancel(handler: (data: RequestCancelEvent) => void): void;
24
30
  onResponse(handler: (data: IteratorEvent<Item>) => void): void;
25
31
  };
26
32
 
@@ -37,7 +43,9 @@ export class AsyncIterableBridgeCaller<Args, Item> {
37
43
  // TODO: Consider expiring the requests after no reply for long enough, t
38
44
  private readonly pending = new Map<number, PendingItem<Item>>();
39
45
 
40
- constructor(private readonly events: Pick<AsyncIterableEventBus<Args, Item>, "onResponse" | "emitRequest">) {
46
+ constructor(
47
+ private readonly events: Pick<AsyncIterableEventBus<Args, Item>, "onResponse" | "emitRequest" | "emitRequestCancel">
48
+ ) {
41
49
  events.onResponse(this.onResponse.bind(this));
42
50
  }
43
51
 
@@ -89,7 +97,10 @@ export class AsyncIterableBridgeCaller<Args, Item> {
89
97
 
90
98
  async return() {
91
99
  // This will be reached if the consumer called 'break' or 'return' early in the loop.
92
- self.pending.delete(id);
100
+ // Without the cancel the handler keeps producing items that cross the thread boundary just to be dropped
101
+ if (self.pending.delete(id)) {
102
+ self.events.emitRequestCancel({id});
103
+ }
93
104
  return {value: undefined, done: true};
94
105
  },
95
106
  };
@@ -132,20 +143,35 @@ export class AsyncIterableBridgeCaller<Args, Item> {
132
143
  }
133
144
 
134
145
  export class AsyncIterableBridgeHandler<Args, Item> {
146
+ private readonly iterators = new Map<number, AsyncIterator<Item>>();
147
+
135
148
  constructor(
136
- private readonly events: Pick<AsyncIterableEventBus<Args, Item>, "onRequest" | "emitResponse">,
149
+ private readonly events: Pick<AsyncIterableEventBus<Args, Item>, "onRequest" | "onRequestCancel" | "emitResponse">,
137
150
  private readonly handler: (args: Args) => AsyncIterable<Item>
138
151
  ) {
139
152
  events.onRequest(this.onRequest.bind(this));
153
+ events.onRequestCancel(this.onRequestCancel.bind(this));
154
+ }
155
+
156
+ get iteratingCount(): number {
157
+ return this.iterators.size;
140
158
  }
141
159
 
142
160
  private async onRequest(data: RequestEvent<Args>): Promise<void> {
143
161
  try {
144
- for await (const item of this.handler(data.callArgs)) {
162
+ const iterator = this.handler(data.callArgs)[Symbol.asyncIterator]();
163
+ this.iterators.set(data.id, iterator);
164
+
165
+ while (true) {
166
+ const result = await iterator.next();
167
+ if (result.done) {
168
+ break;
169
+ }
170
+
145
171
  this.events.emitResponse({
146
172
  type: IteratorEventType.next,
147
173
  id: data.id,
148
- item,
174
+ item: result.value,
149
175
  });
150
176
  }
151
177
 
@@ -159,6 +185,19 @@ export class AsyncIterableBridgeHandler<Args, Item> {
159
185
  id: data.id,
160
186
  error: toThreadBoundaryError(e as Error),
161
187
  });
188
+ } finally {
189
+ this.iterators.delete(data.id);
190
+ }
191
+ }
192
+
193
+ private onRequestCancel(data: RequestCancelEvent): void {
194
+ const iterator = this.iterators.get(data.id);
195
+ if (!iterator?.return) {
196
+ return;
162
197
  }
198
+
199
+ // An async generator queues return() behind the next() that is in flight, so at most one more
200
+ // item is produced before its finally blocks run. Any error surfaces through that next() call.
201
+ void iterator.return().catch(() => {});
163
202
  }
164
203
  }
package/src/util/clock.ts CHANGED
@@ -78,9 +78,9 @@ export class Clock extends EventEmitter implements IClock {
78
78
 
79
79
  this.config = config;
80
80
  this.genesisTime = genesisTime;
81
- this.timeoutId = setTimeout(this.onNextSlot, this.msUntilNextSlot());
82
81
  this.signal = signal;
83
82
  this._currentSlot = getCurrentSlot(this.config, this.genesisTime);
83
+ this.timeoutId = setTimeout(this.onNextSlot, this.msUntilNextSlot());
84
84
  this.signal.addEventListener("abort", () => clearTimeout(this.timeoutId), {once: true});
85
85
  }
86
86
 
@@ -204,8 +204,7 @@ export class Clock extends EventEmitter implements IClock {
204
204
  };
205
205
 
206
206
  private msUntilNextSlot(): number {
207
- const milliSecondsPerSlot = this.config.SLOT_DURATION_MS;
208
- const diffInMilliSeconds = Date.now() - this.genesisTime * 1000;
209
- return milliSecondsPerSlot - (diffInMilliSeconds % milliSecondsPerSlot);
207
+ const nextSlotTimeSec = computeTimeAtSlot(this.config, this._currentSlot + 1, this.genesisTime);
208
+ return Math.max(0, nextSlotTimeSec * 1000 - Date.now());
210
209
  }
211
210
  }
@@ -6,7 +6,8 @@ export function getLodestarClientVersion(info?: {version?: string; commit?: stri
6
6
  code: ClientCode.LS,
7
7
  name: "Lodestar",
8
8
  version: info?.version ?? "",
9
- commit: info?.commit?.slice(0, 8) ?? "",
9
+ // engine_getClientVersionV1 defines commit as 4 bytes, so builds without git data must not send an empty one
10
+ commit: info?.commit ? info.commit.slice(0, 8) : "00000000",
10
11
  };
11
12
  }
12
13
 
@@ -6,10 +6,12 @@ import {
6
6
  FIELD_ELEMENTS_PER_BLOB,
7
7
  ForkName,
8
8
  ForkPostDeneb,
9
+ ForkPostGloas,
9
10
  ForkSeq,
10
11
  MAX_COMMITTEES_PER_SLOT,
11
12
  isForkPostElectra,
12
13
  isForkPostGloas,
14
+ isForkPostHeze,
13
15
  } from "@lodestar/params";
14
16
  import {BLSSignature, CommitteeIndex, RootHex, Slot, ValidatorIndex, ssz} from "@lodestar/types";
15
17
 
@@ -57,6 +59,8 @@ const ATTESTATION_DATA_SIZE = 128;
57
59
  // MAX_COMMITTEES_PER_SLOT is in bit, need to convert to byte
58
60
  const COMMITTEE_BITS_SIZE = Math.max(Math.ceil(MAX_COMMITTEES_PER_SLOT / 8), 1);
59
61
  const SIGNATURE_SIZE = 96;
62
+ // SyncAggregate is a fixed-size container, so minSize is its serialized size
63
+ const SYNC_AGGREGATE_SIZE = ssz.altair.SyncAggregate.minSize;
60
64
  const SINGLE_ATTESTATION_ATTDATA_OFFSET = 8 + 8;
61
65
  const SINGLE_ATTESTATION_SLOT_OFFSET = SINGLE_ATTESTATION_ATTDATA_OFFSET;
62
66
  const SINGLE_ATTESTATION_COMMITTEE_INDEX_OFFSET = 0;
@@ -447,30 +451,39 @@ export function getParentRootFromSignedBeaconBlockSerialized(data: Uint8Array):
447
451
  * BeaconBlockBody (GLOAS) fixed section before signedExecutionPayloadBid offset pointer:
448
452
  * randaoReveal(96) + eth1Data(72) + graffiti(32)
449
453
  * + proposerSlashings(4) + attesterSlashings(4) + attestations(4) + deposits(4) + voluntaryExits(4)
450
- * + syncAggregate(160) + blsToExecutionChanges(4) = 384 bytes
454
+ * + syncAggregate(SyncAggregate.minSize) + blsToExecutionChanges(4) = 384 bytes (mainnet preset)
451
455
  *
452
- * The 4-byte pointer at byte 568 (= 184+384) gives the offset of SignedExecutionPayloadBid
456
+ * Heze body: randaoReveal(96) + graffiti(32) + proposerSlashings(4) + attesterSlashings(4) + attestations(4) + voluntaryExits(4) + syncAggregate(SyncAggregate.minSize) + blsToExecutionChanges(4) = 308 bytes (mainnet preset)
457
+ *
458
+ * The 4-byte pointer at byte 568 (= 184+384) for Gloas and 492 (= 184+308) for Heze (mainnet preset) gives the offset of SignedExecutionPayloadBid
453
459
  * within BeaconBlockBody. parentBlockHash is at that bid's byte 100 (after offset+sig).
454
460
  */
455
461
  // BeaconBlock body starts after: msg_offset(4) + sig(96) + slot(8) + proposer_index(8) + parent_root(32) + state_root(32) + body_offset_ptr(4)
456
462
  const GLOAS_BODY_START_IN_SIGNED_BEACON_BLOCK =
457
463
  VARIABLE_FIELD_OFFSET + SIGNATURE_SIZE + SLOT_SIZE + 8 + ROOT_SIZE + ROOT_SIZE + VARIABLE_FIELD_OFFSET; // = 184
458
- const GLOAS_SIGNED_BID_OFFSET_POINTER_IN_BODY = 96 + 72 + 32 + 4 + 4 + 4 + 4 + 4 + 160 + 4; // = 384
459
- const GLOAS_SIGNED_BID_OFFSET_POINTER_IN_SIGNED_BEACON_BLOCK =
460
- GLOAS_BODY_START_IN_SIGNED_BEACON_BLOCK + GLOAS_SIGNED_BID_OFFSET_POINTER_IN_BODY; // = 568
464
+ const GLOAS_SIGNED_BID_OFFSET_POINTER_IN_BODY = 96 + 72 + 32 + 4 + 4 + 4 + 4 + 4 + SYNC_AGGREGATE_SIZE + 4; // = 384 at mainnet preset
465
+ // Heze removes eth1Data (72 B) and the deposits offset (4 B) from the body fixed section
466
+ const HEZE_SIGNED_BID_OFFSET_POINTER_IN_BODY = GLOAS_SIGNED_BID_OFFSET_POINTER_IN_BODY - 72 - VARIABLE_FIELD_OFFSET; // = 308
461
467
  // Within SignedExecutionPayloadBid, parentBlockHash is at byte 100 (msg_offset:4 + sig:96)
462
468
  const PARENT_BLOCK_HASH_OFFSET_IN_SIGNED_BID = VARIABLE_FIELD_OFFSET + SIGNATURE_SIZE; // = 100
463
469
 
464
- // CAUTION: update offsets if BeaconBlockBody fixed fields change after Gloas
465
- export function getParentBlockHashFromGloasSignedBeaconBlockSerialized(data: Uint8Array): RootHex | null {
466
- if (data.length < GLOAS_SIGNED_BID_OFFSET_POINTER_IN_SIGNED_BEACON_BLOCK + VARIABLE_FIELD_OFFSET) {
470
+ // CAUTION: update offsets if BeaconBlockBody fixed fields change after Heze
471
+ export function getParentBlockHashFromGloasSignedBeaconBlockSerialized(
472
+ data: Uint8Array,
473
+ fork: ForkPostGloas
474
+ ): RootHex | null {
475
+ const bidOffsetPointer =
476
+ GLOAS_BODY_START_IN_SIGNED_BEACON_BLOCK +
477
+ (isForkPostHeze(fork) ? HEZE_SIGNED_BID_OFFSET_POINTER_IN_BODY : GLOAS_SIGNED_BID_OFFSET_POINTER_IN_BODY);
478
+ if (data.length < bidOffsetPointer + VARIABLE_FIELD_OFFSET) {
467
479
  return null;
468
480
  }
469
481
  const bidOffset =
470
- data[GLOAS_SIGNED_BID_OFFSET_POINTER_IN_SIGNED_BEACON_BLOCK] |
471
- (data[GLOAS_SIGNED_BID_OFFSET_POINTER_IN_SIGNED_BEACON_BLOCK + 1] << 8) |
472
- (data[GLOAS_SIGNED_BID_OFFSET_POINTER_IN_SIGNED_BEACON_BLOCK + 2] << 16) |
473
- (data[GLOAS_SIGNED_BID_OFFSET_POINTER_IN_SIGNED_BEACON_BLOCK + 3] << 24);
482
+ (data[bidOffsetPointer] |
483
+ (data[bidOffsetPointer + 1] << 8) |
484
+ (data[bidOffsetPointer + 2] << 16) |
485
+ (data[bidOffsetPointer + 3] << 24)) >>>
486
+ 0;
474
487
 
475
488
  const parentBlockHashStart =
476
489
  GLOAS_BODY_START_IN_SIGNED_BEACON_BLOCK + bidOffset + PARENT_BLOCK_HASH_OFFSET_IN_SIGNED_BID;