@lodestar/beacon-node 1.43.0-dev.bc569affb9 → 1.43.0-dev.c98da75ec7

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 (352) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +16 -5
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
  5. package/lib/api/impl/beacon/pool/index.js +86 -2
  6. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  7. package/lib/api/impl/debug/index.d.ts.map +1 -1
  8. package/lib/api/impl/debug/index.js +0 -1
  9. package/lib/api/impl/debug/index.js.map +1 -1
  10. package/lib/api/impl/lodestar/index.js +1 -1
  11. package/lib/api/impl/lodestar/index.js.map +1 -1
  12. package/lib/api/impl/validator/index.d.ts.map +1 -1
  13. package/lib/api/impl/validator/index.js +68 -2
  14. package/lib/api/impl/validator/index.js.map +1 -1
  15. package/lib/chain/blocks/blockInput/blockInput.d.ts +3 -0
  16. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  17. package/lib/chain/blocks/blockInput/blockInput.js +4 -1
  18. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  19. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  20. package/lib/chain/blocks/importBlock.js +16 -28
  21. package/lib/chain/blocks/importBlock.js.map +1 -1
  22. package/lib/chain/blocks/importExecutionPayload.d.ts +23 -6
  23. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  24. package/lib/chain/blocks/importExecutionPayload.js +57 -24
  25. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  26. package/lib/chain/blocks/index.d.ts +5 -3
  27. package/lib/chain/blocks/index.d.ts.map +1 -1
  28. package/lib/chain/blocks/index.js +58 -25
  29. package/lib/chain/blocks/index.js.map +1 -1
  30. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +12 -1
  31. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
  32. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +28 -2
  33. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
  34. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +17 -0
  35. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
  36. package/lib/chain/blocks/payloadEnvelopeProcessor.js +2 -2
  37. package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
  38. package/lib/chain/blocks/types.d.ts +4 -3
  39. package/lib/chain/blocks/types.d.ts.map +1 -1
  40. package/lib/chain/blocks/utils/chainSegment.d.ts +21 -2
  41. package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
  42. package/lib/chain/blocks/utils/chainSegment.js +92 -12
  43. package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
  44. package/lib/chain/blocks/verifyBlock.d.ts +5 -3
  45. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  46. package/lib/chain/blocks/verifyBlock.js +50 -7
  47. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  48. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +0 -4
  49. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  50. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +5 -2
  51. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  52. package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts +2 -1
  53. package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
  54. package/lib/chain/blocks/verifyBlocksSanityChecks.js +25 -5
  55. package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
  56. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +2 -2
  57. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -1
  58. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +12 -8
  59. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -1
  60. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -1
  61. package/lib/chain/blocks/verifyPayloadsDataAvailability.js +8 -3
  62. package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -1
  63. package/lib/chain/chain.d.ts +5 -3
  64. package/lib/chain/chain.d.ts.map +1 -1
  65. package/lib/chain/chain.js +38 -13
  66. package/lib/chain/chain.js.map +1 -1
  67. package/lib/chain/emitter.d.ts +0 -11
  68. package/lib/chain/emitter.d.ts.map +1 -1
  69. package/lib/chain/emitter.js +0 -4
  70. package/lib/chain/emitter.js.map +1 -1
  71. package/lib/chain/errors/blockError.d.ts +8 -1
  72. package/lib/chain/errors/blockError.d.ts.map +1 -1
  73. package/lib/chain/errors/blockError.js +2 -0
  74. package/lib/chain/errors/blockError.js.map +1 -1
  75. package/lib/chain/errors/executionPayloadBid.d.ts +19 -1
  76. package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
  77. package/lib/chain/errors/executionPayloadBid.js +3 -0
  78. package/lib/chain/errors/executionPayloadBid.js.map +1 -1
  79. package/lib/chain/errors/index.d.ts +1 -0
  80. package/lib/chain/errors/index.d.ts.map +1 -1
  81. package/lib/chain/errors/index.js +1 -0
  82. package/lib/chain/errors/index.js.map +1 -1
  83. package/lib/chain/errors/proposerPreferences.d.ts +40 -0
  84. package/lib/chain/errors/proposerPreferences.d.ts.map +1 -0
  85. package/lib/chain/errors/proposerPreferences.js +14 -0
  86. package/lib/chain/errors/proposerPreferences.js.map +1 -0
  87. package/lib/chain/initState.d.ts.map +1 -1
  88. package/lib/chain/initState.js +6 -1
  89. package/lib/chain/initState.js.map +1 -1
  90. package/lib/chain/interface.d.ts +5 -3
  91. package/lib/chain/interface.d.ts.map +1 -1
  92. package/lib/chain/interface.js.map +1 -1
  93. package/lib/chain/lightClient/index.d.ts.map +1 -1
  94. package/lib/chain/lightClient/index.js +1 -1
  95. package/lib/chain/lightClient/index.js.map +1 -1
  96. package/lib/chain/opPools/index.d.ts +1 -0
  97. package/lib/chain/opPools/index.d.ts.map +1 -1
  98. package/lib/chain/opPools/index.js +1 -0
  99. package/lib/chain/opPools/index.js.map +1 -1
  100. package/lib/chain/opPools/payloadAttestationPool.d.ts +4 -3
  101. package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -1
  102. package/lib/chain/opPools/payloadAttestationPool.js +56 -14
  103. package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
  104. package/lib/chain/opPools/proposerPreferencesPool.d.ts +29 -0
  105. package/lib/chain/opPools/proposerPreferencesPool.d.ts.map +1 -0
  106. package/lib/chain/opPools/proposerPreferencesPool.js +56 -0
  107. package/lib/chain/opPools/proposerPreferencesPool.js.map +1 -0
  108. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  109. package/lib/chain/prepareNextSlot.js +16 -18
  110. package/lib/chain/prepareNextSlot.js.map +1 -1
  111. package/lib/chain/produceBlock/produceBlockBody.d.ts +12 -3
  112. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  113. package/lib/chain/produceBlock/produceBlockBody.js +35 -17
  114. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  115. package/lib/chain/regen/interface.d.ts +1 -0
  116. package/lib/chain/regen/interface.d.ts.map +1 -1
  117. package/lib/chain/regen/interface.js +1 -0
  118. package/lib/chain/regen/interface.js.map +1 -1
  119. package/lib/chain/regen/queued.d.ts.map +1 -1
  120. package/lib/chain/regen/queued.js +1 -4
  121. package/lib/chain/regen/queued.js.map +1 -1
  122. package/lib/chain/regen/regen.d.ts.map +1 -1
  123. package/lib/chain/regen/regen.js +1 -4
  124. package/lib/chain/regen/regen.js.map +1 -1
  125. package/lib/chain/seenCache/index.d.ts +1 -0
  126. package/lib/chain/seenCache/index.d.ts.map +1 -1
  127. package/lib/chain/seenCache/index.js +1 -0
  128. package/lib/chain/seenCache/index.js.map +1 -1
  129. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +21 -11
  130. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
  131. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +70 -20
  132. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
  133. package/lib/chain/seenCache/seenProposerPreferences.d.ts +16 -0
  134. package/lib/chain/seenCache/seenProposerPreferences.d.ts.map +1 -0
  135. package/lib/chain/seenCache/seenProposerPreferences.js +26 -0
  136. package/lib/chain/seenCache/seenProposerPreferences.js.map +1 -0
  137. package/lib/chain/validation/block.d.ts.map +1 -1
  138. package/lib/chain/validation/block.js +1 -0
  139. package/lib/chain/validation/block.js.map +1 -1
  140. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  141. package/lib/chain/validation/executionPayloadBid.js +68 -17
  142. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  143. package/lib/chain/validation/payloadAttestationMessage.d.ts +1 -1
  144. package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
  145. package/lib/chain/validation/payloadAttestationMessage.js +5 -3
  146. package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
  147. package/lib/chain/validation/proposerPreferences.d.ts +8 -0
  148. package/lib/chain/validation/proposerPreferences.d.ts.map +1 -0
  149. package/lib/chain/validation/proposerPreferences.js +91 -0
  150. package/lib/chain/validation/proposerPreferences.js.map +1 -0
  151. package/lib/metrics/metrics/lodestar.d.ts +5 -0
  152. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  153. package/lib/metrics/metrics/lodestar.js +9 -0
  154. package/lib/metrics/metrics/lodestar.js.map +1 -1
  155. package/lib/network/gossip/interface.d.ts +7 -1
  156. package/lib/network/gossip/interface.d.ts.map +1 -1
  157. package/lib/network/gossip/interface.js +1 -0
  158. package/lib/network/gossip/interface.js.map +1 -1
  159. package/lib/network/gossip/scoringParameters.d.ts.map +1 -1
  160. package/lib/network/gossip/scoringParameters.js +12 -1
  161. package/lib/network/gossip/scoringParameters.js.map +1 -1
  162. package/lib/network/gossip/topic.d.ts +29 -766
  163. package/lib/network/gossip/topic.d.ts.map +1 -1
  164. package/lib/network/gossip/topic.js +6 -0
  165. package/lib/network/gossip/topic.js.map +1 -1
  166. package/lib/network/interface.d.ts +3 -0
  167. package/lib/network/interface.d.ts.map +1 -1
  168. package/lib/network/network.d.ts +3 -0
  169. package/lib/network/network.d.ts.map +1 -1
  170. package/lib/network/network.js +13 -0
  171. package/lib/network/network.js.map +1 -1
  172. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  173. package/lib/network/processor/gossipHandlers.js +77 -20
  174. package/lib/network/processor/gossipHandlers.js.map +1 -1
  175. package/lib/network/processor/gossipQueues/index.d.ts.map +1 -1
  176. package/lib/network/processor/gossipQueues/index.js +5 -0
  177. package/lib/network/processor/gossipQueues/index.js.map +1 -1
  178. package/lib/network/processor/index.d.ts.map +1 -1
  179. package/lib/network/processor/index.js +6 -5
  180. package/lib/network/processor/index.js.map +1 -1
  181. package/lib/network/reqresp/ReqRespBeaconNode.d.ts.map +1 -1
  182. package/lib/network/reqresp/ReqRespBeaconNode.js +1 -1
  183. package/lib/network/reqresp/ReqRespBeaconNode.js.map +1 -1
  184. package/lib/network/reqresp/handlers/beaconBlocksByHead.d.ts +9 -0
  185. package/lib/network/reqresp/handlers/beaconBlocksByHead.d.ts.map +1 -0
  186. package/lib/network/reqresp/handlers/beaconBlocksByHead.js +61 -0
  187. package/lib/network/reqresp/handlers/beaconBlocksByHead.js.map +1 -0
  188. package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
  189. package/lib/network/reqresp/handlers/beaconBlocksByRange.js +14 -6
  190. package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
  191. package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts.map +1 -1
  192. package/lib/network/reqresp/handlers/blobSidecarsByRange.js +11 -5
  193. package/lib/network/reqresp/handlers/blobSidecarsByRange.js.map +1 -1
  194. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
  195. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +17 -5
  196. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
  197. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -1
  198. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +7 -4
  199. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
  200. package/lib/network/reqresp/handlers/index.d.ts.map +1 -1
  201. package/lib/network/reqresp/handlers/index.js +5 -0
  202. package/lib/network/reqresp/handlers/index.js.map +1 -1
  203. package/lib/network/reqresp/interface.d.ts +1 -1
  204. package/lib/network/reqresp/interface.js +1 -1
  205. package/lib/network/reqresp/protocols.d.ts +1 -0
  206. package/lib/network/reqresp/protocols.d.ts.map +1 -1
  207. package/lib/network/reqresp/protocols.js +5 -0
  208. package/lib/network/reqresp/protocols.js.map +1 -1
  209. package/lib/network/reqresp/rateLimit.d.ts.map +1 -1
  210. package/lib/network/reqresp/rateLimit.js +4 -0
  211. package/lib/network/reqresp/rateLimit.js.map +1 -1
  212. package/lib/network/reqresp/score.d.ts.map +1 -1
  213. package/lib/network/reqresp/score.js +1 -0
  214. package/lib/network/reqresp/score.js.map +1 -1
  215. package/lib/network/reqresp/types.d.ts +3 -0
  216. package/lib/network/reqresp/types.d.ts.map +1 -1
  217. package/lib/network/reqresp/types.js +3 -0
  218. package/lib/network/reqresp/types.js.map +1 -1
  219. package/lib/node/nodejs.js +2 -2
  220. package/lib/node/nodejs.js.map +1 -1
  221. package/lib/sync/constants.d.ts +7 -1
  222. package/lib/sync/constants.d.ts.map +1 -1
  223. package/lib/sync/constants.js +7 -4
  224. package/lib/sync/constants.js.map +1 -1
  225. package/lib/sync/range/batch.d.ts +55 -8
  226. package/lib/sync/range/batch.d.ts.map +1 -1
  227. package/lib/sync/range/batch.js +291 -66
  228. package/lib/sync/range/batch.js.map +1 -1
  229. package/lib/sync/range/chain.d.ts +22 -4
  230. package/lib/sync/range/chain.d.ts.map +1 -1
  231. package/lib/sync/range/chain.js +103 -11
  232. package/lib/sync/range/chain.js.map +1 -1
  233. package/lib/sync/range/range.d.ts.map +1 -1
  234. package/lib/sync/range/range.js +71 -11
  235. package/lib/sync/range/range.js.map +1 -1
  236. package/lib/sync/range/utils/peerBalancer.d.ts +2 -1
  237. package/lib/sync/range/utils/peerBalancer.d.ts.map +1 -1
  238. package/lib/sync/range/utils/peerBalancer.js +8 -4
  239. package/lib/sync/range/utils/peerBalancer.js.map +1 -1
  240. package/lib/sync/sync.d.ts.map +1 -1
  241. package/lib/sync/sync.js +13 -0
  242. package/lib/sync/sync.js.map +1 -1
  243. package/lib/sync/types.d.ts +34 -0
  244. package/lib/sync/types.d.ts.map +1 -1
  245. package/lib/sync/types.js +34 -0
  246. package/lib/sync/types.js.map +1 -1
  247. package/lib/sync/unknownBlock.d.ts +29 -1
  248. package/lib/sync/unknownBlock.d.ts.map +1 -1
  249. package/lib/sync/unknownBlock.js +727 -61
  250. package/lib/sync/unknownBlock.js.map +1 -1
  251. package/lib/sync/utils/downloadByRange.d.ts +73 -10
  252. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  253. package/lib/sync/utils/downloadByRange.js +213 -26
  254. package/lib/sync/utils/downloadByRange.js.map +1 -1
  255. package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
  256. package/lib/sync/utils/downloadByRoot.js +16 -2
  257. package/lib/sync/utils/downloadByRoot.js.map +1 -1
  258. package/lib/sync/utils/pendingBlocksTree.d.ts +0 -1
  259. package/lib/sync/utils/pendingBlocksTree.d.ts.map +1 -1
  260. package/lib/sync/utils/pendingBlocksTree.js +0 -9
  261. package/lib/sync/utils/pendingBlocksTree.js.map +1 -1
  262. package/lib/sync/utils/rateLimit.d.ts +2 -0
  263. package/lib/sync/utils/rateLimit.d.ts.map +1 -0
  264. package/lib/sync/utils/rateLimit.js +15 -0
  265. package/lib/sync/utils/rateLimit.js.map +1 -0
  266. package/lib/util/dependentRoot.d.ts +6 -2
  267. package/lib/util/dependentRoot.d.ts.map +1 -1
  268. package/lib/util/dependentRoot.js +20 -16
  269. package/lib/util/dependentRoot.js.map +1 -1
  270. package/lib/util/sszBytes.d.ts.map +1 -1
  271. package/lib/util/sszBytes.js +8 -6
  272. package/lib/util/sszBytes.js.map +1 -1
  273. package/package.json +15 -16
  274. package/src/api/impl/beacon/blocks/index.ts +21 -5
  275. package/src/api/impl/beacon/pool/index.ts +136 -1
  276. package/src/api/impl/debug/index.ts +0 -1
  277. package/src/api/impl/lodestar/index.ts +1 -1
  278. package/src/api/impl/validator/index.ts +82 -1
  279. package/src/chain/blocks/blockInput/blockInput.ts +4 -1
  280. package/src/chain/blocks/importBlock.ts +16 -48
  281. package/src/chain/blocks/importExecutionPayload.ts +76 -30
  282. package/src/chain/blocks/index.ts +71 -22
  283. package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +37 -3
  284. package/src/chain/blocks/payloadEnvelopeInput/types.ts +18 -0
  285. package/src/chain/blocks/payloadEnvelopeProcessor.ts +2 -2
  286. package/src/chain/blocks/types.ts +4 -3
  287. package/src/chain/blocks/utils/chainSegment.ts +117 -17
  288. package/src/chain/blocks/verifyBlock.ts +70 -9
  289. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +6 -4
  290. package/src/chain/blocks/verifyBlocksSanityChecks.ts +26 -7
  291. package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +16 -8
  292. package/src/chain/blocks/verifyPayloadsDataAvailability.ts +7 -4
  293. package/src/chain/chain.ts +46 -10
  294. package/src/chain/emitter.ts +0 -11
  295. package/src/chain/errors/blockError.ts +4 -1
  296. package/src/chain/errors/executionPayloadBid.ts +22 -1
  297. package/src/chain/errors/index.ts +1 -0
  298. package/src/chain/errors/proposerPreferences.ts +47 -0
  299. package/src/chain/initState.ts +9 -1
  300. package/src/chain/interface.ts +9 -1
  301. package/src/chain/lightClient/index.ts +6 -6
  302. package/src/chain/opPools/index.ts +1 -0
  303. package/src/chain/opPools/payloadAttestationPool.ts +63 -18
  304. package/src/chain/opPools/proposerPreferencesPool.ts +59 -0
  305. package/src/chain/prepareNextSlot.ts +21 -29
  306. package/src/chain/produceBlock/produceBlockBody.ts +46 -22
  307. package/src/chain/regen/interface.ts +1 -0
  308. package/src/chain/regen/queued.ts +2 -7
  309. package/src/chain/regen/regen.ts +2 -7
  310. package/src/chain/seenCache/index.ts +1 -0
  311. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +90 -24
  312. package/src/chain/seenCache/seenProposerPreferences.ts +32 -0
  313. package/src/chain/validation/block.ts +1 -0
  314. package/src/chain/validation/executionPayloadBid.ts +71 -18
  315. package/src/chain/validation/payloadAttestationMessage.ts +6 -4
  316. package/src/chain/validation/proposerPreferences.ts +110 -0
  317. package/src/metrics/metrics/lodestar.ts +10 -0
  318. package/src/network/gossip/interface.ts +6 -0
  319. package/src/network/gossip/scoringParameters.ts +14 -1
  320. package/src/network/gossip/topic.ts +6 -0
  321. package/src/network/interface.ts +3 -0
  322. package/src/network/network.ts +34 -0
  323. package/src/network/processor/gossipHandlers.ts +96 -20
  324. package/src/network/processor/gossipQueues/index.ts +5 -0
  325. package/src/network/processor/index.ts +6 -5
  326. package/src/network/reqresp/ReqRespBeaconNode.ts +1 -0
  327. package/src/network/reqresp/handlers/beaconBlocksByHead.ts +91 -0
  328. package/src/network/reqresp/handlers/beaconBlocksByRange.ts +14 -6
  329. package/src/network/reqresp/handlers/blobSidecarsByRange.ts +11 -5
  330. package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +17 -5
  331. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +7 -4
  332. package/src/network/reqresp/handlers/index.ts +5 -0
  333. package/src/network/reqresp/interface.ts +1 -1
  334. package/src/network/reqresp/protocols.ts +6 -0
  335. package/src/network/reqresp/rateLimit.ts +4 -0
  336. package/src/network/reqresp/score.ts +1 -0
  337. package/src/network/reqresp/types.ts +5 -0
  338. package/src/node/nodejs.ts +2 -2
  339. package/src/sync/constants.ts +8 -4
  340. package/src/sync/range/batch.ts +388 -75
  341. package/src/sync/range/chain.ts +131 -14
  342. package/src/sync/range/range.ts +86 -11
  343. package/src/sync/range/utils/peerBalancer.ts +9 -3
  344. package/src/sync/sync.ts +13 -1
  345. package/src/sync/types.ts +72 -0
  346. package/src/sync/unknownBlock.ts +915 -65
  347. package/src/sync/utils/downloadByRange.ts +386 -39
  348. package/src/sync/utils/downloadByRoot.ts +24 -2
  349. package/src/sync/utils/pendingBlocksTree.ts +0 -15
  350. package/src/sync/utils/rateLimit.ts +16 -0
  351. package/src/util/dependentRoot.ts +22 -18
  352. package/src/util/sszBytes.ts +8 -6
