@lodestar/beacon-node 1.51.0-dev.e22f67e7bc → 1.51.0-dev.e2bf489dd3

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 (402) hide show
  1. package/lib/api/impl/api.js +1 -1
  2. package/lib/api/impl/api.js.map +1 -1
  3. package/lib/api/impl/beacon/blocks/index.d.ts +2 -1
  4. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  5. package/lib/api/impl/beacon/blocks/index.js +29 -34
  6. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  7. package/lib/api/impl/beacon/index.d.ts +2 -1
  8. package/lib/api/impl/beacon/index.d.ts.map +1 -1
  9. package/lib/api/impl/beacon/index.js +2 -2
  10. package/lib/api/impl/beacon/index.js.map +1 -1
  11. package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
  12. package/lib/api/impl/beacon/pool/index.js +5 -2
  13. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  14. package/lib/api/impl/beacon/state/utils.d.ts +1 -1
  15. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  16. package/lib/api/impl/validator/index.d.ts +6 -0
  17. package/lib/api/impl/validator/index.d.ts.map +1 -1
  18. package/lib/api/impl/validator/index.js +42 -26
  19. package/lib/api/impl/validator/index.js.map +1 -1
  20. package/lib/api/options.d.ts +2 -0
  21. package/lib/api/options.d.ts.map +1 -1
  22. package/lib/api/options.js +1 -0
  23. package/lib/api/options.js.map +1 -1
  24. package/lib/chain/GetBlobsTracker.d.ts +13 -2
  25. package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
  26. package/lib/chain/GetBlobsTracker.js +85 -27
  27. package/lib/chain/GetBlobsTracker.js.map +1 -1
  28. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  29. package/lib/chain/archiveStore/archiveStore.js +1 -0
  30. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  31. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +4 -0
  32. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
  33. package/lib/chain/archiveStore/utils/archiveBlocks.js +61 -97
  34. package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
  35. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  36. package/lib/chain/blocks/importBlock.js +21 -50
  37. package/lib/chain/blocks/importBlock.js.map +1 -1
  38. package/lib/chain/blocks/importExecutionPayload.d.ts +10 -11
  39. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  40. package/lib/chain/blocks/importExecutionPayload.js +34 -19
  41. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  42. package/lib/chain/blocks/index.d.ts.map +1 -1
  43. package/lib/chain/blocks/index.js +4 -4
  44. package/lib/chain/blocks/index.js.map +1 -1
  45. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +12 -9
  46. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -1
  47. package/lib/chain/blocks/payloadEnvelopeProcessor.js +24 -19
  48. package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
  49. package/lib/chain/blocks/types.d.ts +4 -1
  50. package/lib/chain/blocks/types.d.ts.map +1 -1
  51. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  52. package/lib/chain/blocks/verifyBlock.js +18 -7
  53. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  54. package/lib/chain/blocks/verifyBlocksDataAvailability.d.ts.map +1 -1
  55. package/lib/chain/blocks/verifyBlocksDataAvailability.js +8 -1
  56. package/lib/chain/blocks/verifyBlocksDataAvailability.js.map +1 -1
  57. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +1 -1
  58. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  59. package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
  60. package/lib/chain/blocks/verifyBlocksSanityChecks.js +4 -0
  61. package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
  62. package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
  63. package/lib/chain/blocks/verifyBlocksSignatures.js +7 -5
  64. package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
  65. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts +3 -3
  66. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -1
  67. package/lib/chain/blocks/verifyPayloadsDataAvailability.js +11 -6
  68. package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -1
  69. package/lib/chain/bls/interface.d.ts +2 -0
  70. package/lib/chain/bls/interface.d.ts.map +1 -1
  71. package/lib/chain/bls/multithread/index.d.ts.map +1 -1
  72. package/lib/chain/bls/multithread/index.js +13 -11
  73. package/lib/chain/bls/multithread/index.js.map +1 -1
  74. package/lib/chain/bls/multithread/types.d.ts +1 -1
  75. package/lib/chain/bls/multithread/types.d.ts.map +1 -1
  76. package/lib/chain/bls/multithread/worker.js +1 -1
  77. package/lib/chain/bls/multithread/worker.js.map +1 -1
  78. package/lib/chain/bls/singleThread.js +1 -1
  79. package/lib/chain/bls/singleThread.js.map +1 -1
  80. package/lib/chain/bls/utils.js +1 -1
  81. package/lib/chain/bls/utils.js.map +1 -1
  82. package/lib/chain/chain.d.ts +8 -2
  83. package/lib/chain/chain.d.ts.map +1 -1
  84. package/lib/chain/chain.js +57 -7
  85. package/lib/chain/chain.js.map +1 -1
  86. package/lib/chain/errors/blockError.d.ts +1 -1
  87. package/lib/chain/errors/blockError.d.ts.map +1 -1
  88. package/lib/chain/errors/blockError.js +1 -1
  89. package/lib/chain/errors/blockError.js.map +1 -1
  90. package/lib/chain/errors/executionPayloadEnvelope.d.ts +7 -0
  91. package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
  92. package/lib/chain/errors/executionPayloadEnvelope.js +1 -0
  93. package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
  94. package/lib/chain/forkChoice/index.d.ts +11 -1
  95. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  96. package/lib/chain/forkChoice/index.js +11 -0
  97. package/lib/chain/forkChoice/index.js.map +1 -1
  98. package/lib/chain/forkChoiceExecutionEngine.d.ts +53 -0
  99. package/lib/chain/forkChoiceExecutionEngine.d.ts.map +1 -0
  100. package/lib/chain/forkChoiceExecutionEngine.js +121 -0
  101. package/lib/chain/forkChoiceExecutionEngine.js.map +1 -0
  102. package/lib/chain/interface.d.ts +5 -5
  103. package/lib/chain/interface.d.ts.map +1 -1
  104. package/lib/chain/interface.js.map +1 -1
  105. package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
  106. package/lib/chain/opPools/aggregatedAttestationPool.js +23 -10
  107. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  108. package/lib/chain/opPools/attestationPool.d.ts +1 -1
  109. package/lib/chain/opPools/attestationPool.d.ts.map +1 -1
  110. package/lib/chain/opPools/attestationPool.js +15 -4
  111. package/lib/chain/opPools/attestationPool.js.map +1 -1
  112. package/lib/chain/opPools/inclusionListStore.d.ts.map +1 -1
  113. package/lib/chain/opPools/inclusionListStore.js +2 -2
  114. package/lib/chain/opPools/inclusionListStore.js.map +1 -1
  115. package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -1
  116. package/lib/chain/opPools/payloadAttestationPool.js +17 -7
  117. package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
  118. package/lib/chain/opPools/syncCommitteeMessagePool.d.ts.map +1 -1
  119. package/lib/chain/opPools/syncCommitteeMessagePool.js +9 -3
  120. package/lib/chain/opPools/syncCommitteeMessagePool.js.map +1 -1
  121. package/lib/chain/opPools/syncContributionAndProofPool.d.ts.map +1 -1
  122. package/lib/chain/opPools/syncContributionAndProofPool.js +11 -3
  123. package/lib/chain/opPools/syncContributionAndProofPool.js.map +1 -1
  124. package/lib/chain/opPools/utils.d.ts +1 -1
  125. package/lib/chain/opPools/utils.d.ts.map +1 -1
  126. package/lib/chain/opPools/utils.js +1 -1
  127. package/lib/chain/opPools/utils.js.map +1 -1
  128. package/lib/chain/options.d.ts +0 -1
  129. package/lib/chain/options.d.ts.map +1 -1
  130. package/lib/chain/options.js +0 -1
  131. package/lib/chain/options.js.map +1 -1
  132. package/lib/chain/produceBlock/produceBlockBody.d.ts +3 -2
  133. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  134. package/lib/chain/produceBlock/produceBlockBody.js +1 -2
  135. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  136. package/lib/chain/regen/interface.d.ts +1 -2
  137. package/lib/chain/regen/interface.d.ts.map +1 -1
  138. package/lib/chain/regen/interface.js +0 -1
  139. package/lib/chain/regen/interface.js.map +1 -1
  140. package/lib/chain/regen/queued.d.ts +1 -1
  141. package/lib/chain/regen/queued.d.ts.map +1 -1
  142. package/lib/chain/regen/queued.js +5 -3
  143. package/lib/chain/regen/queued.js.map +1 -1
  144. package/lib/chain/validation/executionPayloadBid.d.ts +0 -15
  145. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  146. package/lib/chain/validation/executionPayloadBid.js +13 -166
  147. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  148. package/lib/chain/validation/executionPayloadEnvelope.d.ts +6 -0
  149. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  150. package/lib/chain/validation/executionPayloadEnvelope.js +53 -0
  151. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  152. package/lib/chain/validation/inclusionList.d.ts.map +1 -1
  153. package/lib/chain/validation/inclusionList.js +11 -2
  154. package/lib/chain/validation/inclusionList.js.map +1 -1
  155. package/lib/db/beacon.d.ts +7 -0
  156. package/lib/db/beacon.d.ts.map +1 -1
  157. package/lib/db/beacon.js +34 -0
  158. package/lib/db/beacon.js.map +1 -1
  159. package/lib/db/dataColumnStore.d.ts +1 -1
  160. package/lib/db/dataColumnStore.d.ts.map +1 -1
  161. package/lib/db/dataColumnStore.js +1 -4
  162. package/lib/db/dataColumnStore.js.map +1 -1
  163. package/lib/db/flatFileStore/flatFileStore.js +5 -5
  164. package/lib/db/flatFileStore/flatFileStore.js.map +1 -1
  165. package/lib/db/flatFileStore/slotIndex.d.ts.map +1 -1
  166. package/lib/db/flatFileStore/slotIndex.js +2 -2
  167. package/lib/db/flatFileStore/slotIndex.js.map +1 -1
  168. package/lib/db/interface.d.ts +1 -0
  169. package/lib/db/interface.d.ts.map +1 -1
  170. package/lib/db/repositories/dataColumnSidecarArchive.d.ts +6 -0
  171. package/lib/db/repositories/dataColumnSidecarArchive.d.ts.map +1 -1
  172. package/lib/db/repositories/dataColumnSidecarArchive.js +19 -0
  173. package/lib/db/repositories/dataColumnSidecarArchive.js.map +1 -1
  174. package/lib/execution/builder/apiClient.d.ts +14 -8
  175. package/lib/execution/builder/apiClient.d.ts.map +1 -1
  176. package/lib/execution/builder/apiClient.js +12 -10
  177. package/lib/execution/builder/apiClient.js.map +1 -1
  178. package/lib/execution/builder/http.d.ts +2 -0
  179. package/lib/execution/builder/http.d.ts.map +1 -1
  180. package/lib/execution/builder/http.js +2 -0
  181. package/lib/execution/builder/http.js.map +1 -1
  182. package/lib/execution/engine/blobVersionedHashes.d.ts +1 -1
  183. package/lib/execution/engine/blobVersionedHashes.d.ts.map +1 -1
  184. package/lib/execution/engine/blobVersionedHashes.js.map +1 -1
  185. package/lib/execution/engine/http.d.ts +2 -2
  186. package/lib/execution/engine/http.d.ts.map +1 -1
  187. package/lib/execution/engine/http.js +5 -5
  188. package/lib/execution/engine/http.js.map +1 -1
  189. package/lib/execution/engine/index.d.ts +1 -1
  190. package/lib/execution/engine/index.d.ts.map +1 -1
  191. package/lib/execution/engine/index.js +1 -1
  192. package/lib/execution/engine/index.js.map +1 -1
  193. package/lib/execution/engine/interface.d.ts +17 -3
  194. package/lib/execution/engine/interface.d.ts.map +1 -1
  195. package/lib/execution/engine/interface.js.map +1 -1
  196. package/lib/execution/engine/jsonRpcTransport.d.ts +2 -2
  197. package/lib/execution/engine/jsonRpcTransport.d.ts.map +1 -1
  198. package/lib/execution/engine/jsonRpcTransport.js +1 -1
  199. package/lib/execution/engine/jsonRpcTransport.js.map +1 -1
  200. package/lib/execution/engine/mock.d.ts.map +1 -1
  201. package/lib/execution/engine/mock.js +6 -4
  202. package/lib/execution/engine/mock.js.map +1 -1
  203. package/lib/execution/engine/payloadIdCache.d.ts +1 -2
  204. package/lib/execution/engine/payloadIdCache.d.ts.map +1 -1
  205. package/lib/execution/engine/payloadIdCache.js +3 -3
  206. package/lib/execution/engine/payloadIdCache.js.map +1 -1
  207. package/lib/execution/engine/restTransport.d.ts +2 -2
  208. package/lib/execution/engine/restTransport.d.ts.map +1 -1
  209. package/lib/execution/engine/restTransport.js.map +1 -1
  210. package/lib/execution/engine/sszTypes.d.ts +38 -38
  211. package/lib/execution/engine/transport.d.ts +1 -12
  212. package/lib/execution/engine/transport.d.ts.map +1 -1
  213. package/lib/execution/engine/types.d.ts +1 -1
  214. package/lib/execution/engine/types.d.ts.map +1 -1
  215. package/lib/execution/engine/types.js +9 -8
  216. package/lib/execution/engine/types.js.map +1 -1
  217. package/lib/execution/engine/utils.d.ts.map +1 -1
  218. package/lib/execution/engine/utils.js +3 -2
  219. package/lib/execution/engine/utils.js.map +1 -1
  220. package/lib/index.d.ts +1 -0
  221. package/lib/index.d.ts.map +1 -1
  222. package/lib/index.js +2 -0
  223. package/lib/index.js.map +1 -1
  224. package/lib/metrics/metrics/lodestar.d.ts +7 -0
  225. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  226. package/lib/metrics/metrics/lodestar.js +15 -0
  227. package/lib/metrics/metrics/lodestar.js.map +1 -1
  228. package/lib/metrics/server/http.js +5 -5
  229. package/lib/metrics/server/http.js.map +1 -1
  230. package/lib/monitoring/service.js +1 -1
  231. package/lib/monitoring/service.js.map +1 -1
  232. package/lib/network/core/networkCore.d.ts +2 -0
  233. package/lib/network/core/networkCore.d.ts.map +1 -1
  234. package/lib/network/core/networkCore.js +3 -0
  235. package/lib/network/core/networkCore.js.map +1 -1
  236. package/lib/network/core/networkCoreWorker.js +1 -0
  237. package/lib/network/core/networkCoreWorker.js.map +1 -1
  238. package/lib/network/core/networkCoreWorkerHandler.d.ts +2 -0
  239. package/lib/network/core/networkCoreWorkerHandler.d.ts.map +1 -1
  240. package/lib/network/core/networkCoreWorkerHandler.js +3 -0
  241. package/lib/network/core/networkCoreWorkerHandler.js.map +1 -1
  242. package/lib/network/core/types.d.ts +2 -0
  243. package/lib/network/core/types.d.ts.map +1 -1
  244. package/lib/network/gossip/gossipsub.d.ts +1 -0
  245. package/lib/network/gossip/gossipsub.d.ts.map +1 -1
  246. package/lib/network/gossip/gossipsub.js +10 -0
  247. package/lib/network/gossip/gossipsub.js.map +1 -1
  248. package/lib/network/gossip/topic.d.ts +6 -6
  249. package/lib/network/interface.d.ts +2 -0
  250. package/lib/network/interface.d.ts.map +1 -1
  251. package/lib/network/libp2p/index.d.ts.map +1 -1
  252. package/lib/network/libp2p/index.js +5 -1
  253. package/lib/network/libp2p/index.js.map +1 -1
  254. package/lib/network/network.d.ts +4 -1
  255. package/lib/network/network.d.ts.map +1 -1
  256. package/lib/network/network.js +45 -15
  257. package/lib/network/network.js.map +1 -1
  258. package/lib/network/options.d.ts +2 -0
  259. package/lib/network/options.d.ts.map +1 -1
  260. package/lib/network/options.js.map +1 -1
  261. package/lib/network/peers/peerManager.d.ts +2 -1
  262. package/lib/network/peers/peerManager.d.ts.map +1 -1
  263. package/lib/network/peers/peerManager.js +28 -1
  264. package/lib/network/peers/peerManager.js.map +1 -1
  265. package/lib/network/peers/utils/assertPeerRelevance.d.ts +9 -1
  266. package/lib/network/peers/utils/assertPeerRelevance.d.ts.map +1 -1
  267. package/lib/network/peers/utils/assertPeerRelevance.js +32 -21
  268. package/lib/network/peers/utils/assertPeerRelevance.js.map +1 -1
  269. package/lib/network/peers/utils/prioritizePeers.d.ts +4 -1
  270. package/lib/network/peers/utils/prioritizePeers.d.ts.map +1 -1
  271. package/lib/network/peers/utils/prioritizePeers.js +8 -16
  272. package/lib/network/peers/utils/prioritizePeers.js.map +1 -1
  273. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  274. package/lib/network/processor/gossipHandlers.js +60 -37
  275. package/lib/network/processor/gossipHandlers.js.map +1 -1
  276. package/lib/network/processor/index.d.ts +6 -0
  277. package/lib/network/processor/index.d.ts.map +1 -1
  278. package/lib/network/processor/index.js +29 -3
  279. package/lib/network/processor/index.js.map +1 -1
  280. package/lib/node/nodejs.d.ts +3 -1
  281. package/lib/node/nodejs.d.ts.map +1 -1
  282. package/lib/node/nodejs.js +47 -21
  283. package/lib/node/nodejs.js.map +1 -1
  284. package/lib/node/options.d.ts +3 -1
  285. package/lib/node/options.d.ts.map +1 -1
  286. package/lib/node/options.js +4 -2
  287. package/lib/node/options.js.map +1 -1
  288. package/lib/sync/interface.d.ts.map +1 -1
  289. package/lib/sync/interface.js.map +1 -1
  290. package/lib/sync/sync.d.ts +7 -0
  291. package/lib/sync/sync.d.ts.map +1 -1
  292. package/lib/sync/sync.js +61 -3
  293. package/lib/sync/sync.js.map +1 -1
  294. package/lib/sync/unknownBlock.d.ts.map +1 -1
  295. package/lib/sync/unknownBlock.js +42 -18
  296. package/lib/sync/unknownBlock.js.map +1 -1
  297. package/lib/util/execution.d.ts +4 -4
  298. package/lib/util/execution.d.ts.map +1 -1
  299. package/lib/util/execution.js.map +1 -1
  300. package/lib/util/file.d.ts.map +1 -1
  301. package/lib/util/file.js +8 -9
  302. package/lib/util/file.js.map +1 -1
  303. package/lib/util/queue/itemQueue.js +1 -1
  304. package/lib/util/queue/itemQueue.js.map +1 -1
  305. package/lib/util/sszBytes.d.ts +5 -0
  306. package/lib/util/sszBytes.d.ts.map +1 -1
  307. package/lib/util/sszBytes.js +35 -2
  308. package/lib/util/sszBytes.js.map +1 -1
  309. package/package.json +31 -32
  310. package/src/api/impl/api.ts +1 -1
  311. package/src/api/impl/beacon/blocks/index.ts +57 -62
  312. package/src/api/impl/beacon/index.ts +3 -1
  313. package/src/api/impl/beacon/pool/index.ts +5 -1
  314. package/src/api/impl/beacon/state/utils.ts +1 -1
  315. package/src/api/impl/validator/index.ts +47 -30
  316. package/src/api/options.ts +3 -0
  317. package/src/chain/GetBlobsTracker.ts +99 -40
  318. package/src/chain/archiveStore/archiveStore.ts +1 -0
  319. package/src/chain/archiveStore/utils/archiveBlocks.ts +76 -130
  320. package/src/chain/blocks/importBlock.ts +40 -71
  321. package/src/chain/blocks/importExecutionPayload.ts +57 -35
  322. package/src/chain/blocks/index.ts +11 -4
  323. package/src/chain/blocks/payloadEnvelopeProcessor.ts +35 -24
  324. package/src/chain/blocks/types.ts +4 -1
  325. package/src/chain/blocks/verifyBlock.ts +31 -16
  326. package/src/chain/blocks/verifyBlocksDataAvailability.ts +10 -1
  327. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +1 -1
  328. package/src/chain/blocks/verifyBlocksSanityChecks.ts +4 -1
  329. package/src/chain/blocks/verifyBlocksSignatures.ts +7 -5
  330. package/src/chain/blocks/verifyPayloadsDataAvailability.ts +14 -6
  331. package/src/chain/bls/interface.ts +2 -0
  332. package/src/chain/bls/multithread/index.ts +14 -10
  333. package/src/chain/bls/multithread/types.ts +1 -1
  334. package/src/chain/bls/multithread/worker.ts +1 -5
  335. package/src/chain/bls/singleThread.ts +1 -1
  336. package/src/chain/bls/utils.ts +1 -1
  337. package/src/chain/chain.ts +67 -8
  338. package/src/chain/errors/blockError.ts +1 -1
  339. package/src/chain/errors/executionPayloadEnvelope.ts +8 -0
  340. package/src/chain/forkChoice/index.ts +11 -0
  341. package/src/chain/forkChoiceExecutionEngine.ts +197 -0
  342. package/src/chain/interface.ts +5 -5
  343. package/src/chain/opPools/aggregatedAttestationPool.ts +25 -9
  344. package/src/chain/opPools/attestationPool.ts +16 -4
  345. package/src/chain/opPools/inclusionListStore.ts +3 -3
  346. package/src/chain/opPools/payloadAttestationPool.ts +18 -7
  347. package/src/chain/opPools/syncCommitteeMessagePool.ts +10 -3
  348. package/src/chain/opPools/syncContributionAndProofPool.ts +13 -3
  349. package/src/chain/opPools/utils.ts +1 -1
  350. package/src/chain/options.ts +0 -2
  351. package/src/chain/produceBlock/produceBlockBody.ts +4 -3
  352. package/src/chain/regen/interface.ts +1 -2
  353. package/src/chain/regen/queued.ts +6 -4
  354. package/src/chain/validation/executionPayloadBid.ts +14 -193
  355. package/src/chain/validation/executionPayloadEnvelope.ts +68 -1
  356. package/src/chain/validation/inclusionList.ts +11 -2
  357. package/src/db/beacon.ts +44 -0
  358. package/src/db/dataColumnStore.ts +2 -4
  359. package/src/db/flatFileStore/flatFileStore.ts +7 -7
  360. package/src/db/flatFileStore/slotIndex.ts +4 -3
  361. package/src/db/interface.ts +2 -0
  362. package/src/db/repositories/dataColumnSidecarArchive.ts +20 -0
  363. package/src/execution/builder/apiClient.ts +16 -13
  364. package/src/execution/builder/http.ts +4 -0
  365. package/src/execution/engine/blobVersionedHashes.ts +1 -1
  366. package/src/execution/engine/http.ts +12 -14
  367. package/src/execution/engine/index.ts +1 -1
  368. package/src/execution/engine/interface.ts +19 -3
  369. package/src/execution/engine/jsonRpcTransport.ts +10 -2
  370. package/src/execution/engine/mock.ts +6 -4
  371. package/src/execution/engine/payloadIdCache.ts +6 -7
  372. package/src/execution/engine/restTransport.ts +3 -1
  373. package/src/execution/engine/transport.ts +8 -14
  374. package/src/execution/engine/types.ts +11 -9
  375. package/src/execution/engine/utils.ts +4 -2
  376. package/src/index.ts +2 -0
  377. package/src/metrics/metrics/lodestar.ts +15 -0
  378. package/src/metrics/server/http.ts +5 -5
  379. package/src/monitoring/service.ts +1 -1
  380. package/src/network/core/networkCore.ts +5 -0
  381. package/src/network/core/networkCoreWorker.ts +1 -0
  382. package/src/network/core/networkCoreWorkerHandler.ts +4 -0
  383. package/src/network/core/types.ts +2 -0
  384. package/src/network/gossip/gossipsub.ts +11 -0
  385. package/src/network/interface.ts +2 -0
  386. package/src/network/libp2p/index.ts +5 -1
  387. package/src/network/network.ts +45 -19
  388. package/src/network/options.ts +2 -0
  389. package/src/network/peers/peerManager.ts +28 -3
  390. package/src/network/peers/utils/assertPeerRelevance.ts +39 -23
  391. package/src/network/peers/utils/prioritizePeers.ts +14 -22
  392. package/src/network/processor/gossipHandlers.ts +72 -40
  393. package/src/network/processor/index.ts +25 -3
  394. package/src/node/nodejs.ts +58 -22
  395. package/src/node/options.ts +9 -6
  396. package/src/sync/interface.ts +1 -0
  397. package/src/sync/sync.ts +65 -4
  398. package/src/sync/unknownBlock.ts +47 -28
  399. package/src/util/execution.ts +6 -6
  400. package/src/util/file.ts +8 -9
  401. package/src/util/queue/itemQueue.ts +1 -1
  402. package/src/util/sszBytes.ts +42 -2
