@lodestar/beacon-node 1.43.0-dev.433e692fd9 → 1.43.0-dev.4451fec75a

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 (406) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +17 -9
  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 +45 -2
  6. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  7. package/lib/api/impl/beacon/state/utils.d.ts +2 -2
  8. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  9. package/lib/api/impl/beacon/state/utils.js.map +1 -1
  10. package/lib/api/impl/debug/index.d.ts.map +1 -1
  11. package/lib/api/impl/debug/index.js +0 -1
  12. package/lib/api/impl/debug/index.js.map +1 -1
  13. package/lib/api/impl/lodestar/index.js +1 -1
  14. package/lib/api/impl/lodestar/index.js.map +1 -1
  15. package/lib/api/impl/validator/index.d.ts.map +1 -1
  16. package/lib/api/impl/validator/index.js +68 -6
  17. package/lib/api/impl/validator/index.js.map +1 -1
  18. package/lib/chain/GetBlobsTracker.d.ts +1 -1
  19. package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
  20. package/lib/chain/GetBlobsTracker.js +1 -2
  21. package/lib/chain/GetBlobsTracker.js.map +1 -1
  22. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  23. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  24. package/lib/chain/archiveStore/interface.d.ts +4 -4
  25. package/lib/chain/archiveStore/interface.d.ts.map +1 -1
  26. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts +4 -4
  27. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts.map +1 -1
  28. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js.map +1 -1
  29. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +2 -2
  30. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
  31. package/lib/chain/archiveStore/utils/archiveBlocks.js +110 -58
  32. package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
  33. package/lib/chain/blocks/blockInput/blockInput.d.ts +3 -0
  34. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  35. package/lib/chain/blocks/blockInput/blockInput.js +4 -1
  36. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  37. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  38. package/lib/chain/blocks/importBlock.js +16 -32
  39. package/lib/chain/blocks/importBlock.js.map +1 -1
  40. package/lib/chain/blocks/importExecutionPayload.d.ts +32 -14
  41. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  42. package/lib/chain/blocks/importExecutionPayload.js +101 -90
  43. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  44. package/lib/chain/blocks/index.d.ts +5 -3
  45. package/lib/chain/blocks/index.d.ts.map +1 -1
  46. package/lib/chain/blocks/index.js +58 -26
  47. package/lib/chain/blocks/index.js.map +1 -1
  48. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +15 -1
  49. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
  50. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +48 -2
  51. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
  52. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +17 -0
  53. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
  54. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +5 -0
  55. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -1
  56. package/lib/chain/blocks/payloadEnvelopeProcessor.js +7 -5
  57. package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
  58. package/lib/chain/blocks/types.d.ts +15 -20
  59. package/lib/chain/blocks/types.d.ts.map +1 -1
  60. package/lib/chain/blocks/utils/chainSegment.d.ts +21 -2
  61. package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
  62. package/lib/chain/blocks/utils/chainSegment.js +92 -12
  63. package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
  64. package/lib/chain/blocks/verifyBlock.d.ts +5 -3
  65. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  66. package/lib/chain/blocks/verifyBlock.js +50 -7
  67. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  68. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +0 -4
  69. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  70. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +5 -2
  71. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  72. package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts +2 -1
  73. package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
  74. package/lib/chain/blocks/verifyBlocksSanityChecks.js +25 -5
  75. package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
  76. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +24 -0
  77. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -0
  78. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +80 -0
  79. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -0
  80. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts +14 -0
  81. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -0
  82. package/lib/chain/blocks/verifyPayloadsDataAvailability.js +30 -0
  83. package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -0
  84. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts +1 -1
  85. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts.map +1 -1
  86. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js +2 -11
  87. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js.map +1 -1
  88. package/lib/chain/chain.d.ts +8 -6
  89. package/lib/chain/chain.d.ts.map +1 -1
  90. package/lib/chain/chain.js +44 -14
  91. package/lib/chain/chain.js.map +1 -1
  92. package/lib/chain/emitter.d.ts +16 -15
  93. package/lib/chain/emitter.d.ts.map +1 -1
  94. package/lib/chain/emitter.js +5 -4
  95. package/lib/chain/emitter.js.map +1 -1
  96. package/lib/chain/errors/blockError.d.ts +8 -1
  97. package/lib/chain/errors/blockError.d.ts.map +1 -1
  98. package/lib/chain/errors/blockError.js +2 -0
  99. package/lib/chain/errors/blockError.js.map +1 -1
  100. package/lib/chain/errors/executionPayloadBid.d.ts +5 -0
  101. package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
  102. package/lib/chain/errors/executionPayloadBid.js +1 -0
  103. package/lib/chain/errors/executionPayloadBid.js.map +1 -1
  104. package/lib/chain/errors/executionPayloadEnvelope.d.ts +5 -0
  105. package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
  106. package/lib/chain/errors/executionPayloadEnvelope.js +1 -0
  107. package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
  108. package/lib/chain/errors/index.d.ts +1 -0
  109. package/lib/chain/errors/index.d.ts.map +1 -1
  110. package/lib/chain/errors/index.js +1 -0
  111. package/lib/chain/errors/index.js.map +1 -1
  112. package/lib/chain/errors/proposerPreferences.d.ts +40 -0
  113. package/lib/chain/errors/proposerPreferences.d.ts.map +1 -0
  114. package/lib/chain/errors/proposerPreferences.js +14 -0
  115. package/lib/chain/errors/proposerPreferences.js.map +1 -0
  116. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  117. package/lib/chain/forkChoice/index.js +11 -19
  118. package/lib/chain/forkChoice/index.js.map +1 -1
  119. package/lib/chain/initState.d.ts.map +1 -1
  120. package/lib/chain/initState.js +6 -1
  121. package/lib/chain/initState.js.map +1 -1
  122. package/lib/chain/interface.d.ts +7 -5
  123. package/lib/chain/interface.d.ts.map +1 -1
  124. package/lib/chain/interface.js.map +1 -1
  125. package/lib/chain/lightClient/index.d.ts.map +1 -1
  126. package/lib/chain/lightClient/index.js +1 -1
  127. package/lib/chain/lightClient/index.js.map +1 -1
  128. package/lib/chain/opPools/payloadAttestationPool.d.ts +4 -3
  129. package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -1
  130. package/lib/chain/opPools/payloadAttestationPool.js +56 -14
  131. package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
  132. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  133. package/lib/chain/prepareNextSlot.js +45 -17
  134. package/lib/chain/prepareNextSlot.js.map +1 -1
  135. package/lib/chain/produceBlock/produceBlockBody.d.ts +13 -2
  136. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  137. package/lib/chain/produceBlock/produceBlockBody.js +68 -25
  138. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  139. package/lib/chain/regen/interface.d.ts +1 -0
  140. package/lib/chain/regen/interface.d.ts.map +1 -1
  141. package/lib/chain/regen/interface.js +1 -0
  142. package/lib/chain/regen/interface.js.map +1 -1
  143. package/lib/chain/regen/queued.d.ts.map +1 -1
  144. package/lib/chain/regen/queued.js +1 -4
  145. package/lib/chain/regen/queued.js.map +1 -1
  146. package/lib/chain/regen/regen.d.ts.map +1 -1
  147. package/lib/chain/regen/regen.js +1 -4
  148. package/lib/chain/regen/regen.js.map +1 -1
  149. package/lib/chain/seenCache/index.d.ts +1 -0
  150. package/lib/chain/seenCache/index.d.ts.map +1 -1
  151. package/lib/chain/seenCache/index.js +1 -0
  152. package/lib/chain/seenCache/index.js.map +1 -1
  153. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +24 -7
  154. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
  155. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +69 -17
  156. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
  157. package/lib/chain/seenCache/seenProposerPreferences.d.ts +16 -0
  158. package/lib/chain/seenCache/seenProposerPreferences.d.ts.map +1 -0
  159. package/lib/chain/seenCache/seenProposerPreferences.js +26 -0
  160. package/lib/chain/seenCache/seenProposerPreferences.js.map +1 -0
  161. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  162. package/lib/chain/stateCache/persistentCheckpointsCache.js +4 -1
  163. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  164. package/lib/chain/validation/block.d.ts.map +1 -1
  165. package/lib/chain/validation/block.js +1 -0
  166. package/lib/chain/validation/block.js.map +1 -1
  167. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  168. package/lib/chain/validation/executionPayloadBid.js +24 -9
  169. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  170. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  171. package/lib/chain/validation/executionPayloadEnvelope.js +19 -9
  172. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  173. package/lib/chain/validation/payloadAttestationMessage.d.ts +1 -1
  174. package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
  175. package/lib/chain/validation/payloadAttestationMessage.js +9 -6
  176. package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
  177. package/lib/chain/validation/proposerPreferences.d.ts +8 -0
  178. package/lib/chain/validation/proposerPreferences.d.ts.map +1 -0
  179. package/lib/chain/validation/proposerPreferences.js +91 -0
  180. package/lib/chain/validation/proposerPreferences.js.map +1 -0
  181. package/lib/db/repositories/executionPayloadEnvelopeArchive.js +1 -1
  182. package/lib/db/repositories/executionPayloadEnvelopeArchive.js.map +1 -1
  183. package/lib/execution/engine/http.d.ts.map +1 -1
  184. package/lib/execution/engine/http.js +21 -14
  185. package/lib/execution/engine/http.js.map +1 -1
  186. package/lib/execution/engine/interface.d.ts +1 -0
  187. package/lib/execution/engine/interface.d.ts.map +1 -1
  188. package/lib/execution/engine/mock.d.ts.map +1 -1
  189. package/lib/execution/engine/mock.js +6 -0
  190. package/lib/execution/engine/mock.js.map +1 -1
  191. package/lib/execution/engine/types.d.ts +20 -0
  192. package/lib/execution/engine/types.d.ts.map +1 -1
  193. package/lib/execution/engine/types.js +18 -0
  194. package/lib/execution/engine/types.js.map +1 -1
  195. package/lib/metrics/metrics/lodestar.d.ts +5 -0
  196. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  197. package/lib/metrics/metrics/lodestar.js +9 -0
  198. package/lib/metrics/metrics/lodestar.js.map +1 -1
  199. package/lib/network/gossip/interface.d.ts +7 -1
  200. package/lib/network/gossip/interface.d.ts.map +1 -1
  201. package/lib/network/gossip/interface.js +1 -0
  202. package/lib/network/gossip/interface.js.map +1 -1
  203. package/lib/network/gossip/scoringParameters.d.ts.map +1 -1
  204. package/lib/network/gossip/scoringParameters.js +12 -1
  205. package/lib/network/gossip/scoringParameters.js.map +1 -1
  206. package/lib/network/gossip/topic.d.ts +760 -2
  207. package/lib/network/gossip/topic.d.ts.map +1 -1
  208. package/lib/network/gossip/topic.js +6 -0
  209. package/lib/network/gossip/topic.js.map +1 -1
  210. package/lib/network/interface.d.ts +2 -0
  211. package/lib/network/interface.d.ts.map +1 -1
  212. package/lib/network/network.d.ts +2 -0
  213. package/lib/network/network.d.ts.map +1 -1
  214. package/lib/network/network.js +9 -1
  215. package/lib/network/network.js.map +1 -1
  216. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  217. package/lib/network/processor/gossipHandlers.js +93 -25
  218. package/lib/network/processor/gossipHandlers.js.map +1 -1
  219. package/lib/network/processor/gossipQueues/index.d.ts.map +1 -1
  220. package/lib/network/processor/gossipQueues/index.js +5 -0
  221. package/lib/network/processor/gossipQueues/index.js.map +1 -1
  222. package/lib/network/processor/index.d.ts.map +1 -1
  223. package/lib/network/processor/index.js +6 -5
  224. package/lib/network/processor/index.js.map +1 -1
  225. package/lib/network/reqresp/ReqRespBeaconNode.d.ts.map +1 -1
  226. package/lib/network/reqresp/ReqRespBeaconNode.js +1 -1
  227. package/lib/network/reqresp/ReqRespBeaconNode.js.map +1 -1
  228. package/lib/network/reqresp/handlers/beaconBlocksByHead.d.ts +9 -0
  229. package/lib/network/reqresp/handlers/beaconBlocksByHead.d.ts.map +1 -0
  230. package/lib/network/reqresp/handlers/beaconBlocksByHead.js +61 -0
  231. package/lib/network/reqresp/handlers/beaconBlocksByHead.js.map +1 -0
  232. package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
  233. package/lib/network/reqresp/handlers/beaconBlocksByRange.js +14 -6
  234. package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
  235. package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts.map +1 -1
  236. package/lib/network/reqresp/handlers/blobSidecarsByRange.js +11 -5
  237. package/lib/network/reqresp/handlers/blobSidecarsByRange.js.map +1 -1
  238. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
  239. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +17 -5
  240. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
  241. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -1
  242. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +7 -4
  243. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
  244. package/lib/network/reqresp/handlers/index.d.ts.map +1 -1
  245. package/lib/network/reqresp/handlers/index.js +5 -0
  246. package/lib/network/reqresp/handlers/index.js.map +1 -1
  247. package/lib/network/reqresp/interface.d.ts +1 -1
  248. package/lib/network/reqresp/interface.js +1 -1
  249. package/lib/network/reqresp/protocols.d.ts +1 -0
  250. package/lib/network/reqresp/protocols.d.ts.map +1 -1
  251. package/lib/network/reqresp/protocols.js +5 -0
  252. package/lib/network/reqresp/protocols.js.map +1 -1
  253. package/lib/network/reqresp/rateLimit.d.ts.map +1 -1
  254. package/lib/network/reqresp/rateLimit.js +4 -0
  255. package/lib/network/reqresp/rateLimit.js.map +1 -1
  256. package/lib/network/reqresp/score.d.ts.map +1 -1
  257. package/lib/network/reqresp/score.js +1 -0
  258. package/lib/network/reqresp/score.js.map +1 -1
  259. package/lib/network/reqresp/types.d.ts +3 -0
  260. package/lib/network/reqresp/types.d.ts.map +1 -1
  261. package/lib/network/reqresp/types.js +3 -0
  262. package/lib/network/reqresp/types.js.map +1 -1
  263. package/lib/node/nodejs.d.ts.map +1 -1
  264. package/lib/node/nodejs.js +6 -4
  265. package/lib/node/nodejs.js.map +1 -1
  266. package/lib/sync/constants.d.ts +7 -1
  267. package/lib/sync/constants.d.ts.map +1 -1
  268. package/lib/sync/constants.js +7 -4
  269. package/lib/sync/constants.js.map +1 -1
  270. package/lib/sync/range/batch.d.ts +55 -8
  271. package/lib/sync/range/batch.d.ts.map +1 -1
  272. package/lib/sync/range/batch.js +291 -66
  273. package/lib/sync/range/batch.js.map +1 -1
  274. package/lib/sync/range/chain.d.ts +22 -4
  275. package/lib/sync/range/chain.d.ts.map +1 -1
  276. package/lib/sync/range/chain.js +103 -11
  277. package/lib/sync/range/chain.js.map +1 -1
  278. package/lib/sync/range/range.d.ts.map +1 -1
  279. package/lib/sync/range/range.js +71 -11
  280. package/lib/sync/range/range.js.map +1 -1
  281. package/lib/sync/range/utils/peerBalancer.d.ts +2 -1
  282. package/lib/sync/range/utils/peerBalancer.d.ts.map +1 -1
  283. package/lib/sync/range/utils/peerBalancer.js +8 -4
  284. package/lib/sync/range/utils/peerBalancer.js.map +1 -1
  285. package/lib/sync/sync.d.ts.map +1 -1
  286. package/lib/sync/sync.js +13 -0
  287. package/lib/sync/sync.js.map +1 -1
  288. package/lib/sync/types.d.ts +34 -0
  289. package/lib/sync/types.d.ts.map +1 -1
  290. package/lib/sync/types.js +34 -0
  291. package/lib/sync/types.js.map +1 -1
  292. package/lib/sync/unknownBlock.d.ts +29 -1
  293. package/lib/sync/unknownBlock.d.ts.map +1 -1
  294. package/lib/sync/unknownBlock.js +727 -61
  295. package/lib/sync/unknownBlock.js.map +1 -1
  296. package/lib/sync/utils/downloadByRange.d.ts +73 -10
  297. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  298. package/lib/sync/utils/downloadByRange.js +213 -26
  299. package/lib/sync/utils/downloadByRange.js.map +1 -1
  300. package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
  301. package/lib/sync/utils/downloadByRoot.js +16 -2
  302. package/lib/sync/utils/downloadByRoot.js.map +1 -1
  303. package/lib/sync/utils/pendingBlocksTree.d.ts +0 -1
  304. package/lib/sync/utils/pendingBlocksTree.d.ts.map +1 -1
  305. package/lib/sync/utils/pendingBlocksTree.js +0 -9
  306. package/lib/sync/utils/pendingBlocksTree.js.map +1 -1
  307. package/lib/sync/utils/rateLimit.d.ts +2 -0
  308. package/lib/sync/utils/rateLimit.d.ts.map +1 -0
  309. package/lib/sync/utils/rateLimit.js +15 -0
  310. package/lib/sync/utils/rateLimit.js.map +1 -0
  311. package/lib/util/sszBytes.d.ts.map +1 -1
  312. package/lib/util/sszBytes.js +20 -5
  313. package/lib/util/sszBytes.js.map +1 -1
  314. package/package.json +17 -17
  315. package/src/api/impl/beacon/blocks/index.ts +22 -9
  316. package/src/api/impl/beacon/pool/index.ts +83 -1
  317. package/src/api/impl/beacon/state/utils.ts +2 -2
  318. package/src/api/impl/debug/index.ts +0 -1
  319. package/src/api/impl/lodestar/index.ts +1 -1
  320. package/src/api/impl/validator/index.ts +82 -5
  321. package/src/chain/GetBlobsTracker.ts +1 -2
  322. package/src/chain/archiveStore/archiveStore.ts +5 -5
  323. package/src/chain/archiveStore/interface.ts +4 -4
  324. package/src/chain/archiveStore/strategies/frequencyStateArchiveStrategy.ts +4 -4
  325. package/src/chain/archiveStore/utils/archiveBlocks.ts +153 -94
  326. package/src/chain/blocks/blockInput/blockInput.ts +4 -1
  327. package/src/chain/blocks/importBlock.ts +16 -56
  328. package/src/chain/blocks/importExecutionPayload.ts +127 -107
  329. package/src/chain/blocks/index.ts +71 -23
  330. package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +64 -3
  331. package/src/chain/blocks/payloadEnvelopeInput/types.ts +18 -0
  332. package/src/chain/blocks/payloadEnvelopeProcessor.ts +7 -6
  333. package/src/chain/blocks/types.ts +15 -25
  334. package/src/chain/blocks/utils/chainSegment.ts +117 -17
  335. package/src/chain/blocks/verifyBlock.ts +70 -9
  336. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +6 -4
  337. package/src/chain/blocks/verifyBlocksSanityChecks.ts +26 -7
  338. package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +137 -0
  339. package/src/chain/blocks/verifyPayloadsDataAvailability.ts +41 -0
  340. package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +9 -18
  341. package/src/chain/chain.ts +65 -26
  342. package/src/chain/emitter.ts +15 -14
  343. package/src/chain/errors/blockError.ts +4 -1
  344. package/src/chain/errors/executionPayloadBid.ts +6 -0
  345. package/src/chain/errors/executionPayloadEnvelope.ts +6 -0
  346. package/src/chain/errors/index.ts +1 -0
  347. package/src/chain/errors/proposerPreferences.ts +47 -0
  348. package/src/chain/forkChoice/index.ts +8 -24
  349. package/src/chain/initState.ts +9 -1
  350. package/src/chain/interface.ts +11 -3
  351. package/src/chain/lightClient/index.ts +6 -6
  352. package/src/chain/opPools/payloadAttestationPool.ts +63 -18
  353. package/src/chain/prepareNextSlot.ts +53 -18
  354. package/src/chain/produceBlock/produceBlockBody.ts +91 -21
  355. package/src/chain/regen/interface.ts +1 -0
  356. package/src/chain/regen/queued.ts +2 -7
  357. package/src/chain/regen/regen.ts +2 -7
  358. package/src/chain/seenCache/index.ts +1 -0
  359. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +89 -21
  360. package/src/chain/seenCache/seenProposerPreferences.ts +32 -0
  361. package/src/chain/stateCache/persistentCheckpointsCache.ts +4 -1
  362. package/src/chain/validation/block.ts +1 -0
  363. package/src/chain/validation/executionPayloadBid.ts +25 -8
  364. package/src/chain/validation/executionPayloadEnvelope.ts +20 -10
  365. package/src/chain/validation/payloadAttestationMessage.ts +11 -7
  366. package/src/chain/validation/proposerPreferences.ts +110 -0
  367. package/src/db/repositories/executionPayloadEnvelopeArchive.ts +1 -1
  368. package/src/execution/engine/http.ts +21 -14
  369. package/src/execution/engine/interface.ts +1 -0
  370. package/src/execution/engine/mock.ts +8 -1
  371. package/src/execution/engine/types.ts +41 -0
  372. package/src/metrics/metrics/lodestar.ts +10 -0
  373. package/src/network/gossip/interface.ts +6 -0
  374. package/src/network/gossip/scoringParameters.ts +14 -1
  375. package/src/network/gossip/topic.ts +6 -0
  376. package/src/network/interface.ts +2 -0
  377. package/src/network/network.ts +24 -1
  378. package/src/network/processor/gossipHandlers.ts +116 -30
  379. package/src/network/processor/gossipQueues/index.ts +5 -0
  380. package/src/network/processor/index.ts +6 -5
  381. package/src/network/reqresp/ReqRespBeaconNode.ts +1 -0
  382. package/src/network/reqresp/handlers/beaconBlocksByHead.ts +91 -0
  383. package/src/network/reqresp/handlers/beaconBlocksByRange.ts +14 -6
  384. package/src/network/reqresp/handlers/blobSidecarsByRange.ts +11 -5
  385. package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +17 -5
  386. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +7 -4
  387. package/src/network/reqresp/handlers/index.ts +5 -0
  388. package/src/network/reqresp/interface.ts +1 -1
  389. package/src/network/reqresp/protocols.ts +6 -0
  390. package/src/network/reqresp/rateLimit.ts +4 -0
  391. package/src/network/reqresp/score.ts +1 -0
  392. package/src/network/reqresp/types.ts +5 -0
  393. package/src/node/nodejs.ts +6 -4
  394. package/src/sync/constants.ts +8 -4
  395. package/src/sync/range/batch.ts +388 -75
  396. package/src/sync/range/chain.ts +131 -14
  397. package/src/sync/range/range.ts +86 -11
  398. package/src/sync/range/utils/peerBalancer.ts +9 -3
  399. package/src/sync/sync.ts +13 -1
  400. package/src/sync/types.ts +72 -0
  401. package/src/sync/unknownBlock.ts +915 -65
  402. package/src/sync/utils/downloadByRange.ts +386 -39
  403. package/src/sync/utils/downloadByRoot.ts +24 -2
  404. package/src/sync/utils/pendingBlocksTree.ts +0 -15
  405. package/src/sync/utils/rateLimit.ts +16 -0
  406. package/src/util/sszBytes.ts +25 -5