@@ -26,6 +26,7 @@ import {
26
26
  computeTimeAtSlot,
27
27
  getCurrentSlot,
28
28
  isStatePostAltair,
29
+ isStatePostGloas,
29
30
  proposerShufflingDecisionRoot,
30
31
  } from "@lodestar/state-transition";
31
32
  import {
@@ -1049,6 +1050,36 @@ export function getValidatorApi(
1049
1050
  };
1050
1051
  },
1051
1052
 
1053
+ async producePayloadAttestationData({slot}) {
1054
+ const fork = config.getForkName(slot);
1055
+ if (!isForkPostGloas(fork)) {
1056
+ throw new ApiError(400, `producePayloadAttestationData is not supported before Gloas fork=${fork}`);
1057
+ }
1058
+
1059
+ notWhileSyncing();
1060
+ await waitForSlot(slot);
1061
+
1062
+ const block = chain.forkChoice.getCanonicalBlockClosestLteSlot(slot);
1063
+ if (!block) {
1064
+ throw new ApiError(404, `No canonical block found at or before slot=${slot}`);
1065
+ }
1066
+
1067
+ const blockIsForSlot = block.slot === slot;
1068
+ const payloadInput = chain.seenPayloadEnvelopeInputCache.get(block.blockRoot);
1069
+ const payloadPresent = blockIsForSlot && (payloadInput?.hasPayloadEnvelope() ?? false);
1070
+ const blobDataAvailable = blockIsForSlot && (payloadInput?.hasAllData() ?? false);
1071
+
1072
+ return {
1073
+ data: {
1074
+ beaconBlockRoot: fromHex(block.blockRoot),
1075
+ slot,
1076
+ payloadPresent,
1077
+ blobDataAvailable,
1078
+ },
1079
+ meta: {version: fork},
1080
+ };
1081
+ },
1082
+
1052
1083
  /**
1053
1084
  * GET `/eth/v1/validator/sync_committee_contribution`
1054
1085
  *
@@ -1263,6 +1294,55 @@ export function getValidatorApi(
1263
1294
  };
1264
1295
  },
1265
1296
 
1297
+ async getPtcDuties({epoch, indices}) {
1298
+ notWhileSyncing();
1299
+
1300
+ if (indices.length === 0) {
1301
+ throw new ApiError(400, "No validator to get PTC duties");
1302
+ }
1303
+
1304
+ const startSlot = computeStartSlotAtEpoch(epoch);
1305
+ const fork = config.getForkName(startSlot);
1306
+ if (!isForkPostGloas(fork)) {
1307
+ throw new ApiError(400, `PTC duties are not supported before Gloas fork=${fork}`);
1308
+ }
1309
+
1310
+ await waitForNextClosestEpoch();
1311
+
1312
+ if (epoch > chain.clock.currentEpoch + 1) {
1313
+ throw new ApiError(400, "Cannot get PTC duties for epoch more than one ahead");
1314
+ }
1315
+
1316
+ const head = chain.forkChoice.getHead();
1317
+ const state = await chain.getHeadStateAtCurrentEpoch(RegenCaller.getDuties);
1318
+ if (!isStatePostGloas(state)) {
1319
+ throw new ApiError(400, `PTC duties are not available before Gloas fork=${state.forkName}`);
1320
+ }
1321
+
1322
+ const pubkeys = getPubkeysForIndices(state, indices);
1323
+ const ptcs = state.getEpochPTCs(epoch);
1324
+ const duties: routes.validator.PtcDuty[] = [];
1325
+ for (let i = 0, len = indices.length; i < len; i++) {
1326
+ const validatorIndex = indices[i];
1327
+ for (let j = 0; j < SLOTS_PER_EPOCH; j++) {
1328
+ if (ptcs[j].indexOf(validatorIndex) !== -1) {
1329
+ duties.push({pubkey: pubkeys[i], validatorIndex, slot: j + startSlot});
1330
+ break;
1331
+ }
1332
+ }
1333
+ }
1334
+
1335
+ const dependentRoot = fromHex(state.getShufflingDecisionRoot(epoch)) || (await getGenesisBlockRoot(state));
1336
+
1337
+ return {
1338
+ data: duties,
1339
+ meta: {
1340
+ dependentRoot: toRootHex(dependentRoot),
1341
+ executionOptimistic: isOptimisticBlock(head),
1342
+ },
1343
+ };
1344
+ },
1345
+
1266
1346
  /**
1267
1347
  * `POST /eth/v1/validator/duties/sync/{epoch}`
1268
1348
  *
@@ -1641,13 +1721,14 @@ export function getValidatorApi(
1641
1721
  throw Error("Cached block production result is not full block");
1642
1722
  }
1643
1723
 
1644
- const {executionPayload, executionRequests} = produceResult as ProduceFullGloas;
1724
+ const {executionPayload, executionRequests, parentBlockRoot} = produceResult as ProduceFullGloas;
1645
1725
 
1646
1726
  const envelope: gloas.ExecutionPayloadEnvelope = {
1647
1727
  payload: executionPayload,
1648
1728
  executionRequests: executionRequests,
1649
1729
  builderIndex: BUILDER_INDEX_SELF_BUILD,
1650
1730
  beaconBlockRoot,
1731
+ parentBeaconBlockRoot: parentBlockRoot,
1651
1732
  };
1652
1733
 
1653
1734
  logger.info("Produced execution payload envelope", {
@@ -895,8 +895,11 @@ export class BlockInputColumns extends AbstractBlockInput<ForkColumnsDA, fulu.Da
895
895
  return this.getAllColumnsWithSource().map(({columnSidecar}) => columnSidecar);
896
896
  }
897
897
 
898
+ /**
899
+ * Strictly checks missing sampled columns. Does NOT short-circuit on `state.hasAllData`.
900
+ */
898
901
  getMissingSampledColumnMeta(): MissingColumnMeta {
899
- if (this.state.hasAllData) {
902
+ if (this.state.hasComputedAllData) {
900
903
  return {
901
904
  missing: [],
902
905
  versionedHashes: this.state.versionedHashes,
@@ -9,14 +9,7 @@ import {
9
9
  NotReorgedReason,
10
10
  getSafeExecutionBlockHash,
11
11
  } from "@lodestar/fork-choice";
12
- import {
13
- ForkPostAltair,
14
- ForkPostElectra,
15
- ForkPostGloas,
16
- ForkSeq,
17
- MAX_SEED_LOOKAHEAD,
18
- SLOTS_PER_EPOCH,
19
- } from "@lodestar/params";
12
+ import {ForkPostAltair, ForkPostElectra, ForkSeq, MAX_SEED_LOOKAHEAD, SLOTS_PER_EPOCH} from "@lodestar/params";
20
13
  import {
21
14
  IBeaconStateView,
22
15
  RootCache,
@@ -27,17 +20,7 @@ import {
27
20
  isStatePostAltair,
28
21
  isStatePostBellatrix,
29
22
  } from "@lodestar/state-transition";
30
- import {
31
- Attestation,
32
- BeaconBlock,
33
- SignedBeaconBlock,
34
- altair,
35
- capella,
36
- electra,
37
- isGloasBeaconBlock,
38
- phase0,
39
- ssz,
40
- } from "@lodestar/types";
23
+ import {Attestation, BeaconBlock, altair, capella, electra, isGloasBeaconBlock, phase0, ssz} from "@lodestar/types";
41
24
  import {isErrorAborted, toRootHex} from "@lodestar/utils";
42
25
  import {ZERO_HASH_HEX} from "../../constants/index.js";
43
26
  import {callInNextEventLoop} from "../../util/eventLoop.js";
@@ -86,8 +69,8 @@ export async function importBlock(
86
69
  fullyVerifiedBlock: FullyVerifiedBlock,
87
70
  opts: ImportBlockOpts
88
71
  ): Promise<void> {
89
- const {blockInput, postState, parentBlockSlot, executionStatus, dataAvailabilityStatus, indexedAttestations} =
90
- fullyVerifiedBlock;
72
+ const {blockInput, postState, parentBlockSlot, dataAvailabilityStatus, indexedAttestations} = fullyVerifiedBlock;
73
+ let {executionStatus} = fullyVerifiedBlock;
91
74
  const block = blockInput.getBlock();
92
75
  const source = blockInput.getBlockSource();
93
76
  const {slot: blockSlot} = block.message;
@@ -122,12 +105,23 @@ export async function importBlock(
122
105
 
123
106
  // Should compute checkpoint balances before forkchoice.onBlock
124
107
  this.checkpointBalancesCache.processState(blockRootHex, postState);
108
+ if (fork >= ForkSeq.gloas) {
109
+ const parentRootHex = toRootHex(block.message.parentRoot);
110
+ const parentBlock = this.forkChoice.getBlockHexDefaultStatus(parentRootHex);
111
+ if (parentBlock === null) {
112
+ throw Error(`Parent block not found in forkChoice, parentRoot=${parentRootHex}`);
113
+ }
114
+ if (parentBlock.executionStatus === ExecutionStatus.Invalid) {
115
+ throw Error(`Parent block has invalid execution status, parentRoot=${parentRootHex}`);
116
+ }
117
+ executionStatus = parentBlock.executionStatus;
118
+ }
125
119
  const blockSummary = this.forkChoice.onBlock(
126
120
  block.message,
127
121
  postState,
128
122
  blockDelaySec,
129
123
  currentSlot,
130
- fork >= ForkSeq.gloas ? ExecutionStatus.PayloadSeparated : executionStatus,
124
+ executionStatus,
131
125
  dataAvailabilityStatus
132
126
  );
133
127
 
@@ -135,32 +129,6 @@ export async function importBlock(
135
129
  // Some block event handlers require state being in state cache so need to do this before emitting EventType.block
136
130
  this.regen.processState(blockRootHex, postState);
137
131
 
138
- // For Gloas blocks, create PayloadEnvelopeInput so it's available for later payload import
139
- if (fork >= ForkSeq.gloas) {
140
- const payloadInput = this.seenPayloadEnvelopeInputCache.add({
141
- blockRootHex,
142
- block: block as SignedBeaconBlock<ForkPostGloas>,
143
- forkName: blockInput.forkName,
144
- sampledColumns: this.custodyConfig.sampledColumns,
145
- custodyColumns: this.custodyConfig.custodyColumns,
146
- timeCreatedSec: fullyVerifiedBlock.seenTimestampSec,
147
- });
148
- this.logger.debug("Created PayloadEnvelopeInput for block", {
149
- slot: blockSlot,
150
- root: blockRootHex,
151
- source: source.source,
152
- ...(opts.seenTimestampSec !== undefined ? {recvToImport: Date.now() / 1000 - opts.seenTimestampSec} : {}),
153
- });
154
-
155
- // Immediately attempt fetch of data columns from execution engine as the bid contains kzg commitments
156
- // which is all the information we need so there is no reason to delay until execution payload arrives
157
- // TODO GLOAS: If we want EL retries after this initial attempt, add an explicit retry policy here
158
- // (for example later in the slot). Do not couple retries to incoming gossip columns.
159
- // Columns fetched here feed payloadInput.addColumn, which resolves waitForAllData for any
160
- // in-flight importExecutionPayload. No processExecutionPayload trigger needed from this path.
161
- this.getBlobsTracker.triggerGetBlobs(payloadInput);
162
- }
163
-
164
132
  this.metrics?.importBlock.bySource.inc({source: source.source});
165
133
  this.logger.verbose("Added block to forkchoice and state cache", {slot: blockSlot, root: blockRootHex});
166
134
 
@@ -1,7 +1,8 @@
1
1
  import {routes} from "@lodestar/api";
2
- import {ExecutionStatus, PayloadExecutionStatus} from "@lodestar/fork-choice";
3
- import {isStatePostGloas} from "@lodestar/state-transition";
4
- import {fromHex} from "@lodestar/utils";
2
+ import {ExecutionStatus, PayloadExecutionStatus, getSafeExecutionBlockHash} from "@lodestar/fork-choice";
3
+ import {DataAvailabilityStatus, isStatePostGloas} from "@lodestar/state-transition";
4
+ import {isErrorAborted} from "@lodestar/utils";
5
+ import {ZERO_HASH_HEX} from "../../constants/index.js";
5
6
  import {ExecutionPayloadStatus} from "../../execution/index.js";
6
7
  import {isQueueErrorAborted} from "../../util/queue/index.js";
7
8
  import {BeaconChain} from "../chain.js";
@@ -20,6 +21,7 @@ export enum PayloadErrorCode {
20
21
  EXECUTION_ENGINE_INVALID = "PAYLOAD_ERROR_EXECUTION_ENGINE_INVALID",
21
22
  EXECUTION_ENGINE_ERROR = "PAYLOAD_ERROR_EXECUTION_ENGINE_ERROR",
22
23
  BLOCK_NOT_IN_FORK_CHOICE = "PAYLOAD_ERROR_BLOCK_NOT_IN_FORK_CHOICE",
24
+ MISS_BLOCK_STATE = "PAYLOAD_ERROR_MISS_BLOCK_STATE",
23
25
  ENVELOPE_VERIFICATION_ERROR = "PAYLOAD_ERROR_ENVELOPE_VERIFICATION_ERROR",
24
26
  INVALID_SIGNATURE = "PAYLOAD_ERROR_INVALID_SIGNATURE",
25
27
  }
@@ -39,6 +41,10 @@ export type PayloadErrorType =
39
41
  code: PayloadErrorCode.BLOCK_NOT_IN_FORK_CHOICE;
40
42
  blockRootHex: string;
41
43
  }
44
+ | {
45
+ code: PayloadErrorCode.MISS_BLOCK_STATE;
46
+ blockRootHex: string;
47
+ }
42
48
  | {
43
49
  code: PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR;
44
50
  message: string;
@@ -60,7 +66,6 @@ function toForkChoiceExecutionStatus(status: ExecutionPayloadStatus): PayloadExe
60
66
  switch (status) {
61
67
  case ExecutionPayloadStatus.VALID:
62
68
  return ExecutionStatus.Valid;
63
- // TODO GLOAS: Handle optimistic import for payload
64
69
  case ExecutionPayloadStatus.SYNCING:
65
70
  case ExecutionPayloadStatus.ACCEPTED:
66
71
  return ExecutionStatus.Syncing;
@@ -75,21 +80,24 @@ function toForkChoiceExecutionStatus(status: ExecutionPayloadStatus): PayloadExe
75
80
  * The envelope is only verified here, no state mutation. State effects from the payload
76
81
  * are applied on the next block via processParentExecutionPayload.
77
82
  *
83
+ * The DA wait must have run upstream (range sync awaits DA in `verifyBlocksInEpoch` for the
84
+ * whole segment; gossip / API path uses the `processExecutionPayload` wrapper below).
85
+ *
78
86
  * Steps:
79
87
  * 1. Emit `execution_payload_available` event for payload attestation
80
88
  * 2. Get the ProtoBlock from fork choice
81
- * 3. Wait for data columns to be available
82
- * 4. Regenerate state for envelope verification
83
- * 5. Verify envelope (fields against state, signature, and EL in parallel where possible)
84
- * 6. Persist verified payload envelope to hot DB (waits for write-queue space for backpressure)
85
- * 7. Update fork choice (transitions the block's PENDING variant to FULL)
89
+ * 3. Regenerate state for envelope verification
90
+ * 4. Verify envelope (fields against state, signature, and EL in parallel where possible)
91
+ * 5. Persist verified payload envelope to hot DB (waits for write-queue space for backpressure)
92
+ * 6. Update fork choice (transitions the block's PENDING variant to FULL)
93
+ * 7. Queue notifyForkchoiceUpdate to engine api
86
94
  * 8. Record metrics for payload envelope and column sources
87
95
  * 9. Emit `execution_payload` event
88
96
  */
89
97
  export async function importExecutionPayload(
90
98
  this: BeaconChain,
91
99
  payloadInput: PayloadEnvelopeInput,
92
- signal: AbortSignal,
100
+ dataAvailabilityStatus: DataAvailabilityStatus,
93
101
  opts: ImportPayloadOpts = {}
94
102
  ): Promise<void> {
95
103
  const signedEnvelope = payloadInput.getPayloadEnvelope();
@@ -119,17 +127,20 @@ export async function importExecutionPayload(
119
127
  });
120
128
  }
121
129
 
122
- // 3. Wait for data columns to be available.
123
- // The helper is shared with future gloas sync services; take the single-item batch form here.
124
- await verifyPayloadsDataAvailability([payloadInput], signal);
130
+ // 3. Regenerate state for envelope verification
131
+ const blockState = await this.regen
132
+ .getBlockSlotState(protoBlock, protoBlock.slot, {dontTransferCache: true}, RegenCaller.processBlock)
133
+ .catch(() =>
134
+ // only happen at the 1st batch of skipped slot checkpoint sync
135
+ this.regen.getClosestHeadState(protoBlock)
136
+ );
125
137
 
126
- // 4. Regenerate state for envelope verification
127
- const blockState = await this.regen.getBlockSlotState(
128
- protoBlock,
129
- protoBlock.slot,
130
- {dontTransferCache: true},
131
- RegenCaller.processBlock
132
- );
138
+ if (blockState == null) {
139
+ throw new PayloadError({
140
+ code: PayloadErrorCode.MISS_BLOCK_STATE,
141
+ blockRootHex: protoBlock.blockRoot,
142
+ });
143
+ }
133
144
  if (!isStatePostGloas(blockState)) {
134
145
  throw new PayloadError({
135
146
  code: PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR,
@@ -137,7 +148,7 @@ export async function importExecutionPayload(
137
148
  });
138
149
  }
139
150
 
140
- // 5. Verify envelope fields against state first to fail fast before the EL + BLS work.
151
+ // 4. Verify envelope fields against state first to fail fast before the EL + BLS work.
141
152
  // When validSignature is true, gossip/API has already verified both the signature and the
142
153
  // executionRequestsRoot, so we skip those checks here.
143
154
  try {
@@ -154,13 +165,13 @@ export async function importExecutionPayload(
154
165
  );
155
166
  }
156
167
 
157
- // 5a. Run EL and signature verification in parallel
168
+ // 4a. Run EL and signature verification in parallel
158
169
  const [execResult, signatureValid] = await Promise.all([
159
170
  this.executionEngine.notifyNewPayload(
160
171
  fork,
161
172
  envelope.payload,
162
173
  payloadInput.getVersionedHashes(),
163
- fromHex(protoBlock.parentRoot),
174
+ envelope.parentBeaconBlockRoot,
164
175
  envelope.executionRequests
165
176
  ),
166
177
 
@@ -176,12 +187,12 @@ export async function importExecutionPayload(
176
187
  ),
177
188
  ]);
178
189
 
179
- // 5b. Check signature verification result
190
+ // 4b. Check signature verification result
180
191
  if (!signatureValid) {
181
192
  throw new PayloadError({code: PayloadErrorCode.INVALID_SIGNATURE});
182
193
  }
183
194
 
184
- // 5c. Handle EL response
195
+ // 4c. Handle EL response
185
196
  switch (execResult.status) {
186
197
  case ExecutionPayloadStatus.VALID:
187
198
  break;
@@ -207,7 +218,7 @@ export async function importExecutionPayload(
207
218
  });
208
219
  }
209
220
 
210
- // 6. Persist payload envelope to hot DB. Wait for write-queue space here to apply backpressure
221
+ // 5. Persist payload envelope to hot DB. Wait for write-queue space here to apply backpressure
211
222
  // on the import pipeline during sync, then perform the write asynchronously to avoid blocking.
212
223
  await this.unfinalizedPayloadEnvelopeWrites.waitForSpace();
213
224
  this.unfinalizedPayloadEnvelopeWrites.push(payloadInput).catch((e) => {
@@ -220,9 +231,27 @@ export async function importExecutionPayload(
220
231
  }
221
232
  });
222
233
 
223
- // 7. Update fork choice, transitions the block's PENDING variant to FULL
234
+ // 6. Update fork choice, transitions the block's PENDING variant to FULL
224
235
  const execStatus = toForkChoiceExecutionStatus(execResult.status);
225
- this.forkChoice.onExecutionPayload(blockRootHex, blockHashHex, envelope.payload.blockNumber, execStatus);
236
+ this.forkChoice.onExecutionPayload(
237
+ blockRootHex,
238
+ blockHashHex,
239
+ envelope.payload.blockNumber,
240
+ execStatus,
241
+ dataAvailabilityStatus
242
+ );
243
+
244
+ // 7. Queue notifyForkchoiceUpdate to engine api
245
+ const head = this.forkChoice.getHead();
246
+ if (!this.opts.disableImportExecutionFcU && blockRootHex === head.blockRoot) {
247
+ const safeBlockHash = getSafeExecutionBlockHash(this.forkChoice);
248
+ const finalizedBlockHash = this.forkChoice.getFinalizedBlock().executionPayloadBlockHash ?? ZERO_HASH_HEX;
249
+ this.executionEngine.notifyForkchoiceUpdate(fork, blockHashHex, safeBlockHash, finalizedBlockHash).catch((e) => {
250
+ if (!isErrorAborted(e) && !isQueueErrorAborted(e)) {
251
+ this.logger.error("Error pushing notifyForkchoiceUpdate()", {blockHashHex, finalizedBlockHash}, e);
252
+ }
253
+ });
254
+ }
226
255
 
227
256
  // 8. Record metrics for payload envelope and column sources
228
257
  this.metrics?.importPayload.bySource.inc({source: payloadInput.getPayloadEnvelopeSource().source});
@@ -237,8 +266,7 @@ export async function importExecutionPayload(
237
266
  builderIndex: envelope.builderIndex,
238
267
  blockHash: blockHashHex,
239
268
  blockRoot: blockRootHex,
240
- // TODO GLOAS: revisit once we support optimistic import
241
- executionOptimistic: false,
269
+ executionOptimistic: execStatus === ExecutionStatus.Syncing,
242
270
  });
243
271
  }
244
272
 
@@ -249,3 +277,21 @@ export async function importExecutionPayload(
249
277
  blockHash: blockHashHex,
250
278
  });
251
279
  }
280
+
281
+ /**
282
+ * Process an execution payload envelope end-to-end: wait for DA, then import.
283
+ *
284
+ * Used by the PayloadEnvelopeProcessor queue (gossip / API / unknown-payload sync) — i.e.
285
+ * callers that have NOT already awaited DA themselves. Range sync's inline dispatch in
286
+ * processBlocks skips this wrapper and calls `importExecutionPayload` directly, since
287
+ * `verifyBlocksInEpoch` already awaited DA for the segment.
288
+ */
289
+ export async function processExecutionPayload(
290
+ this: BeaconChain,
291
+ payloadInput: PayloadEnvelopeInput,
292
+ signal: AbortSignal,
293
+ opts: ImportPayloadOpts = {}
294
+ ): Promise<void> {
295
+ const {dataAvailabilityStatuses} = await verifyPayloadsDataAvailability([payloadInput], signal);
296
+ await importExecutionPayload.call(this, payloadInput, dataAvailabilityStatuses[0], opts);
297
+ }
@@ -1,4 +1,4 @@
1
- import {SignedBeaconBlock} from "@lodestar/types";
1
+ import {SignedBeaconBlock, Slot} from "@lodestar/types";
2
2
  import {isErrorAborted, toRootHex} from "@lodestar/utils";
3
3
  import {Metrics} from "../../metrics/metrics.js";
4
4
  import {nextEventLoop} from "../../util/eventLoop.js";
@@ -8,6 +8,8 @@ import {BlockError, BlockErrorCode, isBlockErrorAborted} from "../errors/index.j
8
8
  import {BlockProcessOpts} from "../options.js";
9
9
  import {IBlockInput} from "./blockInput/types.js";
10
10
  import {importBlock} from "./importBlock.js";
11
+ import {importExecutionPayload} from "./importExecutionPayload.js";
12
+ import {PayloadEnvelopeInput} from "./payloadEnvelopeInput/payloadEnvelopeInput.js";
11
13
  import {FullyVerifiedBlock, ImportBlockOpts} from "./types.js";
12
14
  import {assertLinearChainSegment} from "./utils/chainSegment.js";
13
15
  import {verifyBlocksInEpoch} from "./verifyBlock.js";
@@ -21,20 +23,24 @@ const QUEUE_MAX_LENGTH = 256;
21
23
  * BlockProcessor processes block jobs in a queued fashion, one after the other.
22
24
  */
23
25
  export class BlockProcessor {
24
- readonly jobQueue: JobItemQueue<[IBlockInput[], ImportBlockOpts], void>;
26
+ readonly jobQueue: JobItemQueue<[IBlockInput[], Map<Slot, PayloadEnvelopeInput> | null, ImportBlockOpts], void>;
25
27
 
26
28
  constructor(chain: BeaconChain, metrics: Metrics | null, opts: BlockProcessOpts, signal: AbortSignal) {
27
- this.jobQueue = new JobItemQueue<[IBlockInput[], ImportBlockOpts], void>(
28
- (job, importOpts) => {
29
- return processBlocks.call(chain, job, {...opts, ...importOpts});
29
+ this.jobQueue = new JobItemQueue<[IBlockInput[], Map<Slot, PayloadEnvelopeInput> | null, ImportBlockOpts], void>(
30
+ (job, payloadEnvelopes, importOpts) => {
31
+ return processBlocks.call(chain, job, payloadEnvelopes, {...opts, ...importOpts});
30
32
  },
31
33
  {maxLength: QUEUE_MAX_LENGTH, noYieldIfOneItem: true, signal},
32
34
  metrics?.blockProcessorQueue ?? undefined
33
35
  );
34
36
  }
35
37
 
36
- async processBlocksJob(job: IBlockInput[], opts: ImportBlockOpts = {}): Promise<void> {
37
- await this.jobQueue.push(job, opts);
38
+ async processBlocksJob(
39
+ job: IBlockInput[],
40
+ payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
41
+ opts: ImportBlockOpts = {}
42
+ ): Promise<void> {
43
+ await this.jobQueue.push(job, payloadEnvelopes, opts);
38
44
  }
39
45
  }
40
46
 
@@ -51,18 +57,15 @@ export class BlockProcessor {
51
57
  export async function processBlocks(
52
58
  this: BeaconChain,
53
59
  blocks: IBlockInput[],
60
+ payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
54
61
  opts: BlockProcessOpts & ImportBlockOpts
55
62
  ): Promise<void> {
56
63
  if (blocks.length === 0) {
57
64
  return; // TODO: or throw?
58
65
  }
59
66
 
60
- if (blocks.length > 1) {
61
- assertLinearChainSegment(this.config, blocks);
62
- }
63
-
64
67
  try {
65
- const {relevantBlocks, parentSlots, parentBlock} = verifyBlocksSanityChecks(this, blocks, opts);
68
+ const {relevantBlocks, parentSlots, parentBlock} = verifyBlocksSanityChecks(this, blocks, payloadEnvelopes, opts);
66
69
 
67
70
  // No relevant blocks, skip verifyBlocksInEpoch()
68
71
  if (relevantBlocks.length === 0 || parentBlock === null) {
@@ -70,10 +73,31 @@ export async function processBlocks(
70
73
  return;
71
74
  }
72
75
 
76
+ const {warnings: orphanedPayloads} = assertLinearChainSegment(
77
+ this.config,
78
+ relevantBlocks,
79
+ payloadEnvelopes,
80
+ parentBlock
81
+ );
82
+ if (orphanedPayloads != null) {
83
+ for (const orphaned of orphanedPayloads) {
84
+ this.logger.debug("Orphaned payload envelope in chain segment", {
85
+ slot: orphaned.slot,
86
+ blockRoot: orphaned.payloadEnvelopeInput.blockRootHex,
87
+ });
88
+ }
89
+ }
90
+
73
91
  // Fully verify a block to be imported immediately after. Does not produce any side-effects besides adding intermediate
74
92
  // states in the state cache through regen.
75
- const {postStates, dataAvailabilityStatuses, proposerBalanceDeltas, segmentExecStatus, indexedAttestationsByBlock} =
76
- await verifyBlocksInEpoch.call(this, parentBlock, relevantBlocks, opts);
93
+ const {
94
+ postStates,
95
+ blockDAStatuses,
96
+ payloadDAStatuses,
97
+ proposerBalanceDeltas,
98
+ segmentExecStatus,
99
+ indexedAttestationsByBlock,
100
+ } = await verifyBlocksInEpoch.call(this, parentBlock, relevantBlocks, payloadEnvelopes, opts);
77
101
 
78
102
  // If segmentExecStatus has lvhForkchoice then, the entire segment should be invalid
79
103
  // and we need to further propagate
@@ -85,24 +109,49 @@ export async function processBlocks(
85
109
  }
86
110
 
87
111
  const {executionStatuses} = segmentExecStatus;
88
- const fullyVerifiedBlocks = relevantBlocks.map(
89
- (block, i): FullyVerifiedBlock => ({
112
+ const verifiedBlocksBySlot = new Map<Slot, FullyVerifiedBlock>();
113
+ for (let i = 0; i < relevantBlocks.length; i++) {
114
+ const block = relevantBlocks[i];
115
+ verifiedBlocksBySlot.set(block.getBlock().message.slot, {
90
116
  blockInput: block,
91
117
  postState: postStates[i],
92
118
  parentBlockSlot: parentSlots[i],
93
119
  executionStatus: executionStatuses[i],
94
120
  // start supporting optimistic syncing/processing
95
- dataAvailabilityStatus: dataAvailabilityStatuses[i],
121
+ dataAvailabilityStatus: blockDAStatuses[i],
96
122
  proposerBalanceDelta: proposerBalanceDeltas[i],
97
123
  indexedAttestations: indexedAttestationsByBlock[i],
98
124
  // TODO: Make this param mandatory and capture in gossip
99
125
  seenTimestampSec: opts.seenTimestampSec ?? Math.floor(Date.now() / 1000),
100
- })
101
- );
126
+ });
127
+ }
128
+
129
+ const slotSet = new Set<Slot>(blocks.map((b) => b.getBlock().message.slot));
130
+ if (payloadEnvelopes) {
131
+ for (const slot of payloadEnvelopes.keys()) slotSet.add(slot);
132
+ }
133
+ const slots = Array.from(slotSet).sort((a, b) => a - b);
134
+ for (const slot of slots) {
135
+ const fullyVerifiedBlock = verifiedBlocksBySlot.get(slot);
136
+ if (fullyVerifiedBlock !== undefined) {
137
+ // TODO: Consider batching importBlock too if it takes significant time
138
+ await importBlock.call(this, fullyVerifiedBlock, opts);
139
+ }
140
+
141
+ const payloadInput = payloadEnvelopes?.get(slot);
142
+ if (payloadInput?.hasPayloadEnvelope()) {
143
+ if (!payloadInput.isComplete()) {
144
+ // we validated DA before reaching this
145
+ throw new Error(`Payload envelope for slot ${slot} not complete after DA verification`);
146
+ }
147
+ // we already awaited DA in verifyBlocksInEpoch for this segment
148
+ const payloadDA = payloadDAStatuses.get(slot);
149
+ if (payloadDA === undefined) {
150
+ throw new Error(`Missing payload DA status for slot ${slot}`);
151
+ }
152
+ await importExecutionPayload.call(this, payloadInput, payloadDA, {validSignature: false});
153
+ }
102
154
 
103
- for (const fullyVerifiedBlock of fullyVerifiedBlocks) {
104
- // TODO: Consider batching importBlock too if it takes significant time
105
- await importBlock.call(this, fullyVerifiedBlock, opts);
106
155
  await nextEventLoop();
107
156
  }
108
157
  } catch (e) {