@lodestar/beacon-node 1.50.0-dev.c3aaeedc3b → 1.50.0-dev.c785f2463a

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 (255) 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 +20 -11
  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 +31 -63
  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/range/batch.d.ts +5 -5
  166. package/lib/sync/range/batch.d.ts.map +1 -1
  167. package/lib/sync/range/batch.js +11 -17
  168. package/lib/sync/range/batch.js.map +1 -1
  169. package/lib/sync/range/chain.d.ts +4 -4
  170. package/lib/sync/range/chain.d.ts.map +1 -1
  171. package/lib/sync/range/chain.js +7 -5
  172. package/lib/sync/range/chain.js.map +1 -1
  173. package/lib/sync/range/range.d.ts.map +1 -1
  174. package/lib/sync/range/range.js +25 -11
  175. package/lib/sync/range/range.js.map +1 -1
  176. package/lib/sync/unknownBlock.d.ts +5 -2
  177. package/lib/sync/unknownBlock.d.ts.map +1 -1
  178. package/lib/sync/unknownBlock.js +47 -22
  179. package/lib/sync/unknownBlock.js.map +1 -1
  180. package/lib/sync/utils/downloadByRange.d.ts +38 -14
  181. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  182. package/lib/sync/utils/downloadByRange.js +84 -39
  183. package/lib/sync/utils/downloadByRange.js.map +1 -1
  184. package/lib/util/asyncIterableToEvents.d.ts +10 -2
  185. package/lib/util/asyncIterableToEvents.d.ts.map +1 -1
  186. package/lib/util/asyncIterableToEvents.js +29 -3
  187. package/lib/util/asyncIterableToEvents.js.map +1 -1
  188. package/lib/util/clock.d.ts.map +1 -1
  189. package/lib/util/clock.js +3 -4
  190. package/lib/util/clock.js.map +1 -1
  191. package/lib/util/metadata.d.ts.map +1 -1
  192. package/lib/util/metadata.js +2 -1
  193. package/lib/util/metadata.js.map +1 -1
  194. package/lib/util/sszBytes.d.ts +2 -2
  195. package/lib/util/sszBytes.d.ts.map +1 -1
  196. package/lib/util/sszBytes.js +22 -14
  197. package/lib/util/sszBytes.js.map +1 -1
  198. package/package.json +16 -15
  199. package/src/api/impl/beacon/blocks/index.ts +10 -3
  200. package/src/api/impl/beacon/state/index.ts +13 -4
  201. package/src/api/impl/validator/index.ts +78 -19
  202. package/src/chain/ColumnReconstructionTracker.ts +4 -6
  203. package/src/chain/beaconProposerCache.ts +19 -1
  204. package/src/chain/blocks/blockInput/blockInput.ts +1 -1
  205. package/src/chain/blocks/importBlock.ts +24 -10
  206. package/src/chain/blocks/verifyBlock.ts +7 -6
  207. package/src/chain/chain.ts +62 -17
  208. package/src/chain/interface.ts +4 -1
  209. package/src/chain/opPools/opPool.ts +1 -31
  210. package/src/chain/opPools/proposerPreferencesPool.ts +20 -1
  211. package/src/chain/opPools/utils.ts +31 -0
  212. package/src/chain/prepareNextSlot.ts +22 -6
  213. package/src/chain/produceBlock/computeNewStateRoot.ts +9 -2
  214. package/src/chain/produceBlock/produceBlockBody.ts +78 -39
  215. package/src/chain/reprocess.ts +2 -1
  216. package/src/chain/seenCache/seenGossipBlockInput.ts +2 -1
  217. package/src/chain/shufflingCache.ts +79 -22
  218. package/src/chain/stateCache/persistentCheckpointsCache.ts +4 -1
  219. package/src/chain/validatorMonitor.ts +7 -4
  220. package/src/constants/constants.ts +1 -0
  221. package/src/db/beacon.ts +3 -0
  222. package/src/db/buckets.ts +1 -0
  223. package/src/db/interface.ts +2 -0
  224. package/src/db/repositories/blockArchive.ts +2 -2
  225. package/src/db/repositories/blockArchiveIndex.ts +2 -3
  226. package/src/db/repositories/index.ts +1 -0
  227. package/src/db/repositories/proposerPreferences.ts +23 -0
  228. package/src/execution/engine/blobVersionedHashes.ts +72 -0
  229. package/src/execution/engine/http.ts +304 -271
  230. package/src/execution/engine/index.ts +41 -7
  231. package/src/execution/engine/interface.ts +1 -1
  232. package/src/execution/engine/jsonRpcTransport.ts +247 -0
  233. package/src/execution/engine/restHttpClient.ts +269 -0
  234. package/src/execution/engine/restTransport.ts +544 -0
  235. package/src/execution/engine/sszTypes.ts +354 -0
  236. package/src/execution/engine/transport.ts +61 -0
  237. package/src/execution/engine/types.ts +42 -80
  238. package/src/execution/engine/utils.ts +12 -2
  239. package/src/metrics/metrics/lodestar.ts +19 -0
  240. package/src/network/core/events.ts +16 -1
  241. package/src/network/processor/gossipHandlers.ts +1 -1
  242. package/src/network/processor/index.ts +3 -3
  243. package/src/network/reqresp/rateLimit.ts +2 -2
  244. package/src/network/subnets/attnetsService.ts +8 -3
  245. package/src/node/notifier.ts +14 -13
  246. package/src/node/options.ts +10 -1
  247. package/src/sync/range/batch.ts +14 -19
  248. package/src/sync/range/chain.ts +9 -7
  249. package/src/sync/range/range.ts +26 -12
  250. package/src/sync/unknownBlock.ts +60 -23
  251. package/src/sync/utils/downloadByRange.ts +123 -58
  252. package/src/util/asyncIterableToEvents.ts +44 -5
  253. package/src/util/clock.ts +3 -4
  254. package/src/util/metadata.ts +2 -1
  255. package/src/util/sszBytes.ts +25 -12