@@ -1,6 +1,6 @@
1
1
  import {Type} from "@chainsafe/ssz";
2
2
  import {BeaconConfig} from "@lodestar/config";
3
- import {CheckpointWithHex, CheckpointWithPayloadStatus, IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
3
+ import {CheckpointWithHex, IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
4
4
  import {EpochShuffling, IBeaconStateView, PubkeyCache} from "@lodestar/state-transition";
5
5
  import {
6
6
  BeaconBlock,
@@ -18,6 +18,7 @@ import {
18
18
  altair,
19
19
  capella,
20
20
  deneb,
21
+ electra,
21
22
  gloas,
22
23
  phase0,
23
24
  rewards,
@@ -60,6 +61,7 @@ import {
60
61
  SeenContributionAndProof,
61
62
  SeenExecutionPayloadBids,
62
63
  SeenPayloadAttesters,
64
+ SeenProposerPreferences,
63
65
  SeenSyncCommitteeMessages,
64
66
  } from "./seenCache/index.js";
65
67
  import {SeenAggregatedAttestations} from "./seenCache/seenAggregateAndProof.js";
@@ -130,6 +132,7 @@ export interface IBeaconChain {
130
132
  readonly seenPayloadAttesters: SeenPayloadAttesters;
131
133
  readonly seenAggregatedAttestations: SeenAggregatedAttestations;
132
134
  readonly seenExecutionPayloadBids: SeenExecutionPayloadBids;
135
+ readonly seenProposerPreferences: SeenProposerPreferences;
133
136
  readonly seenBlockProposers: SeenBlockProposers;
134
137
  readonly seenSyncCommitteeMessages: SeenSyncCommitteeMessages;
135
138
  readonly seenContributionAndProof: SeenContributionAndProof;
@@ -195,7 +198,7 @@ export interface IBeaconChain {
195
198
  ): {state: IBeaconStateView; executionOptimistic: boolean; finalized: boolean} | null;
196
199
  /** Return state bytes by checkpoint */
197
200
  getStateOrBytesByCheckpoint(
198
- checkpoint: CheckpointWithPayloadStatus
201
+ checkpoint: CheckpointWithHex
199
202
  ): Promise<{state: IBeaconStateView | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null>;
200
203
 
201
204
  /**
@@ -231,6 +234,7 @@ export interface IBeaconChain {
231
234
  blockSlot: Slot,
232
235
  blockRootHex: string
233
236
  ): Promise<gloas.SignedExecutionPayloadEnvelope | null>;
237
+ getParentExecutionRequests(parentBlockSlot: Slot, parentBlockRootHex: RootHex): Promise<electra.ExecutionRequests>;
234
238
 
235
239
  produceCommonBlockBody(blockAttributes: BlockAttributes): Promise<CommonBlockBody>;
236
240
  produceBlock(blockAttributes: BlockAttributes & {commonBlockBodyPromise: Promise<CommonBlockBody>}): Promise<{
@@ -248,7 +252,11 @@ export interface IBeaconChain {
248
252
  /** Process a block until complete */
249
253
  processBlock(block: IBlockInput, opts?: ImportBlockOpts): Promise<void>;
250
254
  /** Process a chain of blocks until complete */
251
- processChainSegment(blocks: IBlockInput[], opts?: ImportBlockOpts): Promise<void>;
255
+ processChainSegment(
256
+ blocks: IBlockInput[],
257
+ payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
258
+ opts?: ImportBlockOpts
259
+ ): Promise<void>;
252
260
 
253
261
  /** Process execution payload envelope: verify, import to fork choice, and persist to DB */
254
262
  processExecutionPayload(payloadInput: PayloadEnvelopeInput, opts?: ImportPayloadOpts): Promise<void>;
@@ -1,12 +1,6 @@
1
1
  import {BitArray} from "@chainsafe/ssz";
2
2
  import {routes} from "@lodestar/api";
3
3
  import {ChainForkConfig} from "@lodestar/config";
4
- import {
5
- LightClientUpdateSummary,
6
- isBetterUpdate,
7
- toLightClientUpdateSummary,
8
- upgradeLightClientHeader,
9
- } from "@lodestar/light-client/spec";
10
4
  import {
11
5
  ForkName,
12
6
  ForkPostAltair,
@@ -27,6 +21,12 @@ import {
27
21
  computeSyncPeriodAtSlot,
28
22
  executionPayloadToPayloadHeader,
29
23
  } from "@lodestar/state-transition";
24
+ import {
25
+ LightClientUpdateSummary,
26
+ isBetterUpdate,
27
+ toLightClientUpdateSummary,
28
+ upgradeLightClientHeader,
29
+ } from "@lodestar/state-transition/light-client";
30
30
  import {
31
31
  BeaconBlock,
32
32
  BeaconBlockBody,
@@ -1,7 +1,7 @@
1
1
  import {Signature, aggregateSignatures} from "@chainsafe/blst";
2
2
  import {BitArray} from "@chainsafe/ssz";
3
3
  import {ChainForkConfig} from "@lodestar/config";
4
- import {MAX_COMMITTEES_PER_SLOT, PTC_SIZE} from "@lodestar/params";
4
+ import {MAX_COMMITTEES_PER_SLOT, MAX_PAYLOAD_ATTESTATIONS, PTC_SIZE} from "@lodestar/params";
5
5
  import {RootHex, Slot, gloas} from "@lodestar/types";
6
6
  import {MapDef, toRootHex} from "@lodestar/utils";
7
7
  import {Metrics} from "../../metrics/metrics.js";
@@ -57,7 +57,7 @@ export class PayloadAttestationPool {
57
57
  add(
58
58
  message: gloas.PayloadAttestationMessage,
59
59
  payloadAttDataRootHex: RootHex,
60
- validatorCommitteeIndex: number
60
+ validatorCommitteeIndices: number[]
61
61
  ): InsertOutcome {
62
62
  const slot = message.data.slot;
63
63
  const lowestPermissibleSlot = this.lowestPermissibleSlot;
@@ -85,23 +85,19 @@ export class PayloadAttestationPool {
85
85
  const aggregate = aggregateByDataRoot.get(payloadAttDataRootHex);
86
86
  if (aggregate) {
87
87
  // Aggregate msg into aggregate
88
- return aggregateMessageInto(message, validatorCommitteeIndex, aggregate);
88
+ return aggregateMessageInto(message, validatorCommitteeIndices, aggregate);
89
89
  }
90
90
  // Create a new aggregate with data
91
- aggregateByDataRoot.set(payloadAttDataRootHex, messageToAggregate(message, validatorCommitteeIndex));
91
+ aggregateByDataRoot.set(payloadAttDataRootHex, messageToAggregate(message, validatorCommitteeIndices));
92
92
 
93
93
  return InsertOutcome.NewData;
94
94
  }
95
95
 
96
96
  /**
97
97
  * Get payload attestations to be included in a block.
98
- * Pick the top `maxAttestation` number of attestations with the most votes
98
+ * Pick the top `MAX_PAYLOAD_ATTESTATIONS` aggregates with the most votes.
99
99
  */
100
- getPayloadAttestationsForBlock(
101
- beaconBlockRoot: BlockRootHex,
102
- slot: Slot,
103
- maxAttestation: number
104
- ): gloas.PayloadAttestation[] {
100
+ getPayloadAttestationsForBlock(beaconBlockRoot: BlockRootHex, slot: Slot): gloas.PayloadAttestation[] {
105
101
  const aggregateByDataRootByBlockRoot = this.aggregateByDataRootByBlockRootBySlot.get(slot);
106
102
 
107
103
  if (!aggregateByDataRootByBlockRoot) {
@@ -119,7 +115,32 @@ export class PayloadAttestationPool {
119
115
  return Array.from(aggregateByDataRoot.values())
120
116
  .slice()
121
117
  .sort((a, b) => b.aggregationBits.getTrueBitIndexes().length - a.aggregationBits.getTrueBitIndexes().length)
122
- .slice(0, maxAttestation)
118
+ .slice(0, MAX_PAYLOAD_ATTESTATIONS)
119
+ .map(fastToPayloadAttestation);
120
+ }
121
+
122
+ getAll(slot?: Slot): gloas.PayloadAttestation[] {
123
+ const aggregates: AggregateFast[] = [];
124
+
125
+ const addAggregates = (aggregateByDataRootByBlockRoot: Map<BlockRootHex, Map<DataRootHex, AggregateFast>>) => {
126
+ for (const aggregateByDataRoot of aggregateByDataRootByBlockRoot.values()) {
127
+ aggregates.push(...aggregateByDataRoot.values());
128
+ }
129
+ };
130
+
131
+ if (slot !== undefined) {
132
+ const aggregateByDataRootByBlockRoot = this.aggregateByDataRootByBlockRootBySlot.get(slot);
133
+ if (aggregateByDataRootByBlockRoot) {
134
+ addAggregates(aggregateByDataRootByBlockRoot);
135
+ }
136
+ } else {
137
+ for (const aggregateByDataRootByBlockRoot of this.aggregateByDataRootByBlockRootBySlot.values()) {
138
+ addAggregates(aggregateByDataRootByBlockRoot);
139
+ }
140
+ }
141
+
142
+ return aggregates
143
+ .sort((a, b) => b.aggregationBits.getTrueBitIndexes().length - a.aggregationBits.getTrueBitIndexes().length)
123
144
  .map(fastToPayloadAttestation);
124
145
  }
125
146
 
@@ -129,25 +150,49 @@ export class PayloadAttestationPool {
129
150
  }
130
151
  }
131
152
 
132
- function messageToAggregate(message: gloas.PayloadAttestationMessage, validatorCommitteeIndex: number): AggregateFast {
153
+ function messageToAggregate(
154
+ message: gloas.PayloadAttestationMessage,
155
+ validatorCommitteeIndices: number[]
156
+ ): AggregateFast {
157
+ const aggregationBits = BitArray.fromBitLen(PTC_SIZE);
158
+ for (const index of validatorCommitteeIndices) {
159
+ aggregationBits.set(index, true);
160
+ }
161
+ const sig = signatureFromBytesNoCheck(message.signature);
162
+ // The validator signed once but occupies `validatorCommitteeIndices.length` PTC positions.
163
+ // Verification aggregates the pubkey once per set bit, so the signature must be aggregated
164
+ // the same number of times for the BLS check to balance — same pattern as sync committee.
165
+ const signature =
166
+ validatorCommitteeIndices.length === 1
167
+ ? sig
168
+ : aggregateSignatures(new Array(validatorCommitteeIndices.length).fill(sig));
133
169
  return {
134
- aggregationBits: BitArray.fromSingleBit(PTC_SIZE, validatorCommitteeIndex),
170
+ aggregationBits,
135
171
  data: message.data,
136
- signature: signatureFromBytesNoCheck(message.signature),
172
+ signature,
137
173
  };
138
174
  }
139
175
 
140
176
  function aggregateMessageInto(
141
177
  message: gloas.PayloadAttestationMessage,
142
- validatorCommitteeIndex: number,
178
+ validatorCommitteeIndices: number[],
143
179
  aggregate: AggregateFast
144
180
  ): InsertOutcome {
145
- if (aggregate.aggregationBits.get(validatorCommitteeIndex) === true) {
181
+ // Gossip dedup via `seenPayloadAttesters` is keyed by (epoch, validatorIndex), so the same
182
+ // validator's message is never processed twice — all of its bits are set together or none.
183
+ // Checking the first index is sufficient.
184
+ if (aggregate.aggregationBits.get(validatorCommitteeIndices[0]) === true) {
146
185
  return InsertOutcome.AlreadyKnown;
147
186
  }
148
187
 
149
- aggregate.aggregationBits.set(validatorCommitteeIndex, true);
150
- aggregate.signature = aggregateSignatures([aggregate.signature, signatureFromBytesNoCheck(message.signature)]);
188
+ for (const index of validatorCommitteeIndices) {
189
+ aggregate.aggregationBits.set(index, true);
190
+ }
191
+ const sig = signatureFromBytesNoCheck(message.signature);
192
+ aggregate.signature = aggregateSignatures([
193
+ aggregate.signature,
194
+ ...new Array(validatorCommitteeIndices.length).fill(sig),
195
+ ]);
151
196
 
152
197
  return InsertOutcome.Aggregated;
153
198
  }
@@ -4,12 +4,14 @@ import {getSafeExecutionBlockHash} from "@lodestar/fork-choice";
4
4
  import {ForkPostBellatrix, ForkSeq, SLOTS_PER_EPOCH, isForkPostBellatrix} from "@lodestar/params";
5
5
  import {
6
6
  IBeaconStateView,
7
+ IBeaconStateViewBellatrix,
7
8
  StateHashTreeRootSource,
8
9
  computeEpochAtSlot,
9
10
  computeTimeAtSlot,
10
11
  isStatePostBellatrix,
12
+ isStatePostGloas,
11
13
  } from "@lodestar/state-transition";
12
- import {Slot} from "@lodestar/types";
14
+ import {Bytes32, Slot} from "@lodestar/types";
13
15
  import {Logger, fromHex, isErrorAborted, sleep} from "@lodestar/utils";
14
16
  import {GENESIS_SLOT, ZERO_HASH_HEX} from "../constants/constants.js";
15
17
  import {BuilderStatus} from "../execution/builder/http.js";
@@ -81,6 +83,8 @@ export class PrepareNextSlotScheduler {
81
83
  // calling updateHead() here before we produce a block to reduce reorg possibility
82
84
  const headBlock = this.chain.recomputeForkChoiceHead(ForkchoiceCaller.prepareNextSlot);
83
85
  const {slot: headSlot, blockRoot: headRoot} = headBlock;
86
+ // may be updated below if we predict a proposer-boost-reorg
87
+ let updatedHead = headBlock;
84
88
 
85
89
  // PS: previously this was comparing slots, but that gave no leway on the skipped
86
90
  // slots on epoch bounday. Making it more fluid.
@@ -123,7 +127,6 @@ export class PrepareNextSlotScheduler {
123
127
  const proposerIndex = prepareState.getBeaconProposer(prepareSlot);
124
128
  const feeRecipient = this.chain.beaconProposerCache.get(proposerIndex);
125
129
  let updatedPrepareState = prepareState;
126
- let updatedHeadRoot = headRoot;
127
130
 
128
131
  if (feeRecipient) {
129
132
  // If we are proposing next slot, we need to predict if we can proposer-boost-reorg or not
@@ -146,7 +149,7 @@ export class PrepareNextSlotScheduler {
146
149
  {dontTransferCache: !isEpochTransition},
147
150
  RegenCaller.predictProposerHead
148
151
  );
149
- updatedHeadRoot = proposerHeadRoot;
152
+ updatedHead = proposerHead;
150
153
  }
151
154
 
152
155
  // Update the builder status, if enabled shoot an api call to check status
@@ -156,28 +159,54 @@ export class PrepareNextSlotScheduler {
156
159
  this.logger.error("Builder disabled as the check status api failed", {prepareSlot}, e as Error);
157
160
  });
158
161
  }
162
+ }
163
+
164
+ if (!isStatePostBellatrix(updatedPrepareState)) {
165
+ throw new Error("Expected Bellatrix state for payload attributes");
166
+ }
167
+
168
+ let parentBlockHash: Bytes32;
169
+ // Apply parent payload once here as it's reused by EL prep and SSE emit below
170
+ let stateAfterParentPayload: IBeaconStateViewBellatrix = updatedPrepareState;
171
+ if (isStatePostGloas(updatedPrepareState)) {
172
+ if (this.chain.forkChoice.shouldExtendPayload(updatedHead.blockRoot)) {
173
+ parentBlockHash = updatedPrepareState.latestExecutionPayloadBid.blockHash;
174
+ // Skip applying parent payload unless we're proposing the next slot or have to emit payload_attributes events
175
+ if (feeRecipient !== undefined || this.chain.opts.emitPayloadAttributes === true) {
176
+ const parentExecutionRequests = await this.chain.getParentExecutionRequests(
177
+ updatedHead.slot,
178
+ updatedHead.blockRoot
179
+ );
180
+ stateAfterParentPayload = updatedPrepareState.withParentPayloadApplied(parentExecutionRequests);
181
+ }
182
+ } else {
183
+ parentBlockHash = updatedPrepareState.latestExecutionPayloadBid.parentBlockHash;
184
+ }
185
+ } else {
186
+ parentBlockHash = updatedPrepareState.latestExecutionPayloadHeader.blockHash;
187
+ }
159
188
 
189
+ if (feeRecipient) {
160
190
  const preparationTime =
161
191
  computeTimeAtSlot(this.config, prepareSlot, this.chain.genesisTime) - Date.now() / 1000;
162
192
  this.metrics?.blockPayload.payloadAdvancePrepTime.observe(preparationTime);
163
- if (!isStatePostBellatrix(updatedPrepareState)) {
164
- throw new Error("Expected Bellatrix state for payload preparation");
165
- }
166
193
 
167
194
  const safeBlockHash = getSafeExecutionBlockHash(this.chain.forkChoice);
168
195
  const finalizedBlockHash =
169
196
  this.chain.forkChoice.getFinalizedBlock().executionPayloadBlockHash ?? ZERO_HASH_HEX;
197
+
170
198
  // awaiting here instead of throwing an async call because there is no other task
171
- // left for scheduler and this gives nice sematics to catch and log errors in the
199
+ // left for scheduler and this gives nice semantics to catch and log errors in the
172
200
  // try/catch wrapper here.
173
201
  await prepareExecutionPayload(
174
202
  this.chain,
175
203
  this.logger,
176
204
  fork as ForkPostBellatrix, // State is of execution type
177
- fromHex(updatedHeadRoot),
205
+ fromHex(updatedHead.blockRoot),
206
+ parentBlockHash,
178
207
  safeBlockHash,
179
208
  finalizedBlockHash,
180
- updatedPrepareState,
209
+ stateAfterParentPayload,
181
210
  feeRecipient
182
211
  );
183
212
  this.logger.verbose("PrepareNextSlotScheduler prepared new payload", {
@@ -187,24 +216,30 @@ export class PrepareNextSlotScheduler {
187
216
  });
188
217
  }
189
218
 
190
- if (!isStatePostBellatrix(updatedPrepareState)) {
191
- throw new Error("Expected Bellatrix state for payload attributes");
219
+ if (ForkSeq[fork] >= ForkSeq.gloas) {
220
+ // Cutoff = slot of the parent of the block we'll actually build on (post-reorg).
221
+ // Steady state: cache holds just 2 entries — head (parent for next-slot production)
222
+ // and head.parent (proposer-boost-reorg fallback). Anything older is evicted.
223
+ const updatedHeadParent = this.chain.forkChoice.getBlockHexDefaultStatus(updatedHead.parentRoot);
224
+ if (updatedHeadParent) {
225
+ this.chain.seenPayloadEnvelopeInputCache.pruneBelowParent(updatedHeadParent);
226
+ }
192
227
  }
193
228
 
194
229
  this.computeStateHashTreeRoot(updatedPrepareState, isEpochTransition);
195
230
 
196
- // If emitPayloadAttributes is true emit a SSE payloadAttributes event
231
+ // If emitPayloadAttributes is true emit a SSE payloadAttributes event for
232
+ // every slot. Without the flag, only emit the event if we are proposing in the next slot.
197
233
  if (
198
- this.chain.opts.emitPayloadAttributes === true &&
234
+ (feeRecipient || this.chain.opts.emitPayloadAttributes === true) &&
199
235
  this.chain.emitter.listenerCount(routes.events.EventType.payloadAttributes)
200
236
  ) {
201
237
  const data = getPayloadAttributesForSSE(fork as ForkPostBellatrix, this.chain, {
202
- prepareState: updatedPrepareState,
238
+ prepareState: stateAfterParentPayload,
203
239
  prepareSlot,
204
- parentBlockRoot: fromHex(headRoot),
205
- // The likely consumers of this API are builders and will anyway ignore the
206
- // feeRecipient, so just pass zero hash for now till a real use case arises
207
- feeRecipient: "0x0000000000000000000000000000000000000000000000000000000000000000",
240
+ parentBlockRoot: fromHex(updatedHead.blockRoot),
241
+ parentBlockHash,
242
+ feeRecipient: feeRecipient ?? "0x0000000000000000000000000000000000000000",
208
243
  });
209
244
  this.chain.emitter.emit(routes.events.EventType.payloadAttributes, {data, version: fork});
210
245
  }
@@ -19,7 +19,6 @@ import {
19
19
  IBeaconStateView,
20
20
  type IBeaconStateViewBellatrix,
21
21
  computeTimeAtSlot,
22
- isParentBlockFull,
23
22
  isStatePostBellatrix,
24
23
  isStatePostCapella,
25
24
  isStatePostGloas,
@@ -47,8 +46,9 @@ import {
47
46
  electra,
48
47
  fulu,
49
48
  gloas,
49
+ ssz,
50
50
  } from "@lodestar/types";
51
- import {Logger, fromHex, sleep, toHex, toPubkeyHex, toRootHex} from "@lodestar/utils";
51
+ import {Logger, byteArrayEquals, fromHex, sleep, toHex, toPubkeyHex, toRootHex} from "@lodestar/utils";
52
52
  import {ZERO_HASH_HEX} from "../../constants/index.js";
53
53
  import {numToQuantity} from "../../execution/engine/utils.js";
54
54
  import {
@@ -111,6 +111,7 @@ export type ProduceFullGloas = {
111
111
  executionRequests: electra.ExecutionRequests;
112
112
  blobsBundle: BlobsBundle<ForkPostGloas>;
113
113
  cells: fulu.Cell[][];
114
+ parentBlockRoot: Root;
114
115
  };
115
116
  export type ProduceFullFulu = {
116
117
  type: BlockType.Full;
@@ -214,14 +215,28 @@ export async function produceBlockBody<T extends BlockType>(
214
215
  });
215
216
 
216
217
  // Get execution payload from EL
218
+ let parentBlockHash: Bytes32;
219
+ let parentExecutionRequests: electra.ExecutionRequests;
220
+ // Apply parent payload once here as it's reused by EL prep and voluntary exit filtering below
221
+ let stateAfterParentPayload: IBeaconStateViewBellatrix = currentState;
222
+ const isExtendingPayload = this.forkChoice.shouldExtendPayload(toRootHex(parentBlockRoot));
223
+ if (isExtendingPayload) {
224
+ parentBlockHash = currentState.latestExecutionPayloadBid.blockHash;
225
+ parentExecutionRequests = await this.getParentExecutionRequests(parentBlock.slot, parentBlock.blockRoot);
226
+ stateAfterParentPayload = currentState.withParentPayloadApplied(parentExecutionRequests);
227
+ } else {
228
+ parentBlockHash = currentState.latestExecutionPayloadBid.parentBlockHash;
229
+ parentExecutionRequests = ssz.electra.ExecutionRequests.defaultValue();
230
+ }
217
231
  const prepareRes = await prepareExecutionPayload(
218
232
  this,
219
233
  this.logger,
220
234
  fork,
221
235
  parentBlockRoot,
236
+ parentBlockHash,
222
237
  safeBlockHash,
223
238
  finalizedBlockHash ?? ZERO_HASH_HEX,
224
- currentState,
239
+ stateAfterParentPayload,
225
240
  feeRecipient
226
241
  );
227
242
 
@@ -255,8 +270,8 @@ export async function produceBlockBody<T extends BlockType>(
255
270
 
256
271
  // Create self-build execution payload bid
257
272
  const bid: gloas.ExecutionPayloadBid = {
258
- parentBlockHash: currentState.latestBlockHash,
259
- parentBlockRoot: parentBlockRoot,
273
+ parentBlockHash,
274
+ parentBlockRoot,
260
275
  blockHash: executionPayload.blockHash,
261
276
  prevRandao: currentState.getRandaoMix(currentState.epoch),
262
277
  feeRecipient: executionPayload.feeRecipient,
@@ -266,6 +281,7 @@ export async function produceBlockBody<T extends BlockType>(
266
281
  value: 0,
267
282
  executionPayment: 0,
268
283
  blobKzgCommitments: blobsBundle.commitments,
284
+ executionRequestsRoot: ssz.electra.ExecutionRequests.hashTreeRoot(executionRequests),
269
285
  };
270
286
  const signedBid: gloas.SignedExecutionPayloadBid = {
271
287
  message: bid,
@@ -275,8 +291,19 @@ export async function produceBlockBody<T extends BlockType>(
275
291
  const commonBlockBody = await commonBlockBodyPromise;
276
292
  const gloasBody = Object.assign({}, commonBlockBody) as gloas.BeaconBlockBody;
277
293
  gloasBody.signedExecutionPayloadBid = signedBid;
278
- // TODO GLOAS: Get payload attestations from pool for previous slot
279
- gloasBody.payloadAttestations = [];
294
+ gloasBody.payloadAttestations = this.payloadAttestationPool.getPayloadAttestationsForBlock(
295
+ parentBlock.blockRoot,
296
+ blockSlot - 1
297
+ );
298
+ gloasBody.parentExecutionRequests = parentExecutionRequests;
299
+ // Drop voluntary exits that parent_execution_requests have invalidated (e.g. a withdrawal
300
+ // request initiating an exit on the same validator). Op pool selected against the unapplied
301
+ // state, so re-validate against the post-apply state to avoid producing an invalid block.
302
+ if (isExtendingPayload && commonBlockBody.voluntaryExits.length > 0) {
303
+ gloasBody.voluntaryExits = commonBlockBody.voluntaryExits.filter((signedVoluntaryExit) =>
304
+ stateAfterParentPayload.isValidVoluntaryExit(signedVoluntaryExit, false)
305
+ );
306
+ }
280
307
  blockBody = gloasBody as AssembledBodyType<T>;
281
308
 
282
309
  // Store execution payload data required to construct execution payload envelope later
@@ -285,6 +312,7 @@ export async function produceBlockBody<T extends BlockType>(
285
312
  gloasResult.executionRequests = executionRequests;
286
313
  gloasResult.blobsBundle = blobsBundle;
287
314
  gloasResult.cells = cells;
315
+ gloasResult.parentBlockRoot = fromHex(parentBlock.blockRoot);
288
316
 
289
317
  const fetchedTime = Date.now() / 1000 - computeTimeAtSlot(this.config, blockSlot, this.genesisTime);
290
318
  this.metrics?.blockPayload.payloadFetchedTime.observe({prepType}, fetchedTime);
@@ -334,6 +362,7 @@ export async function produceBlockBody<T extends BlockType>(
334
362
  this.logger,
335
363
  fork,
336
364
  parentBlockRoot,
365
+ currentState.latestExecutionPayloadHeader.blockHash,
337
366
  safeBlockHash,
338
367
  finalizedBlockHash ?? ZERO_HASH_HEX,
339
368
  currentState,
@@ -442,6 +471,7 @@ export async function produceBlockBody<T extends BlockType>(
442
471
  this.logger,
443
472
  fork,
444
473
  parentBlockRoot,
474
+ currentState.latestExecutionPayloadHeader.blockHash,
445
475
  safeBlockHash,
446
476
  finalizedBlockHash ?? ZERO_HASH_HEX,
447
477
  currentState,
@@ -607,17 +637,21 @@ export async function prepareExecutionPayload(
607
637
  logger: Logger,
608
638
  fork: ForkPostBellatrix,
609
639
  parentBlockRoot: Root,
640
+ parentBlockHash: Bytes32,
610
641
  safeBlockHash: RootHex,
611
642
  finalizedBlockHash: RootHex,
643
+ /**
644
+ * Post-gloas, when extending a full parent, callers must apply
645
+ * parent execution payload first (see `withParentPayloadApplied`).
646
+ */
612
647
  state: IBeaconStateViewBellatrix,
613
648
  suggestedFeeRecipient: string
614
649
  ): Promise<{prepType: PayloadPreparationType; payloadId: PayloadId}> {
615
- const parentHash = state.latestBlockHash;
616
650
  const timestamp = computeTimeAtSlot(chain.config, state.slot, state.genesisTime);
617
651
  const prevRandao = state.getRandaoMix(state.epoch);
618
652
 
619
653
  const payloadIdCached = chain.executionEngine.payloadIdCache.get({
620
- headBlockHash: toRootHex(parentHash),
654
+ headBlockHash: toRootHex(parentBlockHash),
621
655
  finalizedBlockHash,
622
656
  timestamp: numToQuantity(timestamp),
623
657
  prevRandao: toHex(prevRandao),
@@ -646,12 +680,13 @@ export async function prepareExecutionPayload(
646
680
  prepareState: state,
647
681
  prepareSlot: state.slot,
648
682
  parentBlockRoot,
683
+ parentBlockHash,
649
684
  feeRecipient: suggestedFeeRecipient,
650
685
  });
651
686
 
652
687
  payloadId = await chain.executionEngine.notifyForkchoiceUpdate(
653
688
  fork,
654
- toRootHex(parentHash),
689
+ toRootHex(parentBlockHash),
655
690
  safeBlockHash,
656
691
  finalizedBlockHash,
657
692
  attributes
@@ -703,20 +738,34 @@ export function getPayloadAttributesForSSE(
703
738
  prepareState,
704
739
  prepareSlot,
705
740
  parentBlockRoot,
741
+ parentBlockHash,
706
742
  feeRecipient,
707
- }: {prepareState: IBeaconStateViewBellatrix; prepareSlot: Slot; parentBlockRoot: Root; feeRecipient: string}
743
+ }: {
744
+ /**
745
+ * Post-gloas, when extending a full parent, callers must apply
746
+ * parent execution payload first (see `withParentPayloadApplied`).
747
+ */
748
+ prepareState: IBeaconStateViewBellatrix;
749
+ prepareSlot: Slot;
750
+ parentBlockRoot: Root;
751
+ parentBlockHash: Bytes32;
752
+ feeRecipient: string;
753
+ }
708
754
  ): SSEPayloadAttributes {
709
- const parentHash = prepareState.latestBlockHash;
710
755
  const payloadAttributes = preparePayloadAttributes(fork, chain, {
711
756
  prepareState,
712
757
  prepareSlot,
713
758
  parentBlockRoot,
759
+ parentBlockHash,
714
760
  feeRecipient,
715
761
  });
716
762
 
717
763
  let parentBlockNumber: number;
718
764
  if (isForkPostGloas(fork)) {
719
- const parentBlock = chain.forkChoice.getBlockHexAndBlockHash(toRootHex(parentBlockRoot), toRootHex(parentHash));
765
+ const parentBlock = chain.forkChoice.getBlockHexAndBlockHash(
766
+ toRootHex(parentBlockRoot),
767
+ toRootHex(parentBlockHash)
768
+ );
720
769
  if (parentBlock?.executionPayloadBlockHash == null) {
721
770
  throw Error(`Parent block not found in fork choice root=${toRootHex(parentBlockRoot)}`);
722
771
  }
@@ -730,7 +779,7 @@ export function getPayloadAttributesForSSE(
730
779
  proposalSlot: prepareSlot,
731
780
  parentBlockNumber,
732
781
  parentBlockRoot,
733
- parentBlockHash: parentHash,
782
+ parentBlockHash,
734
783
  payloadAttributes,
735
784
  };
736
785
  return ssePayloadAttributes;
@@ -745,11 +794,17 @@ function preparePayloadAttributes(
745
794
  prepareState,
746
795
  prepareSlot,
747
796
  parentBlockRoot,
797
+ parentBlockHash,
748
798
  feeRecipient,
749
799
  }: {
800
+ /**
801
+ * Post-gloas, when extending a full parent, callers must apply
802
+ * parent execution payload first (see `withParentPayloadApplied`).
803
+ */
750
804
  prepareState: IBeaconStateViewBellatrix;
751
805
  prepareSlot: Slot;
752
806
  parentBlockRoot: Root;
807
+ parentBlockHash: Bytes32;
753
808
  feeRecipient: string;
754
809
  }
755
810
  ): SSEPayloadAttributes["payloadAttributes"] {
@@ -766,13 +821,24 @@ function preparePayloadAttributes(
766
821
  throw new Error("Expected Capella state for withdrawals");
767
822
  }
768
823
 
769
- if (isStatePostGloas(prepareState) && !isParentBlockFull(prepareState)) {
770
- // When the parent block is empty, state.payloadExpectedWithdrawals holds a batch
771
- // already deducted from CL balances but never credited on the EL (the envelope
772
- // was not delivered). The next payload must carry those same withdrawals to
773
- // restore CL/EL consistency, otherwise validators permanently lose that balance.
774
- (payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
775
- prepareState.payloadExpectedWithdrawals;
824
+ if (isStatePostGloas(prepareState)) {
825
+ const isExtendingPayload = byteArrayEquals(parentBlockHash, prepareState.latestExecutionPayloadBid.blockHash);
826
+ if (isExtendingPayload) {
827
+ // applyParentExecutionPayload sets latestBlockHash = parentBid.blockHash, so a mismatch
828
+ // here means the caller did not apply parent payload to prepareState
829
+ if (!byteArrayEquals(prepareState.latestBlockHash, prepareState.latestExecutionPayloadBid.blockHash)) {
830
+ throw new Error("Expected state with parent execution payload applied for withdrawals");
831
+ }
832
+ (payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
833
+ prepareState.getExpectedWithdrawals().expectedWithdrawals;
834
+ } else {
835
+ // When the parent block is empty, state.payloadExpectedWithdrawals holds a batch
836
+ // already deducted from CL balances but never credited on the EL (the envelope
837
+ // was not delivered). The next payload must carry those same withdrawals to
838
+ // restore CL/EL consistency, otherwise validators permanently lose that balance.
839
+ (payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
840
+ prepareState.payloadExpectedWithdrawals;
841
+ }
776
842
  } else {
777
843
  // withdrawals logic is now fork aware as it changes on electra fork post capella
778
844
  (payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
@@ -784,6 +850,10 @@ function preparePayloadAttributes(
784
850
  (payloadAttributes as deneb.SSEPayloadAttributes["payloadAttributes"]).parentBeaconBlockRoot = parentBlockRoot;
785
851
  }
786
852
 
853
+ if (ForkSeq[fork] >= ForkSeq.gloas) {
854
+ (payloadAttributes as gloas.SSEPayloadAttributes["payloadAttributes"]).slotNumber = prepareSlot;
855
+ }
856
+
787
857
  return payloadAttributes;
788
858
  }
789
859
 
@@ -21,6 +21,7 @@ export enum RegenCaller {
21
21
  validateGossipAttestation = "validateGossipAttestation",
22
22
  validateGossipVoluntaryExit = "validateGossipVoluntaryExit",
23
23
  validateGossipExecutionPayloadBid = "validateGossipExecutionPayloadBid",
24
+ validateGossipProposerPreferences = "validateGossipProposerPreferences",
24
25
  onForkChoiceFinalized = "onForkChoiceFinalized",
25
26
  restApi = "restApi",
26
27
  }
@@ -1,7 +1,7 @@
1
1
  import {routes} from "@lodestar/api";
2
2
  import {IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
3
3
  import {IBeaconStateView, computeEpochAtSlot} from "@lodestar/state-transition";
4
- import {BeaconBlock, Epoch, RootHex, Slot, isGloasBeaconBlock, phase0} from "@lodestar/types";
4
+ import {BeaconBlock, Epoch, RootHex, Slot, phase0} from "@lodestar/types";
5
5
  import {Logger, toRootHex} from "@lodestar/utils";
6
6
  import {Metrics} from "../../metrics/index.js";
7
7
  import {JobItemQueue} from "../../util/queue/index.js";
@@ -88,12 +88,7 @@ export class QueuedStateRegenerator implements IStateRegenerator {
88
88
  */
89
89
  getPreStateSync(block: BeaconBlock): IBeaconStateView | null {
90
90
  const parentRoot = toRootHex(block.parentRoot);
91
- const parentBlock = isGloasBeaconBlock(block)
92
- ? this.forkChoice.getBlockHexAndBlockHash(
93
- parentRoot,
94
- toRootHex(block.body.signedExecutionPayloadBid.message.parentBlockHash)
95
- )
96
- : this.forkChoice.getBlockHexDefaultStatus(parentRoot);
91
+ const parentBlock = this.forkChoice.getBlockHexDefaultStatus(parentRoot);
97
92
  if (!parentBlock) {
98
93
  throw new RegenError({
99
94
  code: RegenErrorCode.BLOCK_NOT_IN_FORKCHOICE,