@lodestar/beacon-node 1.50.0-dev.fd4f342a40 → 1.50.0-dev.fe4e7408b4

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 (333) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +13 -3
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/beacon/index.d.ts.map +1 -1
  5. package/lib/api/impl/beacon/index.js +13 -0
  6. package/lib/api/impl/beacon/index.js.map +1 -1
  7. package/lib/api/impl/beacon/state/index.d.ts.map +1 -1
  8. package/lib/api/impl/beacon/state/index.js +28 -6
  9. package/lib/api/impl/beacon/state/index.js.map +1 -1
  10. package/lib/api/impl/debug/index.d.ts.map +1 -1
  11. package/lib/api/impl/debug/index.js +26 -18
  12. package/lib/api/impl/debug/index.js.map +1 -1
  13. package/lib/api/impl/validator/index.d.ts +1 -0
  14. package/lib/api/impl/validator/index.d.ts.map +1 -1
  15. package/lib/api/impl/validator/index.js +65 -4
  16. package/lib/api/impl/validator/index.js.map +1 -1
  17. package/lib/chain/archiveStore/archiveStore.d.ts +5 -0
  18. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  19. package/lib/chain/archiveStore/archiveStore.js +14 -24
  20. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  21. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts +2 -2
  22. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
  23. package/lib/chain/archiveStore/historicalState/getHistoricalState.js +5 -7
  24. package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
  25. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -1
  26. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
  27. package/lib/chain/archiveStore/historicalState/types.d.ts +2 -2
  28. package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
  29. package/lib/chain/archiveStore/historicalState/worker.js +1 -1
  30. package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
  31. package/lib/chain/archiveStore/interface.d.ts +1 -1
  32. package/lib/chain/archiveStore/interface.d.ts.map +1 -1
  33. package/lib/chain/archiveStore/utils/pruneHistory.d.ts +1 -1
  34. package/lib/chain/archiveStore/utils/pruneHistory.d.ts.map +1 -1
  35. package/lib/chain/archiveStore/utils/pruneHistory.js +2 -1
  36. package/lib/chain/archiveStore/utils/pruneHistory.js.map +1 -1
  37. package/lib/chain/beaconProposerCache.d.ts +6 -0
  38. package/lib/chain/beaconProposerCache.d.ts.map +1 -1
  39. package/lib/chain/beaconProposerCache.js +16 -0
  40. package/lib/chain/beaconProposerCache.js.map +1 -1
  41. package/lib/chain/blocks/blockInput/blockInput.d.ts +1 -1
  42. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  43. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  44. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  45. package/lib/chain/blocks/importBlock.js +14 -8
  46. package/lib/chain/blocks/importBlock.js.map +1 -1
  47. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  48. package/lib/chain/blocks/verifyBlock.js +7 -7
  49. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  50. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts +2 -1
  51. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts.map +1 -1
  52. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js +5 -4
  53. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js.map +1 -1
  54. package/lib/chain/chain.d.ts +10 -5
  55. package/lib/chain/chain.d.ts.map +1 -1
  56. package/lib/chain/chain.js +102 -33
  57. package/lib/chain/chain.js.map +1 -1
  58. package/lib/chain/emitter.d.ts +7 -1
  59. package/lib/chain/emitter.d.ts.map +1 -1
  60. package/lib/chain/emitter.js +5 -0
  61. package/lib/chain/emitter.js.map +1 -1
  62. package/lib/chain/errors/envelopeReconstructionError.d.ts +5 -0
  63. package/lib/chain/errors/envelopeReconstructionError.d.ts.map +1 -1
  64. package/lib/chain/errors/envelopeReconstructionError.js +2 -0
  65. package/lib/chain/errors/envelopeReconstructionError.js.map +1 -1
  66. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  67. package/lib/chain/forkChoice/index.js +2 -0
  68. package/lib/chain/forkChoice/index.js.map +1 -1
  69. package/lib/chain/interface.d.ts +6 -3
  70. package/lib/chain/interface.d.ts.map +1 -1
  71. package/lib/chain/opPools/aggregatedAttestationPool.d.ts +4 -2
  72. package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
  73. package/lib/chain/opPools/aggregatedAttestationPool.js +30 -8
  74. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  75. package/lib/chain/opPools/opPool.d.ts.map +1 -1
  76. package/lib/chain/opPools/opPool.js +1 -23
  77. package/lib/chain/opPools/opPool.js.map +1 -1
  78. package/lib/chain/opPools/proposerPreferencesPool.d.ts +8 -4
  79. package/lib/chain/opPools/proposerPreferencesPool.d.ts.map +1 -1
  80. package/lib/chain/opPools/proposerPreferencesPool.js +27 -12
  81. package/lib/chain/opPools/proposerPreferencesPool.js.map +1 -1
  82. package/lib/chain/opPools/utils.d.ts +11 -0
  83. package/lib/chain/opPools/utils.d.ts.map +1 -1
  84. package/lib/chain/opPools/utils.js +22 -0
  85. package/lib/chain/opPools/utils.js.map +1 -1
  86. package/lib/chain/options.d.ts +2 -1
  87. package/lib/chain/options.d.ts.map +1 -1
  88. package/lib/chain/options.js +1 -1
  89. package/lib/chain/options.js.map +1 -1
  90. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  91. package/lib/chain/prepareNextSlot.js +11 -3
  92. package/lib/chain/prepareNextSlot.js.map +1 -1
  93. package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
  94. package/lib/chain/produceBlock/computeNewStateRoot.js +1 -1
  95. package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
  96. package/lib/chain/produceBlock/produceBlockBody.d.ts +8 -0
  97. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  98. package/lib/chain/produceBlock/produceBlockBody.js +48 -34
  99. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  100. package/lib/chain/regen/regen.d.ts +2 -0
  101. package/lib/chain/regen/regen.d.ts.map +1 -1
  102. package/lib/chain/regen/regen.js +10 -4
  103. package/lib/chain/regen/regen.js.map +1 -1
  104. package/lib/chain/seenCache/seenGossipBlockInput.d.ts +7 -0
  105. package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
  106. package/lib/chain/seenCache/seenGossipBlockInput.js +22 -1
  107. package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
  108. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +3 -2
  109. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
  110. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +13 -13
  111. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
  112. package/lib/chain/shufflingCache.d.ts +18 -8
  113. package/lib/chain/shufflingCache.d.ts.map +1 -1
  114. package/lib/chain/shufflingCache.js +72 -18
  115. package/lib/chain/shufflingCache.js.map +1 -1
  116. package/lib/chain/validatorMonitor.d.ts +5 -1
  117. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  118. package/lib/chain/validatorMonitor.js +64 -54
  119. package/lib/chain/validatorMonitor.js.map +1 -1
  120. package/lib/db/beacon.d.ts +4 -1
  121. package/lib/db/beacon.d.ts.map +1 -1
  122. package/lib/db/beacon.js +6 -1
  123. package/lib/db/beacon.js.map +1 -1
  124. package/lib/db/buckets.d.ts +3 -1
  125. package/lib/db/buckets.d.ts.map +1 -1
  126. package/lib/db/buckets.js +2 -0
  127. package/lib/db/buckets.js.map +1 -1
  128. package/lib/db/interface.d.ts +4 -1
  129. package/lib/db/interface.d.ts.map +1 -1
  130. package/lib/db/repositories/blockArchive.js +2 -2
  131. package/lib/db/repositories/blockArchive.js.map +1 -1
  132. package/lib/db/repositories/blockArchiveIndex.d.ts +3 -3
  133. package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
  134. package/lib/db/repositories/blockArchiveIndex.js +1 -2
  135. package/lib/db/repositories/blockArchiveIndex.js.map +1 -1
  136. package/lib/db/repositories/earliestAvailableSlot.d.ts +11 -0
  137. package/lib/db/repositories/earliestAvailableSlot.d.ts.map +1 -0
  138. package/lib/db/repositories/earliestAvailableSlot.js +19 -0
  139. package/lib/db/repositories/earliestAvailableSlot.js.map +1 -0
  140. package/lib/db/repositories/index.d.ts +1 -0
  141. package/lib/db/repositories/index.d.ts.map +1 -1
  142. package/lib/db/repositories/index.js +1 -0
  143. package/lib/db/repositories/index.js.map +1 -1
  144. package/lib/db/repositories/proposerPreferences.d.ts +14 -0
  145. package/lib/db/repositories/proposerPreferences.d.ts.map +1 -0
  146. package/lib/db/repositories/proposerPreferences.js +21 -0
  147. package/lib/db/repositories/proposerPreferences.js.map +1 -0
  148. package/lib/execution/engine/blobVersionedHashes.d.ts +9 -0
  149. package/lib/execution/engine/blobVersionedHashes.d.ts.map +1 -0
  150. package/lib/execution/engine/blobVersionedHashes.js +74 -0
  151. package/lib/execution/engine/blobVersionedHashes.js.map +1 -0
  152. package/lib/execution/engine/disabled.d.ts +0 -2
  153. package/lib/execution/engine/disabled.d.ts.map +1 -1
  154. package/lib/execution/engine/disabled.js +0 -6
  155. package/lib/execution/engine/disabled.js.map +1 -1
  156. package/lib/execution/engine/http.d.ts +46 -16
  157. package/lib/execution/engine/http.d.ts.map +1 -1
  158. package/lib/execution/engine/http.js +236 -213
  159. package/lib/execution/engine/http.js.map +1 -1
  160. package/lib/execution/engine/index.d.ts +3 -2
  161. package/lib/execution/engine/index.d.ts.map +1 -1
  162. package/lib/execution/engine/index.js +33 -8
  163. package/lib/execution/engine/index.js.map +1 -1
  164. package/lib/execution/engine/interface.d.ts +2 -4
  165. package/lib/execution/engine/interface.d.ts.map +1 -1
  166. package/lib/execution/engine/jsonRpcTransport.d.ts +25 -0
  167. package/lib/execution/engine/jsonRpcTransport.d.ts.map +1 -0
  168. package/lib/execution/engine/jsonRpcTransport.js +158 -0
  169. package/lib/execution/engine/jsonRpcTransport.js.map +1 -0
  170. package/lib/execution/engine/mock.d.ts +0 -2
  171. package/lib/execution/engine/mock.d.ts.map +1 -1
  172. package/lib/execution/engine/mock.js +0 -8
  173. package/lib/execution/engine/mock.js.map +1 -1
  174. package/lib/execution/engine/restHttpClient.d.ts +71 -0
  175. package/lib/execution/engine/restHttpClient.d.ts.map +1 -0
  176. package/lib/execution/engine/restHttpClient.js +201 -0
  177. package/lib/execution/engine/restHttpClient.js.map +1 -0
  178. package/lib/execution/engine/restTransport.d.ts +46 -0
  179. package/lib/execution/engine/restTransport.d.ts.map +1 -0
  180. package/lib/execution/engine/restTransport.js +399 -0
  181. package/lib/execution/engine/restTransport.js.map +1 -0
  182. package/lib/execution/engine/sszTypes.d.ts +1261 -0
  183. package/lib/execution/engine/sszTypes.d.ts.map +1 -0
  184. package/lib/execution/engine/sszTypes.js +216 -0
  185. package/lib/execution/engine/sszTypes.js.map +1 -0
  186. package/lib/execution/engine/transport.d.ts +39 -0
  187. package/lib/execution/engine/transport.d.ts.map +1 -0
  188. package/lib/execution/engine/transport.js +2 -0
  189. package/lib/execution/engine/transport.js.map +1 -0
  190. package/lib/execution/engine/types.d.ts +2 -8
  191. package/lib/execution/engine/types.d.ts.map +1 -1
  192. package/lib/execution/engine/types.js +24 -57
  193. package/lib/execution/engine/types.js.map +1 -1
  194. package/lib/execution/engine/utils.d.ts.map +1 -1
  195. package/lib/execution/engine/utils.js +9 -2
  196. package/lib/execution/engine/utils.js.map +1 -1
  197. package/lib/metrics/metrics/lodestar.d.ts +10 -0
  198. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  199. package/lib/metrics/metrics/lodestar.js +22 -0
  200. package/lib/metrics/metrics/lodestar.js.map +1 -1
  201. package/lib/metrics/metrics.d.ts +7 -3
  202. package/lib/metrics/metrics.d.ts.map +1 -1
  203. package/lib/metrics/metrics.js +4 -4
  204. package/lib/metrics/metrics.js.map +1 -1
  205. package/lib/network/core/events.d.ts +5 -1
  206. package/lib/network/core/events.d.ts.map +1 -1
  207. package/lib/network/core/events.js +8 -0
  208. package/lib/network/core/events.js.map +1 -1
  209. package/lib/network/gossip/topic.d.ts +0 -14
  210. package/lib/network/gossip/topic.d.ts.map +1 -1
  211. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  212. package/lib/network/processor/gossipHandlers.js +60 -64
  213. package/lib/network/processor/gossipHandlers.js.map +1 -1
  214. package/lib/network/processor/index.js +3 -3
  215. package/lib/network/processor/index.js.map +1 -1
  216. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js +1 -1
  217. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js.map +1 -1
  218. package/lib/node/nodejs.d.ts +3 -1
  219. package/lib/node/nodejs.d.ts.map +1 -1
  220. package/lib/node/nodejs.js +27 -4
  221. package/lib/node/nodejs.js.map +1 -1
  222. package/lib/node/options.d.ts +3 -2
  223. package/lib/node/options.d.ts.map +1 -1
  224. package/lib/node/options.js +2 -2
  225. package/lib/node/options.js.map +1 -1
  226. package/lib/sync/range/batch.d.ts +11 -5
  227. package/lib/sync/range/batch.d.ts.map +1 -1
  228. package/lib/sync/range/batch.js +21 -17
  229. package/lib/sync/range/batch.js.map +1 -1
  230. package/lib/sync/range/chain.d.ts +4 -4
  231. package/lib/sync/range/chain.d.ts.map +1 -1
  232. package/lib/sync/range/chain.js +12 -6
  233. package/lib/sync/range/chain.js.map +1 -1
  234. package/lib/sync/range/range.d.ts.map +1 -1
  235. package/lib/sync/range/range.js +25 -11
  236. package/lib/sync/range/range.js.map +1 -1
  237. package/lib/sync/unknownBlock.d.ts +5 -2
  238. package/lib/sync/unknownBlock.d.ts.map +1 -1
  239. package/lib/sync/unknownBlock.js +44 -20
  240. package/lib/sync/unknownBlock.js.map +1 -1
  241. package/lib/sync/utils/downloadByRange.d.ts +38 -14
  242. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  243. package/lib/sync/utils/downloadByRange.js +84 -39
  244. package/lib/sync/utils/downloadByRange.js.map +1 -1
  245. package/lib/util/asyncIterableToEvents.d.ts +10 -2
  246. package/lib/util/asyncIterableToEvents.d.ts.map +1 -1
  247. package/lib/util/asyncIterableToEvents.js +29 -3
  248. package/lib/util/asyncIterableToEvents.js.map +1 -1
  249. package/lib/util/execution.d.ts +9 -11
  250. package/lib/util/execution.d.ts.map +1 -1
  251. package/lib/util/execution.js +5 -1
  252. package/lib/util/execution.js.map +1 -1
  253. package/lib/util/metadata.d.ts.map +1 -1
  254. package/lib/util/metadata.js +2 -1
  255. package/lib/util/metadata.js.map +1 -1
  256. package/lib/util/sszBytes.d.ts +2 -2
  257. package/lib/util/sszBytes.d.ts.map +1 -1
  258. package/lib/util/sszBytes.js +21 -14
  259. package/lib/util/sszBytes.js.map +1 -1
  260. package/package.json +18 -17
  261. package/src/api/impl/beacon/blocks/index.ts +17 -7
  262. package/src/api/impl/beacon/index.ts +15 -0
  263. package/src/api/impl/beacon/state/index.ts +43 -6
  264. package/src/api/impl/debug/index.ts +28 -19
  265. package/src/api/impl/validator/index.ts +81 -7
  266. package/src/chain/archiveStore/archiveStore.ts +19 -25
  267. package/src/chain/archiveStore/historicalState/getHistoricalState.ts +5 -7
  268. package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +1 -1
  269. package/src/chain/archiveStore/historicalState/types.ts +2 -2
  270. package/src/chain/archiveStore/historicalState/worker.ts +1 -2
  271. package/src/chain/archiveStore/interface.ts +1 -1
  272. package/src/chain/archiveStore/utils/pruneHistory.ts +4 -1
  273. package/src/chain/beaconProposerCache.ts +19 -1
  274. package/src/chain/blocks/blockInput/blockInput.ts +1 -1
  275. package/src/chain/blocks/importBlock.ts +17 -7
  276. package/src/chain/blocks/verifyBlock.ts +8 -6
  277. package/src/chain/blocks/verifyBlocksStateTransitionOnly.ts +6 -3
  278. package/src/chain/chain.ts +132 -35
  279. package/src/chain/emitter.ts +7 -1
  280. package/src/chain/errors/envelopeReconstructionError.ts +3 -0
  281. package/src/chain/forkChoice/index.ts +2 -0
  282. package/src/chain/interface.ts +7 -3
  283. package/src/chain/opPools/aggregatedAttestationPool.ts +34 -10
  284. package/src/chain/opPools/opPool.ts +1 -31
  285. package/src/chain/opPools/proposerPreferencesPool.ts +34 -11
  286. package/src/chain/opPools/utils.ts +31 -0
  287. package/src/chain/options.ts +3 -3
  288. package/src/chain/prepareNextSlot.ts +15 -3
  289. package/src/chain/produceBlock/computeNewStateRoot.ts +10 -3
  290. package/src/chain/produceBlock/produceBlockBody.ts +78 -39
  291. package/src/chain/regen/regen.ts +12 -4
  292. package/src/chain/seenCache/seenGossipBlockInput.ts +25 -1
  293. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +20 -13
  294. package/src/chain/shufflingCache.ts +84 -22
  295. package/src/chain/validatorMonitor.ts +75 -57
  296. package/src/db/beacon.ts +6 -0
  297. package/src/db/buckets.ts +2 -0
  298. package/src/db/interface.ts +4 -0
  299. package/src/db/repositories/blockArchive.ts +2 -2
  300. package/src/db/repositories/blockArchiveIndex.ts +2 -3
  301. package/src/db/repositories/earliestAvailableSlot.ts +19 -0
  302. package/src/db/repositories/index.ts +1 -0
  303. package/src/db/repositories/proposerPreferences.ts +23 -0
  304. package/src/execution/engine/blobVersionedHashes.ts +72 -0
  305. package/src/execution/engine/disabled.ts +0 -8
  306. package/src/execution/engine/http.ts +304 -300
  307. package/src/execution/engine/index.ts +41 -7
  308. package/src/execution/engine/interface.ts +2 -6
  309. package/src/execution/engine/jsonRpcTransport.ts +247 -0
  310. package/src/execution/engine/mock.ts +1 -19
  311. package/src/execution/engine/restHttpClient.ts +269 -0
  312. package/src/execution/engine/restTransport.ts +544 -0
  313. package/src/execution/engine/sszTypes.ts +354 -0
  314. package/src/execution/engine/transport.ts +61 -0
  315. package/src/execution/engine/types.ts +34 -84
  316. package/src/execution/engine/utils.ts +12 -2
  317. package/src/metrics/metrics/lodestar.ts +23 -0
  318. package/src/metrics/metrics.ts +21 -6
  319. package/src/network/core/events.ts +16 -1
  320. package/src/network/processor/gossipHandlers.ts +91 -77
  321. package/src/network/processor/index.ts +3 -3
  322. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRoot.ts +1 -1
  323. package/src/node/nodejs.ts +35 -3
  324. package/src/node/options.ts +10 -1
  325. package/src/sync/range/batch.ts +25 -19
  326. package/src/sync/range/chain.ts +15 -8
  327. package/src/sync/range/range.ts +26 -12
  328. package/src/sync/unknownBlock.ts +57 -21
  329. package/src/sync/utils/downloadByRange.ts +123 -58
  330. package/src/util/asyncIterableToEvents.ts +44 -5
  331. package/src/util/execution.ts +16 -8
  332. package/src/util/metadata.ts +2 -1
  333. 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({
@@ -1281,6 +1287,10 @@ export function createLodestarMetrics(
1281
1287
  name: "lodestar_oppool_aggregated_attestation_pool_packed_attestations_seen_committees_total",
1282
1288
  help: "Total number of committees for which all members are seen when producing packed attestations",
1283
1289
  }),
1290
+ missingShufflingCommittees: register.gauge({
1291
+ name: "lodestar_oppool_aggregated_attestation_pool_packed_attestations_missing_shuffling_committees_total",
1292
+ help: "Total number of committees skipped due to missing shuffling when producing packed attestations",
1293
+ }),
1284
1294
  },