@@ -19,10 +19,9 @@ export type WithdrawalV1 = {
19
19
  amount: QUANTITY;
20
20
  };
21
21
 
22
- type FcuAttributes = {headBlockHash: DATA; finalizedBlockHash: DATA} & Omit<
23
- PayloadAttributesRpc,
24
- "withdrawals" | "inclusionListTransactions"
25
- > & {inclusionListTransactions?: bellatrix.Transactions};
22
+ type FcuAttributes = {headBlockHash: DATA} & Omit<PayloadAttributesRpc, "withdrawals" | "inclusionListTransactions"> & {
23
+ inclusionListTransactions?: bellatrix.Transactions;
24
+ };
26
25
 
27
26
  export class PayloadIdCache {
28
27
  private readonly payloadIdByFcuAttributes = new Map<
@@ -30,8 +29,8 @@ export class PayloadIdCache {
30
29
  {payloadId: PayloadId; fullKey: string; inclusionListTransactions?: bellatrix.Transactions}
31
30
  >();
32
31
 
33
- getFullKey({headBlockHash, finalizedBlockHash, timestamp, prevRandao, suggestedFeeRecipient}: FcuAttributes): string {
34
- return `${headBlockHash}-${finalizedBlockHash}-${timestamp}-${prevRandao}-${suggestedFeeRecipient}`;
32
+ getFullKey({headBlockHash, timestamp, prevRandao, suggestedFeeRecipient}: FcuAttributes): string {
33
+ return `${headBlockHash}-${timestamp}-${prevRandao}-${suggestedFeeRecipient}`;
35
34
  }
36
35
  getKey({timestamp}: Pick<FcuAttributes, "timestamp">): string {
37
36
  return timestamp;
@@ -69,5 +68,5 @@ function isSameInclusionList(a?: bellatrix.Transactions, b?: bellatrix.Transacti
69
68
  if (a === undefined || b === undefined) {
70
69
  return a === b;
71
70
  }
72
- return a.length === b.length && a.every((transaction, i) => byteArrayEquals(transaction, b[i]));
71
+ return byteArrayEquals(a.bytes, b.bytes);
73
72
  }
@@ -19,8 +19,10 @@ import {
19
19
  ClientCode,
20
20
  ClientVersion,
21
21
  ExecutionPayloadStatus,
22
+ ForkchoiceUpdatedResult,
22
23
  PayloadAttributes,
23
24
  PayloadId,
25
+ PayloadStatusResult,
24
26
  VersionedHashes,
25
27
  } from "./interface.js";
26
28
  import {JsonRpcHttpClientEventEmitter, ReqOpts} from "./jsonRpcHttpClient.js";
@@ -57,7 +59,7 @@ import {
57
59
  PayloadStatusSsz,
58
60
  executionForkName,
59
61
  } from "./sszTypes.js";
60
- import {ForkchoiceUpdatedResult, GetPayloadResult, IEngineTransport, PayloadStatusResult} from "./transport.js";
62
+ import {GetPayloadResult, IEngineTransport} from "./transport.js";
61
63
  import {EngineTransportMetrics} from "./transportMetrics.js";
62
64
  import {
63
65
  ExecutionPayloadBodyV2,
@@ -2,23 +2,17 @@ import {ForkName} from "@lodestar/params";
2
2
  import {BlobsBundle, ExecutionPayload, ExecutionRequests, Root, RootHex, Wei, bellatrix} from "@lodestar/types";
3
3
  import {BlobAndProof} from "@lodestar/types/deneb";
4
4
  import {BlobAndProofV2} from "@lodestar/types/fulu";
5
- import {ClientVersion, ExecutionPayloadStatus, PayloadAttributes, PayloadId, VersionedHashes} from "./interface.js";
5
+ import {
6
+ ClientVersion,
7
+ ForkchoiceUpdatedResult,
8
+ PayloadAttributes,
9
+ PayloadId,
10
+ PayloadStatusResult,
11
+ VersionedHashes,
12
+ } from "./interface.js";
6
13
  import {JsonRpcHttpClientEventEmitter} from "./jsonRpcHttpClient.js";
7
14
  import {ExecutionPayloadBodyV2} from "./types.js";
8
15
 
9
- export type PayloadStatusResult = {
10
- status: ExecutionPayloadStatus;
11
- latestValidHash: RootHex | null;
12
- validationError: string | null;
13
- /** PayloadStatusV2: whether a VALID payload satisfied the inclusion list constraints, null otherwise */
14
- inclusionListSatisfied?: boolean | null;
15
- };
16
-
17
- export type ForkchoiceUpdatedResult = {
18
- payloadStatus: PayloadStatusResult;
19
- payloadId: PayloadId | null;
20
- };
21
-
22
16
  export type GetPayloadResult = {
23
17
  executionPayload: ExecutionPayload;
24
18
  executionPayloadValue: Wei;
@@ -1,4 +1,4 @@
1
- import {Type} from "@chainsafe/ssz";
1
+ import {SerializedList, Type} from "@chainsafe/ssz";
2
2
  import {
3
3
  BUILDER_DEPOSIT_REQUEST_TYPE,
4
4
  BUILDER_EXIT_REQUEST_TYPE,
@@ -9,6 +9,7 @@ import {
9
9
  DEPOSIT_REQUEST_TYPE,
10
10
  FIELD_ELEMENTS_PER_BLOB,
11
11
  ForkName,
12
+ ForkPostElectra,
12
13
  ForkSeq,
13
14
  WITHDRAWAL_REQUEST_TYPE,
14
15
  } from "@lodestar/params";
@@ -23,6 +24,7 @@ import {
23
24
  deneb,
24
25
  gloas,
25
26
  ssz,
27
+ sszTypesFor,
26
28
  } from "@lodestar/types";
27
29
  import {BlobAndProof} from "@lodestar/types/deneb";
28
30
  import {BlobAndProofV2} from "@lodestar/types/fulu";
@@ -181,7 +183,7 @@ export type ExecutionPayloadBodyRpc = {
181
183
  };
182
184
 
183
185
  export type ExecutionPayloadBody = {
184
- transactions: bellatrix.Transaction[];
186
+ transactions: bellatrix.Transactions;
185
187
  withdrawals: capella.Withdrawals | null;
186
188
  };
187
189
 
@@ -316,7 +318,7 @@ export function serializeExecutionPayload(fork: ForkName, data: ExecutionPayload
316
318
  extraData: bytesToData(data.extraData),
317
319
  baseFeePerGas: numToQuantity(data.baseFeePerGas),
318
320
  blockHash: bytesToData(data.blockHash),
319
- transactions: data.transactions.map((tran) => bytesToData(tran)),
321
+ transactions: Array.from(data.transactions, (tran) => bytesToData(tran)),
320
322
  };
321
323
 
322
324
  // Capella adds withdrawals to the ExecutionPayload
@@ -400,7 +402,7 @@ export function parseExecutionPayload(
400
402
  extraData: dataToBytes(data.extraData, null),
401
403
  baseFeePerGas: quantityToBigint(data.baseFeePerGas),
402
404
  blockHash: dataToBytes(data.blockHash, 32),
403
- transactions: data.transactions.map((tran) => dataToBytes(tran, null)),
405
+ transactions: SerializedList.fromArray(data.transactions.map((tran) => dataToBytes(tran, null))),
404
406
  };
405
407
 
406
408
  if (ForkSeq[fork] >= ForkSeq.capella) {
@@ -474,11 +476,11 @@ export function serializeBeaconBlockRoot(data: Root): DATA {
474
476
  }
475
477
 
476
478
  export function serializeInclusionList(data: bellatrix.Transactions): InclusionListRpc {
477
- return data.map((transaction) => bytesToData(transaction));
479
+ return Array.from(data, (transaction) => bytesToData(transaction));
478
480
  }
479
481
 
480
482
  export function deserializeInclusionList(data: InclusionListRpc): bellatrix.Transactions {
481
- return data.map((transaction) => dataToBytes(transaction, null));
483
+ return SerializedList.fromArray(data.map((transaction) => dataToBytes(transaction, null)));
482
484
  }
483
485
 
484
486
  export function deserializePayloadAttributes(data: PayloadAttributesRpc): PayloadAttributes {
@@ -628,7 +630,7 @@ export function deserializeExecutionRequestsFromBytes(fork: ForkName, serialized
628
630
 
629
631
  switch (currentRequestType) {
630
632
  case DEPOSIT_REQUEST_TYPE: {
631
- result.deposits = ssz.electra.DepositRequests.deserialize(requests);
633
+ result.deposits = sszTypesFor(fork as ForkPostElectra).DepositRequests.deserialize(requests);
632
634
  break;
633
635
  }
634
636
  case WITHDRAWAL_REQUEST_TYPE: {
@@ -670,7 +672,7 @@ export function deserializeExecutionRequests(fork: ForkName, serialized: Executi
670
672
  export function deserializeExecutionPayloadBody(data: ExecutionPayloadBodyRpc | null): ExecutionPayloadBody | null {
671
673
  return data
672
674
  ? {
673
- transactions: data.transactions.map((tran) => dataToBytes(tran, null)),
675
+ transactions: SerializedList.fromArray(data.transactions.map((tran) => dataToBytes(tran, null))),
674
676
  withdrawals: data.withdrawals ? data.withdrawals.map(deserializeWithdrawal) : null,
675
677
  }
676
678
  : null;
@@ -693,7 +695,7 @@ export function serializeExecutionPayloadBodyV2(data: ExecutionPayloadBodyV2 | n
693
695
  export function serializeExecutionPayloadBody(data: ExecutionPayloadBody | null): ExecutionPayloadBodyRpc | null {
694
696
  return data
695
697
  ? {
696
- transactions: data.transactions.map((tran) => bytesToData(tran)),
698
+ transactions: Array.from(data.transactions, (tran) => bytesToData(tran)),
697
699
  withdrawals: data.withdrawals ? data.withdrawals.map(serializeWithdrawal) : null,
698
700
  }
699
701
  : null;
@@ -169,14 +169,16 @@ function getExecutionEngineStateForPayloadStatus(payloadStatus: ExecutionPayload
169
169
  return ExecutionEngineState.SYNCED;
170
170
 
171
171
  case ExecutionPayloadStatus.ELERROR:
172
- case ExecutionPayloadStatus.INVALID:
173
172
  case ExecutionPayloadStatus.SYNCING:
174
- case ExecutionPayloadStatus.INVALID_BLOCK_HASH:
175
173
  return ExecutionEngineState.SYNCING;
176
174
 
177
175
  case ExecutionPayloadStatus.UNAVAILABLE:
178
176
  return ExecutionEngineState.OFFLINE;
179
177
 
178
+ case ExecutionPayloadStatus.INVALID:
179
+ case ExecutionPayloadStatus.INVALID_BLOCK_HASH:
180
+ return ExecutionEngineState.ONLINE;
181
+
180
182
  default:
181
183
  // In case we can't determine the state, we assume it stays in old state
182
184
  // This assumption is better than considering offline, because the offline state may trigger some notifications
package/src/index.ts CHANGED
@@ -6,6 +6,8 @@ export {persistAnchorState} from "./chain/index.js";
6
6
  export {DbCPStateDatastore} from "./chain/stateCache/datastore/db.js";
7
7
  export {FileCPStateDatastore} from "./chain/stateCache/datastore/file.js";
8
8
  export {BeaconDb, type IBeaconDb} from "./db/index.js";
9
+ // Export execution engine to make it usable by builder
10
+ export {ExecutionPayloadStatus, initializeExecutionEngine} from "./execution/index.js";
9
11
  // Export metrics utilities to de-duplicate validator metrics
10
12
  export {
11
13
  type HttpMetricsServer,
@@ -645,6 +645,11 @@ export function createLodestarMetrics(
645
645
  help: "Count of peers by sync type [FullySynced, Advanced, Behind]",
646
646
  labelNames: ["syncType"],
647
647
  }),
648
+ syncPeerFinalizedCheckpointMismatch: register.counter<{reason: string}>({
649
+ name: "lodestar_sync_peer_finalized_checkpoint_mismatch_total",
650
+ help: "Total behind peers whose Status finalized checkpoint is not in our chain, by reason",
651
+ labelNames: ["reason"],
652
+ }),
648
653
  syncSwitchGossipSubscriptions: register.gauge<{action: string}>({
649
654
  name: "lodestar_sync_switch_gossip_subscriptions",
650
655
  help: "Sync switched gossip subscriptions on/off",
@@ -1008,6 +1013,11 @@ export function createLodestarMetrics(
1008
1013
  help: "Time elapsed between block received and fully verified state, signatures and payload",
1009
1014
  buckets: [0.05, 0.1, 0.3, 0.5, 0.7, 1, 1.3, 1.6, 2, 2.5, 3, 3.5, 4],
1010
1015
  }),
1016
+ receivedToConsensusVerifiedTime: register.histogram({
1017
+ name: "lodestar_gossip_block_received_to_consensus_verified_seconds",
1018
+ help: "Time from gossip block arrival until both the state transition and all block signature verifications are complete, excluding execution payload verification",
1019
+ buckets: [0.01, 0.015, 0.02, 0.025, 0.03, 0.04, 0.5, 1],
1020
+ }),
1011
1021
  verifiedToBlobsAvailabiltyTime: register.histogram<{numBlobs: number}>({
1012
1022
  name: "lodestar_gossip_block_verified_to_blobs_availability_time",
1013
1023
  help: "Time elapsed between block verified and blobs became available",
@@ -1474,6 +1484,11 @@ export function createLodestarMetrics(
1474
1484
  help: "Total number of InsertOutcome as a result of adding an execution payload bid from gossip to the pool",
1475
1485
  labelNames: ["insertOutcome"],
1476
1486
  }),
1487
+ apiInsertOutcome: register.counter<{insertOutcome: InsertOutcome}>({
1488
+ name: "lodestar_oppool_execution_payload_bid_pool_api_insert_outcome_total",
1489
+ help: "Total number of InsertOutcome as a result of adding an execution payload bid from api to the pool",
1490
+ labelNames: ["insertOutcome"],
1491
+ }),
1477
1492
  apiValidationTime: register.histogram({
1478
1493
  name: "lodestar_api_execution_payload_bid_validation_time_seconds",
1479
1494
  help: "Time elapsed for signed execution payload bid validation - api path",
@@ -44,16 +44,16 @@ export async function getHttpMetricsServer(
44
44
  ): Promise<void> {
45
45
  if (req.method === "GET" && req.url && req.url.includes("/metrics")) {
46
46
  const timer = scrapeTimeMetric.startTimer();
47
- const metricsRes = await Promise.all([wrapError(register.metrics()), getOtherMetrics()]);
48
- timer({status: metricsRes[0].err ? RequestStatus.error : RequestStatus.success});
47
+ const metricsRes = await wrapError(Promise.all([register.metrics(), getOtherMetrics()]));
48
+ timer({status: metricsRes.err ? RequestStatus.error : RequestStatus.success});
49
49
 
50
50
  // Ensure we only writeHead once
51
- if (metricsRes[0].err) {
52
- res.writeHead(500, {"content-type": "text/plain"}).end(metricsRes[0].err.stack);
51
+ if (metricsRes.err) {
52
+ res.writeHead(500, {"content-type": "text/plain"}).end(metricsRes.err.stack);
53
53
  } else {
54
54
  // Get scrape time metrics
55
55
  const httpServerMetrics = await httpServerRegister.metrics();
56
- const metrics = [metricsRes[0].result, httpServerMetrics, ...metricsRes[1]];
56
+ const metrics = [metricsRes.result[0], httpServerMetrics, ...metricsRes.result[1]];
57
57
  const metricsStr = metrics.join("\n\n");
58
58
  res.writeHead(200, {"content-type": register.contentType}).end(metricsStr);
59
59
  }
@@ -101,7 +101,7 @@ export class MonitoringService {
101
101
  if (this.monitoringInterval) {
102
102
  clearTimeout(this.monitoringInterval);
103
103
  }
104
- if (this.pendingRequest) {
104
+ if (this.pendingRequest !== undefined) {
105
105
  this.fetchAbortController?.abort(FetchAbortReason.Close);
106
106
  await this.pendingRequest;
107
107
  }
@@ -10,6 +10,7 @@ import {isForkPostFulu} from "@lodestar/params";
10
10
  import {ResponseIncoming} from "@lodestar/reqresp";
11
11
  import {Epoch, Status, fulu, sszTypesFor} from "@lodestar/types";
12
12
  import {formatNodePeer} from "../../api/impl/node/utils.js";
13
+ import {GoodByeReasonCode} from "../../constants/index.js";
13
14
  import {RegistryMetricCreator} from "../../metrics/index.js";
14
15
  import {ClockEvent, IClock} from "../../util/clock.js";
15
16
  import {CustodyConfig} from "../../util/dataColumns.js";
@@ -332,6 +333,10 @@ export class NetworkCore implements INetworkCore {
332
333
  this.peerManager.reStatusPeers(peers);
333
334
  }
334
335
 
336
+ async goodbyeAndDisconnect(peer: PeerIdStr, reason: GoodByeReasonCode): Promise<void> {
337
+ await this.peerManager.goodbyeAndDisconnect(peerIdFromString(peer), reason);
338
+ }
339
+
335
340
  /**
336
341
  * Request att subnets up `toSlot`. Network will ensure to mantain some peers for each
337
342
  */
@@ -138,6 +138,7 @@ const libp2pWorkerApi: NetworkWorkerApi = {
138
138
  prepareSyncCommitteeSubnets: (subscriptions) => core.prepareSyncCommitteeSubnets(subscriptions),
139
139
  reportPeer: (peer, action, actionName) => core.reportPeer(peer, action, actionName),
140
140
  reStatusPeers: (peers) => core.reStatusPeers(peers),
141
+ goodbyeAndDisconnect: (peer, reason) => core.goodbyeAndDisconnect(peer, reason),
141
142
  subscribeGossipCoreTopics: () => core.subscribeGossipCoreTopics(),
142
143
  unsubscribeGossipCoreTopics: () => core.unsubscribeGossipCoreTopics(),
143
144
 
@@ -11,6 +11,7 @@ import type {LoggerNode} from "@lodestar/logger/node";
11
11
  import {ResponseIncoming, ResponseOutgoing} from "@lodestar/reqresp";
12
12
  import {Status} from "@lodestar/types";
13
13
  import {withTimeout} from "@lodestar/utils";
14
+ import {GoodByeReasonCode} from "../../constants/index.js";
14
15
  import {Metrics} from "../../metrics/index.js";
15
16
  import {AsyncIterableBridgeCaller, AsyncIterableBridgeHandler} from "../../util/asyncIterableToEvents.js";
16
17
  import {PeerIdStr, peerIdFromString} from "../../util/peerId.js";
@@ -205,6 +206,9 @@ export class WorkerNetworkCore implements INetworkCore {
205
206
  reStatusPeers(peers: PeerIdStr[]): Promise<void> {
206
207
  return this.getApi().reStatusPeers(peers);
207
208
  }
209
+ goodbyeAndDisconnect(peer: PeerIdStr, reason: GoodByeReasonCode): Promise<void> {
210
+ return this.getApi().goodbyeAndDisconnect(peer, reason);
211
+ }
208
212
  reportPeer(peer: PeerIdStr, action: PeerAction, actionName: string): Promise<void> {
209
213
  return this.getApi().reportPeer(peer, action, actionName);
210
214
  }
@@ -5,6 +5,7 @@ import {SpecJson} from "@lodestar/config";
5
5
  import {LoggerNodeOpts} from "@lodestar/logger/node";
6
6
  import {ResponseIncoming} from "@lodestar/reqresp";
7
7
  import {Status} from "@lodestar/types";
8
+ import {GoodByeReasonCode} from "../../constants/index.js";
8
9
  import {PeerIdStr} from "../../util/peerId.js";
9
10
  import {NetworkOptions} from "../options.js";
10
11
  import {PeerAction, PeerScoreStats} from "../peers/index.js";
@@ -53,6 +54,7 @@ export interface INetworkCore extends INetworkCorePublic {
53
54
  // Sync method
54
55
  reportPeer(peer: PeerIdStr, action: PeerAction, actionName: string): void;
55
56
  reStatusPeers(peers: PeerIdStr[]): Promise<void>;
57
+ goodbyeAndDisconnect(peer: PeerIdStr, reason: GoodByeReasonCode): Promise<void>;
56
58
 
57
59
  // TODO: Duplicated methods with INetwork interface
58
60
  getConnectedPeers(): Promise<PeerIdStr[]>;
@@ -108,6 +108,7 @@ type GossipSubInternal = GossipSub & {
108
108
  score: {score: (peerIdStr: string) => number};
109
109
  direct: Set<string>;
110
110
  topics: Map<string, Set<string>>;
111
+ streamsOutbound: ReadonlyMap<string, unknown>;
111
112
  start: () => Promise<void>;
112
113
  stop: () => Promise<void>;
113
114
  publish: (topic: TopicStr, data: Uint8Array, opts?: PublishOpts) => Promise<PublishResult>;
@@ -248,6 +249,16 @@ export class Eth2Gossipsub {
248
249
  return this.gossipsub.getMeshPeers(topic);
249
250
  }
250
251
 
252
+ getSubscribersWithOutboundStream(topic: GossipTopic): Set<string> {
253
+ const topicStr = stringifyGossipTopic(this.config, topic);
254
+ const peers = new Set<string>();
255
+ for (const peer of this.gossipsub.getSubscribers(topicStr)) {
256
+ const id = peer.toString();
257
+ if (this.gossipsub.streamsOutbound.has(id)) peers.add(id);
258
+ }
259
+ return peers;
260
+ }
261
+
251
262
  publish(topic: TopicStr, data: Uint8Array, opts?: PublishOpts): Promise<PublishResult> {
252
263
  return this.gossipsub.publish(topic, data, opts);
253
264
  }
@@ -37,6 +37,7 @@ import {
37
37
  phase0,
38
38
  } from "@lodestar/types";
39
39
  import {BlockInputSource} from "../chain/blocks/blockInput/types.js";
40
+ import {GoodByeReasonCode} from "../constants/index.js";
40
41
  import {CustodyConfig} from "../util/dataColumns.js";
41
42
  import {PeerIdStr} from "../util/peerId.js";
42
43
  import {
@@ -74,6 +75,7 @@ export interface INetwork extends INetworkCorePublic {
74
75
  reportPeer(peer: PeerIdStr, action: PeerAction, actionName: string): void;
75
76
  shouldAggregate(subnet: SubnetID, slot: Slot): boolean;
76
77
  reStatusPeers(peers: PeerIdStr[]): Promise<void>;
78
+ goodbyeAndDisconnect(peer: PeerIdStr, reason: GoodByeReasonCode): Promise<void>;
77
79
  searchUnknownBlock(slotRoot: SlotRootHex, source: BlockInputSource, peer?: PeerIdStr): void;
78
80
  searchUnknownEnvelope(slotRoot: SlotRootHex, source: BlockInputSource, peer?: PeerIdStr): void;
79
81
  // ReqResp
@@ -150,7 +150,11 @@ export async function createNodeJsLibp2p(
150
150
  nodeInfo: {
151
151
  name: "lodestar",
152
152
  version: networkOpts.version ?? "unknown",
153
- userAgent: networkOpts.private ? "" : networkOpts.version ? `lodestar/${networkOpts.version}` : "lodestar",
153
+ userAgent: networkOpts.private
154
+ ? ""
155
+ : networkOpts.advertiseVersion && networkOpts.version
156
+ ? `lodestar/${networkOpts.version}`
157
+ : "lodestar",
154
158
  },
155
159
  addresses: {
156
160
  listen: localMultiaddrs,
@@ -30,10 +30,11 @@ import {
30
30
  isGloasDataColumnSidecar,
31
31
  phase0,
32
32
  } from "@lodestar/types";
33
- import {prettyPrintIndices, sleep} from "@lodestar/utils";
33
+ import {defer, prettyPrintIndices, sleep} from "@lodestar/utils";
34
34
  import {BlockInputSource} from "../chain/blocks/blockInput/types.js";
35
35
  import {ChainEvent, IBeaconChain} from "../chain/index.js";
36
36
  import {computeSubnetForDataColumnSidecar} from "../chain/validation/dataColumnSidecar.js";
37
+ import {GoodByeReasonCode} from "../constants/index.js";
37
38
  import {IBeaconDb} from "../db/interface.js";
38
39
  import {Metrics, RegistryMetricCreator} from "../metrics/index.js";
39
40
  import {IClock} from "../util/clock.js";
@@ -127,6 +128,7 @@ export class Network implements INetwork {
127
128
 
128
129
  private subscribedToCoreTopics = false;
129
130
  private connectedPeersSyncMeta = new Map<PeerIdStr, Omit<PeerSyncMeta, "peerId">>();
131
+ private closePromise: Promise<void> | undefined;
130
132
 
131
133
  constructor(modules: NetworkModules) {
132
134
  this.peerId = peerIdFromPrivateKey(modules.privateKey);
@@ -144,12 +146,8 @@ export class Network implements INetwork {
144
146
  this.events.on(NetworkEvent.peerConnected, this.onPeerConnected);
145
147
  this.events.on(NetworkEvent.peerDisconnected, this.onPeerDisconnected);
146
148
  this.chain.emitter.on(routes.events.EventType.head, this.onHead);
147
- this.chain.emitter.on(routes.events.EventType.lightClientFinalityUpdate, ({data}) =>
148
- this.onLightClientFinalityUpdate(data)
149
- );
150
- this.chain.emitter.on(routes.events.EventType.lightClientOptimisticUpdate, ({data}) =>
151
- this.onLightClientOptimisticUpdate(data)
152
- );
149
+ this.chain.emitter.on(routes.events.EventType.lightClientFinalityUpdate, this.onLightClientFinalityUpdate);
150
+ this.chain.emitter.on(routes.events.EventType.lightClientOptimisticUpdate, this.onLightClientOptimisticUpdate);
153
151
  this.chain.emitter.on(ChainEvent.updateTargetCustodyGroupCount, this.onTargetGroupCountUpdated);
154
152
  this.chain.emitter.on(ChainEvent.publishDataColumns, this.onPublishDataColumns);
155
153
  this.chain.emitter.on(ChainEvent.publishBlobSidecars, this.onPublishBlobSidecars);
@@ -239,9 +237,16 @@ export class Network implements INetwork {
239
237
  return this.controller.signal.aborted;
240
238
  }
241
239
 
242
- /** Destroy this instance. Can only be called once. */
243
- async close(): Promise<void> {
244
- if (this.closed) return;
240
+ close(): Promise<void> {
241
+ if (this.closePromise !== undefined) return this.closePromise;
242
+ const completion = defer<void>();
243
+ this.closePromise = completion.promise;
244
+ void this.closeInternal().then(completion.resolve, completion.reject);
245
+ return this.closePromise;
246
+ }
247
+
248
+ private async closeInternal(): Promise<void> {
249
+ this.controller.abort();
245
250
 
246
251
  this.events.off(NetworkEvent.peerConnected, this.onPeerConnected);
247
252
  this.events.off(NetworkEvent.peerDisconnected, this.onPeerDisconnected);
@@ -253,10 +258,12 @@ export class Network implements INetwork {
253
258
  this.chain.emitter.off(ChainEvent.publishBlobSidecars, this.onPublishBlobSidecars);
254
259
  this.chain.emitter.off(ChainEvent.publishProposerSlashing, this.onPublishProposerSlashing);
255
260
  this.chain.emitter.off(ChainEvent.updateStatus, this.onUpdateStatus);
256
- await this.core.close();
257
-
258
- // Used only for sleep() statements
259
- this.controller.abort();
261
+ this.connectedPeersSyncMeta.clear();
262
+ this.subscribedToCoreTopics = false;
263
+ const results = await Promise.allSettled([this.networkProcessor.stop(), this.core.close()]);
264
+ for (const result of results) {
265
+ if (result.status === "rejected") throw result.reason;
266
+ }
260
267
  this.logger.debug("network core closed");
261
268
  }
262
269
 
@@ -289,6 +296,10 @@ export class Network implements INetwork {
289
296
  return this.core.reStatusPeers(peers);
290
297
  }
291
298
 
299
+ async goodbyeAndDisconnect(peer: PeerIdStr, reason: GoodByeReasonCode): Promise<void> {
300
+ return this.core.goodbyeAndDisconnect(peer, reason);
301
+ }
302
+
292
303
  searchUnknownBlock(slotRoot: SlotRootHex, source: BlockInputSource, peer?: PeerIdStr): void {
293
304
  this.networkProcessor.searchUnknownBlock(slotRoot, source, peer);
294
305
  }
@@ -328,6 +339,7 @@ export class Network implements INetwork {
328
339
  async subscribeGossipCoreTopics(): Promise<void> {
329
340
  if (!this.subscribedToCoreTopics) {
330
341
  await this.core.subscribeGossipCoreTopics();
342
+ if (this.closed) return;
331
343
  // Only mark subscribedToCoreTopics if worker resolved this call
332
344
  this.subscribedToCoreTopics = true;
333
345
  }
@@ -798,26 +810,32 @@ export class Network implements INetwork {
798
810
  return this.core.writeDiscv5HeapSnapshot(prefix, dirpath);
799
811
  }
800
812
 
801
- private onLightClientFinalityUpdate = async (finalityUpdate: LightClientFinalityUpdate): Promise<void> => {
813
+ private onLightClientFinalityUpdate = async ({
814
+ data: finalityUpdate,
815
+ }: routes.events.EventData[routes.events.EventType.lightClientFinalityUpdate]): Promise<void> => {
802
816
  // TODO: Review is OK to remove if (this.hasAttachedSyncCommitteeMember())
803
817
 
804
818
  try {
805
819
  // messages SHOULD be broadcast after SYNC_MESSAGE_DUE_BPS of slot has transpired
806
820
  // https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/altair/light-client/p2p-interface.md#sync-committee
807
821
  await this.waitForSyncMessageCutoff(finalityUpdate.signatureSlot);
822
+ if (this.closed) return;
808
823
  await this.publishLightClientFinalityUpdate(finalityUpdate);
809
824
  } catch (e) {
810
825
  this.logger.debug("Error on BeaconGossipHandler.onLightclientFinalityUpdate", {}, e as Error);
811
826
  }
812
827
  };
813
828
 
814
- private onLightClientOptimisticUpdate = async (optimisticUpdate: LightClientOptimisticUpdate): Promise<void> => {
829
+ private onLightClientOptimisticUpdate = async ({
830
+ data: optimisticUpdate,
831
+ }: routes.events.EventData[routes.events.EventType.lightClientOptimisticUpdate]): Promise<void> => {
815
832
  // TODO: Review is OK to remove if (this.hasAttachedSyncCommitteeMember())
816
833
 
817
834
  try {
818
835
  // messages SHOULD be broadcast after SYNC_MESSAGE_DUE_BPS of slot has transpired
819
836
  // https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/altair/light-client/p2p-interface.md#sync-committee
820
837
  await this.waitForSyncMessageCutoff(optimisticUpdate.signatureSlot);
838
+ if (this.closed) return;
821
839
  await this.publishLightClientOptimisticUpdate(optimisticUpdate);
822
840
  } catch (e) {
823
841
  this.logger.debug("Error on BeaconGossipHandler.onLightclientOptimisticUpdate", {}, e as Error);
@@ -854,8 +872,12 @@ export class Network implements INetwork {
854
872
  this.connectedPeersSyncMeta.delete(data.peer);
855
873
  };
856
874
 
857
- private onTargetGroupCountUpdated = (count: number): void => {
858
- this.core.setTargetGroupCount(count);
875
+ private onTargetGroupCountUpdated = async (count: number): Promise<void> => {
876
+ try {
877
+ await this.core.setTargetGroupCount(count);
878
+ } catch (error) {
879
+ this.logger.error("Error updating network custody group count", {count}, error as Error);
880
+ }
859
881
  };
860
882
 
861
883
  private onPublishDataColumns = async (sidecars: DataColumnSidecar[]): Promise<void> => {
@@ -879,6 +901,10 @@ export class Network implements INetwork {
879
901
  };
880
902
 
881
903
  private onUpdateStatus = async (): Promise<void> => {
882
- await this.core.updateStatus(this.chain.getStatus());
904
+ try {
905
+ await this.core.updateStatus(this.chain.getStatus());
906
+ } catch (error) {
907
+ this.logger.error("Error updating network status", {}, error as Error);
908
+ }
883
909
  };
884
910
  }
@@ -25,6 +25,8 @@ export interface NetworkOptions
25
25
  mdns?: boolean;
26
26
  connectToDiscv5Bootnodes?: boolean;
27
27
  version?: string;
28
+ /** Include the version in libp2p Identify. Private mode takes precedence. */
29
+ advertiseVersion?: boolean;
28
30
  private?: boolean;
29
31
  useWorker?: boolean;
30
32
  maxYoungGenerationSizeMb?: number;
@@ -14,6 +14,7 @@ import {NetworkCoreMetrics} from "../core/metrics.js";
14
14
  import {LodestarDiscv5Opts} from "../discv5/types.js";
15
15
  import {INetworkEventBus, NetworkEvent, NetworkEventData} from "../events.js";
16
16
  import {Eth2Gossipsub} from "../gossip/gossipsub.js";
17
+ import {GossipType} from "../gossip/interface.js";
17
18
  import {Libp2p} from "../interface.js";
18
19
  import {SubnetType} from "../metadata.js";
19
20
  import {NetworkConfig} from "../networkConfig.js";
@@ -577,6 +578,8 @@ export class PeerManager {
577
578
  this.lastStatus = status;
578
579
  this.metrics?.peerManager.starved.set(starved ? 1 : 0);
579
580
  const forkSeq = this.config.getForkSeq(this.clock.currentSlot);
581
+ const boundary = this.config.getForkBoundaryAtEpoch(this.clock.currentEpoch);
582
+ const connectedHealthyPeerIds = new Set(connectedHealthyPeers.map((peer) => peer.toString()));
580
583
 
581
584
  const prioritizeTimer = this.metrics?.peerManager.prioritizePeersDuration.startTimer();
582
585
  const {peersToDisconnect, peersToConnect, attnetQueries, syncnetQueries, custodyGroupQueries} = prioritizePeers(
@@ -594,8 +597,30 @@ export class PeerManager {
594
597
  };
595
598
  }),
596
599
  // Collect subnets which we need peers for in the current slot
597
- this.attnetsService.getActiveSubnets(),
598
- this.syncnetsService.getActiveSubnets(),
600
+ this.attnetsService.getActiveSubnets().map((request) => {
601
+ const subscribers = this.gossipsub.getSubscribersWithOutboundStream({
602
+ type: GossipType.beacon_attestation,
603
+ boundary,
604
+ subnet: request.subnet,
605
+ });
606
+ let peerCount = 0;
607
+ for (const peer of subscribers) {
608
+ if (connectedHealthyPeerIds.has(peer)) peerCount++;
609
+ }
610
+ return {...request, peerCount};
611
+ }),
612
+ this.syncnetsService.getActiveSubnets().map((request) => {
613
+ const subscribers = this.gossipsub.getSubscribersWithOutboundStream({
614
+ type: GossipType.sync_committee,
615
+ boundary,
616
+ subnet: request.subnet,
617
+ });
618
+ let peerCount = 0;
619
+ for (const peer of subscribers) {
620
+ if (connectedHealthyPeerIds.has(peer)) peerCount++;
621
+ }
622
+ return {...request, peerCount};
623
+ }),
599
624
  // ignore samplingGroups for pre-fulu forks
600
625
  forkSeq >= ForkSeq.fulu ? this.networkConfig.custodyConfig.sampleGroups : undefined,
601
626
  {
@@ -893,7 +918,7 @@ export class PeerManager {
893
918
  }
894
919
  }
895
920
 
896
- private async goodbyeAndDisconnect(peer: PeerId, goodbye: GoodByeReasonCode): Promise<void> {
921
+ async goodbyeAndDisconnect(peer: PeerId, goodbye: GoodByeReasonCode): Promise<void> {
897
922
  const reason = GOODBYE_KNOWN_CODES[goodbye.toString()] || "";
898
923
  const peerIdStr = peer.toString();
899
924
  try {