@@ -20,6 +20,7 @@ import {InsertOutcome} from "../../chain/opPools/types.js";
20
20
  import {RegenCaller, RegenFnName} from "../../chain/regen/interface.js";
21
21
  import {ReprocessStatus} from "../../chain/reprocess.js";
22
22
  import {RejectReason} from "../../chain/seenCache/seenAttestationData.js";
23
+ import type {ShufflingPromiseCancelReason} from "../../chain/shufflingCache.js";
23
24
  import {CacheItemType} from "../../chain/stateCache/types.js";
24
25
  import {OpSource} from "../../chain/validatorMonitor.js";
25
26
  import type {FlatFileStoreOperation} from "../../db/flatFileStore/metrics.js";
@@ -1176,6 +1177,11 @@ export function createLodestarMetrics(
1176
1177
  help: "The total result of calling notifyForkchoiceUpdate execution engine api",
1177
1178
  labelNames: ["result"],
1178
1179
  }),
1180
+ engineApiRequests: register.counter<{transport: string}>({
1181
+ name: "lodestar_execution_engine_api_requests_total",
1182
+ help: "Total engine API requests by transport",
1183
+ labelNames: ["transport"],
1184
+ }),
1179
1185
  opPool: {
1180
1186
  aggregatedAttestationPool: {
1181
1187
  size: register.gauge({
@@ -1618,6 +1624,19 @@ export function createLodestarMetrics(
1618
1624
  name: "lodestar_shuffling_cache_size",
1619
1625
  help: "Shuffling cache size",
1620
1626
  }),
1627
+ epochs: register.gauge({
1628
+ name: "lodestar_shuffling_cache_epochs",
1629
+ help: "Number of epochs in shuffling cache",
1630
+ }),
1631
+ prunedShufflings: register.counter({
1632
+ name: "lodestar_shuffling_cache_pruned_shufflings_total",
1633
+ help: "Total number of shufflings pruned from shuffling cache",
1634
+ }),
1635
+ cancelledPromises: register.counter<{reason: ShufflingPromiseCancelReason}>({
1636
+ name: "lodestar_shuffling_cache_cancelled_promises_total",
1637
+ help: "Total number of shuffling promises resolved with null",
1638
+ labelNames: ["reason"],
1639
+ }),
1621
1640
  insertPromiseCount: register.gauge({
1622
1641
  name: "lodestar_shuffling_cache_insert_promise_count",
1623
1642
  help: "Total number of times insertPromise is called",
@@ -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;
@@ -14,7 +14,7 @@ import {IClock} from "../../util/clock.js";
14
14
  import {CustodyConfig} from "../../util/dataColumns.js";
15
15
  import {PeerIdStr} from "../../util/peerId.js";
16
16
  import {MAX_BATCH_DOWNLOAD_ATTEMPTS, MAX_BATCH_PROCESSING_ATTEMPTS} from "../constants.js";
17
- import {DownloadByRangeRequests, ParentPayloadCommitments} from "../utils/downloadByRange.js";
17
+ import {DownloadByRangeRequests, ParentPayload} from "../utils/downloadByRange.js";
18
18
  import {getBatchSlotRange, hashBlocks} from "./utils/index.js";
19
19
 
20
20
  /**
@@ -175,7 +175,7 @@ export class Batch {
175
175
  private readonly clock: IClock;
176
176
  private readonly custodyConfig: CustodyConfig;
177
177
  private readonly isFirstBatchInChain: boolean;
178
- private readonly latestBid: gloas.ExecutionPayloadBid | undefined;
178
+ private readonly parentPayload: ParentPayload | undefined;
179
179
 
180
180
  constructor(
181
181
  startEpoch: Epoch,
@@ -183,7 +183,7 @@ export class Batch {
183
183
  clock: IClock,
184
184
  custodyConfig: CustodyConfig,
185
185
  isFirstBatchInChain: boolean,
186
- latestBid: gloas.ExecutionPayloadBid | undefined,
186
+ parentPayload: ParentPayload | undefined,
187
187
  targetSlot: Slot
188
188
  ) {
189
189
  this.config = config;
@@ -196,7 +196,7 @@ export class Batch {
196
196
  this.startSlot = startSlot;
197
197
  this.count = Math.min(count, targetSlot - startSlot + 1);
198
198
  this.isFirstBatchInChain = isFirstBatchInChain;
199
- this.latestBid = latestBid;
199
+ this.parentPayload = parentPayload;
200
200
  this.requests = this.getRequests([]);
201
201
  }
202
202
 
@@ -208,24 +208,19 @@ export class Batch {
208
208
  }
209
209
 
210
210
  // we only know if we should download parent envelope if firstBlock is downloaded
211
- if (firstBlock === undefined) return false;
212
- if (this.latestBid === undefined) return false;
213
- const firstBlockBidParentHash = (firstBlock.message.body as gloas.BeaconBlockBody).signedExecutionPayloadBid.message
214
- .parentBlockHash;
215
- return byteArrayEquals(firstBlockBidParentHash, this.latestBid.blockHash);
211
+ if (firstBlock === undefined || this.parentPayload === undefined) return false;
212
+ const firstBlockBid = (firstBlock.message.body as gloas.BeaconBlockBody).signedExecutionPayloadBid.message;
213
+ return (
214
+ byteArrayEquals(firstBlock.message.parentRoot, this.parentPayload.blockRoot) &&
215
+ byteArrayEquals(firstBlockBid.parentBlockHash, this.parentPayload.bid.blockHash)
216
+ );
216
217
  }
217
218
 
218
- getParentPayloadCommitments(parentBlockRoot: Uint8Array): ParentPayloadCommitments {
219
- if (this.latestBid === undefined) {
220
- throw new Error(
221
- `Coding error: getParentPayloadCommitments called without latestBid for parentBlockRoot=${toRootHex(parentBlockRoot)}`
222
- );
219
+ getParentPayload(): ParentPayload {
220
+ if (this.parentPayload === undefined) {
221
+ throw new Error("Coding error: getParentPayload called without parentPayload");
223
222
  }
224
- return {
225
- blockRoot: parentBlockRoot,
226
- blockRootHex: toRootHex(parentBlockRoot),
227
- kzgCommitments: this.latestBid.blobKzgCommitments,
228
- };
223
+ return this.parentPayload;
229
224
  }
230
225
 
231
226
  /**
@@ -1,5 +1,5 @@
1
1
  import {ChainForkConfig} from "@lodestar/config";
2
- import {Epoch, Root, Slot, gloas} from "@lodestar/types";
2
+ import {Epoch, Root, Slot} from "@lodestar/types";
3
3
  import {ErrorAborted, LodestarError, Logger, prettyPrintIndices, toRootHex} from "@lodestar/utils";
4
4
  import {isBlockInputBlobs, isBlockInputColumns} from "../../chain/blocks/blockInput/blockInput.js";
5
5
  import {BlockInputErrorCode} from "../../chain/blocks/blockInput/errors.js";
@@ -16,7 +16,7 @@ import {ItTrigger} from "../../util/itTrigger.js";
16
16
  import {PeerIdStr} from "../../util/peerId.js";
17
17
  import {WarnResult, wrapError} from "../../util/wrapError.js";
18
18
  import {BATCH_BUFFER_SIZE, EPOCHS_PER_BATCH, MAX_LOOK_AHEAD_EPOCHS} from "../constants.js";
19
- import {DownloadByRangeError, DownloadByRangeErrorCode} from "../utils/downloadByRange.js";
19
+ import {DownloadByRangeError, DownloadByRangeErrorCode, ParentPayload} from "../utils/downloadByRange.js";
20
20
  import {getRateLimitedUntilMs} from "../utils/rateLimit.js";
21
21
  import {RangeSyncType} from "../utils/remoteSyncType.js";
22
22
  import {Batch, BatchError, BatchErrorCode, BatchMetadata, BatchStatus} from "./batch.js";
@@ -160,7 +160,7 @@ export class SyncChain {
160
160
  private readonly clock: IClock;
161
161
  private readonly metrics: Metrics | null;
162
162
  private readonly custodyConfig: CustodyConfig;
163
- private readonly latestBid: gloas.ExecutionPayloadBid | undefined;
163
+ private readonly parentPayload: ParentPayload | undefined;
164
164
 
165
165
  constructor(
166
166
  initialBatchEpoch: Epoch,
@@ -168,7 +168,7 @@ export class SyncChain {
168
168
  syncType: RangeSyncType,
169
169
  fns: SyncChainFns,
170
170
  modules: SyncChainModules,
171
- latestBid: gloas.ExecutionPayloadBid | undefined
171
+ parentPayload: ParentPayload | undefined
172
172
  ) {
173
173
  const {config, clock, custodyConfig, logger, metrics} = modules;
174
174
  this.firstBatchEpoch = initialBatchEpoch;
@@ -184,7 +184,7 @@ export class SyncChain {
184
184
  this.clock = clock;
185
185
  this.metrics = metrics;
186
186
  this.custodyConfig = custodyConfig;
187
- this.latestBid = latestBid;
187
+ this.parentPayload = parentPayload;
188
188
  this.logger = logger;
189
189
  this.logId = `${syncType}-${nextChainId++}`;
190
190
 
@@ -536,8 +536,8 @@ export class SyncChain {
536
536
  this.clock,
537
537
  this.custodyConfig,
538
538
  this.isFirstBatch,
539
- // `latestBid` is only meaningful for the first batch's parent-payload check
540
- this.isFirstBatch ? this.latestBid : undefined,
539
+ // `parentPayload` is only meaningful for the first batch
540
+ this.isFirstBatch ? this.parentPayload : undefined,
541
541
  this.target.slot
542
542
  );
543
543
  this.isFirstBatch = false;
@@ -586,6 +586,8 @@ export class SyncChain {
586
586
  case DownloadByRangeErrorCode.OUT_OF_RANGE_BLOCKS:
587
587
  case DownloadByRangeErrorCode.PARENT_ROOT_MISMATCH:
588
588
  case DownloadByRangeErrorCode.INVALID_ENVELOPE_BEACON_BLOCK_ROOT:
589
+ case DownloadByRangeErrorCode.INVALID_ENVELOPE_BLOCK_HASH:
590
+ case DownloadByRangeErrorCode.INVALID_ENVELOPE_SLOT:
589
591
  case DownloadByRangeErrorCode.INVALID_CHAIN_SEGMENT:
590
592
  case BlobSidecarErrorCode.INCLUSION_PROOF_INVALID:
591
593
  case BlobSidecarErrorCode.INVALID_KZG_PROOF_BATCH:
@@ -2,8 +2,8 @@ import {EventEmitter} from "node:events";
2
2
  import {StrictEventEmitter} from "strict-event-emitter-types";
3
3
  import {BeaconConfig} from "@lodestar/config";
4
4
  import {IBeaconStateViewGloas, computeStartSlotAtEpoch, isStatePostGloas} from "@lodestar/state-transition";
5
- import {Epoch, Status, fulu} from "@lodestar/types";
6
- import {Logger, prettyPrintIndices, toRootHex} from "@lodestar/utils";
5
+ import {Epoch, Status, fulu, ssz} from "@lodestar/types";
6
+ import {Logger, byteArrayEquals, prettyPrintIndices, toRootHex} from "@lodestar/utils";
7
7
  import {IBlockInput} from "../../chain/blocks/blockInput/types.js";
8
8
  import {PayloadError, PayloadErrorCode} from "../../chain/blocks/importExecutionPayload.js";
9
9
  import {AttestationImportOpt, ImportBlockOpts} from "../../chain/blocks/index.js";
@@ -16,6 +16,7 @@ import {PeerIdStr} from "../../util/peerId.js";
16
16
  import {
17
17
  DownloadByRangeError,
18
18
  DownloadByRangeErrorCode,
19
+ ParentPayload,
19
20
  cacheByRangeResponses,
20
21
  downloadByRange,
21
22
  } from "../utils/downloadByRange.js";
@@ -278,15 +279,14 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
278
279
  private downloadByRange: SyncChainFns["downloadByRange"] = async (peer, batch) => {
279
280
  const batchBlocks = batch.getBlocks();
280
281
  const requests = batch.getRequestsForPeer(peer);
281
- const parentRoot = requests.parentPayloadRequest?.envelopeBlockRoot ?? requests.parentPayloadRequest?.blockRoot;
282
- const parentPayloadCommitments = parentRoot ? batch.getParentPayloadCommitments(parentRoot) : undefined;
282
+ const parentPayload = requests.parentPayloadRequest ? batch.getParentPayload() : undefined;
283
283
  const {result, warnings} = await downloadByRange({
284
284
  config: this.config,
285
285
  network: this.network,
286
286
  logger: this.logger,
287
287
  peerIdStr: peer.peerId,
288
288
  batchBlocks,
289
- parentPayloadCommitments,
289
+ parentPayload,
290
290
  peerDasMetrics: this.chain.metrics?.peerDas,
291
291
  ...requests,
292
292
  });
@@ -299,6 +299,7 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
299
299
  batchBlocks,
300
300
  downloadedPayloadEnvelopes,
301
301
  existingPayloadEnvelopes: batch.getPayloadEnvelopes(),
302
+ parentPayload,
302
303
  custodyConfig: this.chain.custodyConfig,
303
304
  seenTimestampSec: Date.now() / 1000,
304
305
  });
@@ -376,13 +377,26 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
376
377
  private addPeerOrCreateChain(startEpoch: Epoch, target: ChainTarget, peer: PeerIdStr, syncType: RangeSyncType): void {
377
378
  let syncChain = this.chains.get(syncType);
378
379
  if (!syncChain) {
379
- // The first batch of a new sync chain may need to detect whether the parent block was an
380
- // gloas "empty" block (no envelope produced). It does so by comparing the first
381
- // downloaded block's `bid.parentBlockHash` against the head state's `latestExecutionPayloadBid.blockHash`.
380
+ // The first block of the first batch may build on the head's FULL variant before its payload is imported,
381
+ // the batch then downloads the head's payload as dangling parent and validates it against the bid
382
382
  const headState = this.chain.getHeadState();
383
- const latestBid = isStatePostGloas(headState)
384
- ? (headState as IBeaconStateViewGloas).latestExecutionPayloadBid
385
- : undefined;
383
+ let parentPayload: ParentPayload | undefined;
384
+ if (isStatePostGloas(headState) && headState.latestBlockHeader.slot > 0) {
385
+ const header = ssz.phase0.BeaconBlockHeader.clone(headState.latestBlockHeader);
386
+ if (byteArrayEquals(header.stateRoot, ssz.Root.defaultValue())) {
387
+ header.stateRoot = headState.hashTreeRoot();
388
+ }
389
+ const headRoot = ssz.phase0.BeaconBlockHeader.hashTreeRoot(header);
390
+ const headSlot = headState.latestBlockHeader.slot;
391
+ parentPayload = {
392
+ blockRoot: headRoot,
393
+ blockRootHex: toRootHex(headRoot),
394
+ slot: headSlot,
395
+ proposerIndex: headState.latestBlockHeader.proposerIndex,
396
+ forkName: this.config.getForkName(headSlot),
397
+ bid: (headState as IBeaconStateViewGloas).latestExecutionPayloadBid,
398
+ };
399
+ }
386
400
 
387
401
  syncChain = new SyncChain(
388
402
  startEpoch,
@@ -403,7 +417,7 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
403
417
  custodyConfig: this.chain.custodyConfig,
404
418
  metrics: this.metrics,
405
419
  },
406
- latestBid
420
+ parentPayload
407
421
  );
408
422
  this.chains.set(syncType, syncChain);
409
423