1285
1295
  },
1286
1296
  attestationPool: {
@@ -1614,6 +1624,19 @@ export function createLodestarMetrics(
1614
1624
  name: "lodestar_shuffling_cache_size",
1615
1625
  help: "Shuffling cache size",
1616
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
+ }),
1617
1640
  insertPromiseCount: register.gauge({
1618
1641
  name: "lodestar_shuffling_cache_insert_promise_count",
1619
1642
  help: "Total number of times insertPromise is called",
@@ -9,27 +9,42 @@ import {RegistryMetricCreator} from "./utils/registryMetricCreator.js";
9
9
 
10
10
  export type Metrics = BeaconMetrics &
11
11
  ForkChoiceMetrics &
12
- BeaconStateTransitionMetrics &
13
- LodestarMetrics & {register: RegistryMetricCreator; close: () => void};
12
+ LodestarMetrics & {
13
+ /** Null when we use native state transition metrics instead */
14
+ stateTransition: BeaconStateTransitionMetrics | null;
15
+ register: RegistryMetricCreator;
16
+ close: () => void;
17
+ };
18
+
19
+ export type CreateMetricsOptions = {
20
+ /*
21
+ * Toggle inclusion of state transition metrics.
22
+ *
23
+ * False when native state transition is used, so we
24
+ * can grab metrics from the native implementation instead.
25
+ * */
26
+ includeStateTransitionMetrics?: boolean;
27
+ collectNodeMetrics?: boolean;
28
+ };
14
29
 
15
30
  export function createMetrics(
16
31
  opts: MetricsOptions,
17
32
  genesisTime: number,
18
33
  externalRegistries: Registry[] = [],
19
- {collectNodeMetrics = true}: {collectNodeMetrics?: boolean} = {}
34
+ createOpts: CreateMetricsOptions = {}
20
35
  ): Metrics {
21
36
  const register = new RegistryMetricCreator();
22
37
  const beacon = createBeaconMetrics(register);
23
38
  const forkChoice = getForkChoiceMetrics(register);
24
39
  const lodestar = createLodestarMetrics(register, opts.metadata, genesisTime);
25
- const stateTransition = getMetrics(register);
40
+ const stateTransition = createOpts.includeStateTransitionMetrics === false ? null : getMetrics(register);
26
41
 
27
42
  const onUnhandledRejection = (_error: unknown): void => {
28
43
  lodestar.unhandledPromiseRejections.inc();
29
44
  };
30
45
  process.on("unhandledRejection", onUnhandledRejection);
31
46
 
32
- const nodeJsMetricsClose = collectNodeMetrics ? collectNodeJSMetrics(register) : (): void => {};
47
+ const nodeJsMetricsClose = createOpts.collectNodeMetrics === false ? (): void => {} : collectNodeJSMetrics(register);
33
48
  const close = (): void => {
34
49
  process.removeListener("unhandledRejection", onUnhandledRejection);
35
50
  nodeJsMetricsClose();
@@ -46,7 +61,7 @@ export function createMetrics(
46
61
  ...beacon,
47
62
  ...forkChoice,
48
63
  ...lodestar,
49
- ...stateTransition,
64
+ stateTransition,
50
65
  register,
51
66
  close,
52
67
  };
@@ -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
  }
@@ -12,9 +12,10 @@ import {
12
12
  isForkPostElectra,
13
13
  isForkPostGloas,
14
14
  } from "@lodestar/params";
15
- import {computeTimeAtSlot} from "@lodestar/state-transition";
15
+ import {computeTimeAtSlot, signedBlockToSignedHeader} from "@lodestar/state-transition";
16
16
  import {
17
17
  Root,
18
+ RootHex,
18
19
  SignedBeaconBlock,
19
20
  SingleAttestation,
20
21
  Slot,
@@ -78,6 +79,7 @@ import {
78
79
  validateGossipSyncCommittee,
79
80
  validateGossipVoluntaryExit,
80
81
  validateSyncCommitteeGossipContributionAndProof,
82
+ verifyBlockProposerSignature,
81
83
  } from "../../chain/validation/index.js";
82
84
  import {validateLightClientFinalityUpdate} from "../../chain/validation/lightClientFinalityUpdate.js";
83
85
  import {validateLightClientOptimisticUpdate} from "../../chain/validation/lightClientOptimisticUpdate.js";
@@ -148,37 +150,16 @@ export function getGossipHandlers(modules: ValidatorFnsModules, options: GossipH
148
150
  function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHandlerOpts): SequentialGossipHandlers {
149
151
  const {chain, config, metrics, logger, core} = modules;
150
152
 
151
- async function validateBeaconBlock(
153
+ /**
154
+ * Add a gossip block to the seen caches. The proposer signature of the block MUST be verified.
155
+ */
156
+ function cacheSignatureVerifiedBlock(
152
157
  signedBlock: SignedBeaconBlock,
158
+ blockRootHex: RootHex,
153
159
  fork: ForkName,
154
160
  peerIdStr: string,
155
161
  seenTimestampSec: number
156
- ): Promise<IBlockInput> {
157
- const slot = signedBlock.message.slot;
158
- const forkTypes = config.getForkTypes(slot);
159
- const blockRootHex = toRootHex(forkTypes.BeaconBlock.hashTreeRoot(signedBlock.message));
160
- const delaySec = chain.clock.secFromSlot(slot, seenTimestampSec);
161
- const recvToValLatency = Date.now() / 1000 - seenTimestampSec;
162
-
163
- // always set block to seen cache for all forks so that we don't need to download it
164
- // TODO: validate block before adding to cache
165
- // tracked in https://github.com/ChainSafe/lodestar/issues/7957
166
-
167
- const logCtx = {
168
- slot,
169
- root: blockRootHex,
170
- currentSlot: chain.clock.currentSlot,
171
- peerId: peerIdStr,
172
- delaySec,
173
- recvToValLatency,
174
- };
175
-
176
- logger.debug("Received gossip block", {...logCtx});
177
-
178
- // optimistically add gossip block to the seen cache
179
- // if validation fails, we will NOT forward this gossip block to peers
180
- // - if PARENT_BLOCK_UNKNOWN error, blockInput will then be queued inside BlockInputSync. If the gossip block is really invalid, it will be pruned there
181
- // - if other validator errors, blockInput will stay in the seen cache and will be pruned on finalization
162
+ ): BlockInput {
182
163
  const blockInput = chain.seenBlockInputCache.getByBlock({
183
164
  block: signedBlock,
184
165
  blockRootHex,
@@ -187,8 +168,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
187
168
  peerIdStr,
188
169
  });
189
170
 
190
- // Optimistically seed the payload-envelope cache too, mirroring seenBlockInputCache above.
191
- // This ensures we have PayloadEnvelopeInput, even through "PARENT_BLOCK_UNKNOWN" error
171
+ // Also seed the payload-envelope cache, so we have PayloadEnvelopeInput even through "PARENT_BLOCK_UNKNOWN" error
192
172
  // see https://github.com/ChainSafe/lodestar/issues/9475
193
173
  if (isForkPostGloas(fork)) {
194
174
  chain.seenPayloadEnvelopeInputCache.add({
@@ -202,8 +182,37 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
202
182
  });
203
183
  }
204
184
 
185
+ return blockInput;
186
+ }
187
+
188
+ async function validateBeaconBlock(
189
+ signedBlock: SignedBeaconBlock,
190
+ fork: ForkName,
191
+ peerIdStr: string,
192
+ seenTimestampSec: number
193
+ ): Promise<IBlockInput> {
194
+ const slot = signedBlock.message.slot;
195
+ const forkTypes = config.getForkTypes(slot);
196
+ const blockRootHex = toRootHex(forkTypes.BeaconBlock.hashTreeRoot(signedBlock.message));
197
+ const delaySec = chain.clock.secFromSlot(slot, seenTimestampSec);
198
+ const recvToValLatency = Date.now() / 1000 - seenTimestampSec;
199
+
200
+ const logCtx = {
201
+ slot,
202
+ root: blockRootHex,
203
+ currentSlot: chain.clock.currentSlot,
204
+ peerId: peerIdStr,
205
+ delaySec,
206
+ recvToValLatency,
207
+ };
208
+
209
+ logger.debug("Received gossip block", {...logCtx});
210
+
211
+ chain.seenBlockInputCache.markValidatingBlock(blockRootHex);
212
+
205
213
  try {
206
214
  const {skippedSlots} = await validateGossipBlock(config, chain, signedBlock, fork);
215
+ const blockInput = cacheSignatureVerifiedBlock(signedBlock, blockRootHex, fork, peerIdStr, seenTimestampSec);
207
216
 
208
217
  const blockInputMeta = blockInput.getLogMeta();
209
218
 
@@ -229,54 +238,54 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
229
238
  if (e instanceof BlockGossipError) {
230
239
  logger.debug("Gossip block has error", {slot, root: blockRootHex, code: e.type.code});
231
240
  if (
232
- (e.type.code === BlockErrorCode.PARENT_BLOCK_UNKNOWN ||
233
- e.type.code === BlockErrorCode.PARENT_PAYLOAD_UNKNOWN) &&
234
- blockInput
241
+ e.type.code === BlockErrorCode.PARENT_BLOCK_UNKNOWN ||
242
+ e.type.code === BlockErrorCode.PARENT_PAYLOAD_UNKNOWN
235
243
  ) {
244
+ // The block is retained for unknown parent sync without full validation. Authenticate it first, this
245
+ // does not need the parent state
246
+ const proposerIndex = signedBlock.message.proposerIndex;
247
+ await verifyBlockProposerSignature(chain, signedBlock, blockRootHex);
248
+ chain.seenBlockProposers.observeBlockRoot(
249
+ slot,
250
+ proposerIndex,
251
+ blockRootHex,
252
+ signedBlockToSignedHeader(config, signedBlock)
253
+ );
254
+
255
+ // Check again after the signature verification so concurrent proposals cannot both be retained
256
+ if (chain.seenBlockProposers.isKnown(slot, proposerIndex)) {
257
+ if (chain.seenBlockProposers.isRepeatProposal(slot, proposerIndex, blockRootHex)) {
258
+ throw new BlockGossipError(GossipAction.IGNORE, {
259
+ code: BlockErrorCode.REPEAT_PROPOSAL,
260
+ proposerIndex,
261
+ root: blockRootHex,
262
+ });
263
+ }
264
+ throw new BlockGossipError(GossipAction.IGNORE, {code: BlockErrorCode.ALREADY_KNOWN, root: blockRootHex});
265
+ }
266
+ chain.seenBlockProposers.add(slot, proposerIndex, blockRootHex);
267
+
268
+ const blockInput = cacheSignatureVerifiedBlock(signedBlock, blockRootHex, fork, peerIdStr, seenTimestampSec);
236
269
  chain.emitter.emit(ChainEvent.blockUnknownParent, {
237
270
  blockInput,
238
271
  peer: peerIdStr,
239
272
  source: BlockInputSource.gossip,
240
273
  });
241
- // throw error (don't prune the blockInput)
242
274
  throw e;
243
275
  }
244
276
 
245
- // IGNORE means the block is acceptable (e.g. FUTURE_SLOT, ALREADY_KNOWN), just not propagated.
246
- // Keep the optimistically-added cache entries; they are pruned on finalization. Only REJECT
247
- // (provably invalid), unexpected errors and repeat proposals that are not imported prune.
248
- if (e.action === GossipAction.IGNORE) {
249
- // Only a signature-verified sibling is imported by the beacon_block handler, any other repeat proposal
250
- // is dropped from the caches and re-downloaded by sync if it ever becomes relevant. Its signature was not
251
- // verified, so only its own entry is removed, never its claimed ancestors
252
- if (
253
- e.type.code === BlockErrorCode.REPEAT_PROPOSAL &&
254
- !chain.seenBlockProposers.hasBlockRoot(slot, signedBlock.message.proposerIndex, blockRootHex)
255
- ) {
256
- chain.seenBlockInputCache.remove(blockRootHex);
257
- if (isForkPostGloas(fork)) {
258
- chain.seenPayloadEnvelopeInputCache.remove(blockRootHex);
259
- }
260
- }
261
- throw e;
277
+ if (e.action === GossipAction.REJECT) {
278
+ chain.persistInvalidSszValue(
279
+ forkTypes.SignedBeaconBlock,
280
+ signedBlock,
281
+ `gossip_reject_slot_${slot}`,
282
+ blockRootHex
283
+ );
262
284
  }
263
-
264
- chain.persistInvalidSszValue(
265
- forkTypes.SignedBeaconBlock,
266
- signedBlock,
267
- `gossip_reject_slot_${slot}`,
268
- blockRootHex
269
- );
270
- }
271
-
272
- // REJECT or unexpected (non-BlockGossipError) error: drop the optimistically-added entries from
273
- // both caches, keeping them consistent. The block may carry any parent root, so only its own entry is removed
274
- chain.seenBlockInputCache.remove(blockRootHex);
275
- if (isForkPostGloas(fork)) {
276
- chain.seenPayloadEnvelopeInputCache.remove(blockRootHex);
277
285
  }
278
286
  throw e;
279
287
  } finally {
288
+ chain.seenBlockInputCache.unmarkValidatingBlock(blockRootHex);
280
289
  // The block received from the network may have established an equivocation, either by conflicting
281
290
  // with a previously observed block root (REPEAT_PROPOSAL) or with a root observed during validation
282
291
  const proposerIndex = signedBlock.message.proposerIndex;
@@ -752,18 +761,23 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
752
761
  e.type.code === BlockErrorCode.REPEAT_PROPOSAL &&
753
762
  // Only a signature-verified sibling recorded in the seen cache is imported. The cache holds at most two
754
763
  // roots per proposer and slot, which bounds full imports over gossip to one alternate
755
- chain.seenBlockProposers.hasBlockRoot(signedBlock.message.slot, e.type.proposerIndex, e.type.root)
764
+ chain.seenBlockProposers.hasBlockRoot(signedBlock.message.slot, e.type.proposerIndex, e.type.root) &&
765
+ // A sibling with an unknown parent cannot be imported, sync fetches it if its branch becomes relevant
766
+ chain.forkChoice.getBlockHexDefaultStatus(toRootHex(signedBlock.message.parentRoot)) !== null
756
767
  ) {
757
- // blockInput was optimistically seeded in validateBeaconBlock and retained on IGNORE
758
- const blockInput = chain.seenBlockInputCache.get(e.type.root);
759
- if (blockInput) {
760
- // We're returning IGNORE (thrown below), so this block is not forwarded to peers. Unlike the
761
- // happy path there is no rush to forward, so we don't need to wrap in callInNextEventLoop.
762
- chain.serializedCache.set(signedBlock, serializedData);
763
- // this is technically not a valid gossip block but gossip validation is a cheap subset of checks
764
- // this runs the full state transition, so importing an equivocating-but-valid block here is safe.
765
- handleValidBeaconBlock(blockInput, peerIdStr, seenTimestampSec);
766
- }
768
+ const blockInput = cacheSignatureVerifiedBlock(
769
+ signedBlock,
770
+ e.type.root,
771
+ topic.boundary.fork,
772
+ peerIdStr,
773
+ seenTimestampSec
774
+ );
775
+ // We're returning IGNORE (thrown below), so this block is not forwarded to peers. Unlike the
776
+ // happy path there is no rush to forward, so we don't need to wrap in callInNextEventLoop.
777
+ chain.serializedCache.set(signedBlock, serializedData);
778
+ // this is technically not a valid gossip block but gossip validation is a cheap subset of checks
779
+ // this runs the full state transition, so importing an equivocating-but-valid block here is safe.
780
+ handleValidBeaconBlock(blockInput, peerIdStr, seenTimestampSec);
767
781
  }
768
782
  // rethrow so gossipValidatorFn maps IGNORE -> TopicValidatorResult.Ignore (message not forwarded)
769
783
  throw e;
@@ -1381,7 +1395,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
1381
1395
  const delaySec = chain.clock.secFromSlot(payloadAttestationMessage.data.slot, seenTimestampSec);
1382
1396
  metrics?.gossipPayloadAttestationMessage.elapsedTimeTillReceived.observe({source: OpSource.gossip}, delaySec);
1383
1397
  const nextSlotProposer = chain.getHeadState().getBeaconProposer(payloadAttestationMessage.data.slot + 1);
1384
- const isNextSlotProposer = chain.beaconProposerCache.get(nextSlotProposer) !== undefined;
1398
+ const isNextSlotProposer = chain.beaconProposerCache.has(nextSlotProposer);
1385
1399
 
1386
1400
  if (isNextSlotProposer) {
1387
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) {
@@ -53,7 +53,7 @@ export async function* onExecutionPayloadEnvelopesByRoot(
53
53
  const batch = requests.slice(i, i + MAX_BODIES_PER_REQUEST);
54
54
  let envelopesBytes: (Uint8Array | null)[];
55
55
  try {
56
- // By-root allows omission, so a mismatched envelope is left out rather than failing the response.
56
+ // By-root allows omission, so an envelope that cannot be rebuilt is left out rather than failing the response.
57
57
  envelopesBytes = await chain.getSerializedExecutionPayloadEnvelopes(batch, "omit");
58
58
  } catch (e) {
59
59
  if (e instanceof EnvelopeReconstructionError) {
@@ -1,6 +1,12 @@
1
1
  import {setMaxListeners} from "node:events";
2
2
  import {PrivateKey} from "@libp2p/interface";
3
3
  import {Registry} from "prom-client";
4
+ import {
5
+ init as initNativeMetrics,
6
+ registerLocalValidator as registerNativeLocalValidator,
7
+ scrapeMetrics as scrapeNativeMetrics,
8
+ unregisterLocalValidator as unregisterNativeLocalValidator,
9
+ } from "@chainsafe/lodestar-z/metrics";
4
10
  import {type PubkeyCache} from "@chainsafe/lodestar-z/pubkeys";
5
11
  import {hasher} from "@chainsafe/persistent-merkle-tree";
6
12
  import {BeaconApiMethods} from "@lodestar/api/beacon/server";
@@ -8,6 +14,7 @@ import {BeaconConfig} from "@lodestar/config";
8
14
  import type {LoggerNode} from "@lodestar/logger/node";
9
15
  import {ZERO_HASH_HEX} from "@lodestar/params";
10
16
  import {IBeaconStateView, isStatePostBellatrix, isStatePostGloas} from "@lodestar/state-transition";
17
+ import {Slot} from "@lodestar/types";
11
18
  import {sleep, toRootHex} from "@lodestar/utils";
12
19
  import {ProcessShutdownCallback} from "@lodestar/validator";
13
20
  import {BeaconRestApiServer, getApi} from "../api/index.js";
@@ -55,6 +62,7 @@ export type BeaconNodeInitModules = {
55
62
  peerStoreDir?: string;
56
63
  anchorState: IBeaconStateView;
57
64
  isAnchorStateFinalized: boolean;
65
+ earliestAvailableSlot: Slot;
58
66
  metricsRegistries?: Registry[];
59
67
  };
60
68
 
@@ -153,6 +161,7 @@ export class BeaconNode {
153
161
  peerStoreDir,
154
162
  anchorState,
155
163
  isAnchorStateFinalized,
164
+ earliestAvailableSlot,
156
165
  metricsRegistries = [],
157
166
  }: BeaconNodeInitModules): Promise<T> {
158
167
  if (hasher.name !== "hashtree") {
@@ -171,7 +180,13 @@ export class BeaconNode {
171
180
  // monitoring relies on metrics data
172
181
  opts.monitoring.endpoint
173
182
  ) {
174
- metrics = createMetrics(opts.metrics, anchorState.genesisTime, metricsRegistries);
183
+ if (opts.chain.nativeStateTransition) {
184
+ initNativeMetrics();
185
+ }
186
+
187
+ metrics = createMetrics(opts.metrics, anchorState.genesisTime, metricsRegistries, {
188
+ includeStateTransitionMetrics: !opts.chain.nativeStateTransition,
189
+ });
175
190
  initBeaconMetrics(metrics, anchorState);
176
191
  // Since the db is instantiated before this, metrics must be injected manually afterwards
177
192
  db.setMetrics(metrics.db, metrics.flatFileStore);
@@ -185,7 +200,13 @@ export class BeaconNode {
185
200
  config,
186
201
  anchorState.genesisTime,
187
202
  logger.child({module: LoggerModule.vmon}),
188
- opts.validatorMonitor
203
+ opts.validatorMonitor,
204
+ opts.chain.nativeStateTransition
205
+ ? {
206
+ registerLocalValidator: registerNativeLocalValidator,
207
+ unregisterLocalValidator: unregisterNativeLocalValidator,
208
+ }
209
+ : null
189
210
  )
190
211
  : null;
191
212
 
@@ -248,6 +269,7 @@ export class BeaconNode {
248
269
  validatorMonitor,
249
270
  anchorState,
250
271
  isAnchorStateFinalized,
272
+ earliestAvailableSlot,
251
273
  executionEngine: initializeExecutionEngine(executionEngineOpts, {
252
274
  metrics,
253
275
  signal,
@@ -303,7 +325,17 @@ export class BeaconNode {
303
325
  const metricsServer = opts.metrics.enabled
304
326
  ? await getHttpMetricsServer(opts.metrics, {
305
327
  register: (metrics as Metrics).register,
306
- getOtherMetrics: async () => Promise.all([network.scrapeMetrics(), chain.archiveStore.scrapeMetrics()]),
328
+ getOtherMetrics: async () => {
329
+ const otherMetrics = await Promise.all([network.scrapeMetrics(), chain.archiveStore.scrapeMetrics()]);
330
+ if (opts.chain.nativeStateTransition) {
331
+ try {
332
+ otherMetrics.push(scrapeNativeMetrics());
333
+ } catch (e) {
334
+ logger.warn("Failed to scrape native state-transition metrics", {}, e as Error);
335
+ }
336
+ }
337
+ return otherMetrics;
338
+ },
307
339
  logger: logger.child({module: LoggerModule.metrics}),
308
340
  })
309
341
  : null;
@@ -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
  /**
@@ -773,6 +768,7 @@ export class Batch {
773
768
  // remove any downloaded blocks and re-attempt
774
769
  // TODO(fulu): need to remove the bad blocks from the SeenBlockInputCache
775
770
  this.state = {status: BatchStatus.AwaitingDownload, blocks: [], payloadEnvelopes: null};
771
+ this.resetRequests();
776
772
  }
777
773
 
778
774
  private onProcessingError(attempt: FailedAttempt): void {
@@ -784,6 +780,16 @@ export class Batch {
784
780
  // remove any downloaded blocks and re-attempt
785
781
  // TODO(fulu): need to remove the bad blocks from the SeenBlockInputCache
786
782
  this.state = {status: BatchStatus.AwaitingDownload, blocks: [], payloadEnvelopes: null};
783
+ this.resetRequests();
784
+ }
785
+
786
+ /**
787
+ * After a partial download `requests` only cover the data still missing from the downloaded blocks,
788
+ * e.g. a single column. Once those blocks are dropped, request the whole batch again, otherwise
789
+ * every peer fails the retry for lack of blocks to validate the data against.
790
+ */
791
+ private resetRequests(): void {
792
+ this.requests = this.getRequests([]);
787
793
  }
788
794
 
789
795
  /** Helper to construct typed BatchError. Stack traces are correct as the error is thrown above */