@lodestar/beacon-node 1.43.0-dev.9c8becae00 → 1.43.0-dev.9f5db5b9c7

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 (331) 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/archiveStore/archiveStore.d.ts.map +1 -1
  19. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  20. package/lib/chain/archiveStore/interface.d.ts +4 -4
  21. package/lib/chain/archiveStore/interface.d.ts.map +1 -1
  22. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts +4 -4
  23. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts.map +1 -1
  24. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js.map +1 -1
  25. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +2 -2
  26. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
  27. package/lib/chain/archiveStore/utils/archiveBlocks.js +110 -58
  28. package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
  29. package/lib/chain/blocks/blockInput/blockInput.d.ts +3 -0
  30. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  31. package/lib/chain/blocks/blockInput/blockInput.js +4 -1
  32. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  33. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  34. package/lib/chain/blocks/importBlock.js +24 -20
  35. package/lib/chain/blocks/importBlock.js.map +1 -1
  36. package/lib/chain/blocks/importExecutionPayload.d.ts +28 -14
  37. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  38. package/lib/chain/blocks/importExecutionPayload.js +88 -90
  39. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  40. package/lib/chain/blocks/index.d.ts +5 -3
  41. package/lib/chain/blocks/index.d.ts.map +1 -1
  42. package/lib/chain/blocks/index.js +59 -26
  43. package/lib/chain/blocks/index.js.map +1 -1
  44. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +4 -0
  45. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
  46. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +9 -2
  47. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
  48. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +1 -0
  49. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
  50. package/lib/chain/blocks/payloadEnvelopeProcessor.js +2 -2
  51. package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
  52. package/lib/chain/blocks/types.d.ts +15 -20
  53. package/lib/chain/blocks/types.d.ts.map +1 -1
  54. package/lib/chain/blocks/utils/chainSegment.d.ts +23 -2
  55. package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
  56. package/lib/chain/blocks/utils/chainSegment.js +89 -12
  57. package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
  58. package/lib/chain/blocks/verifyBlock.d.ts +5 -3
  59. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  60. package/lib/chain/blocks/verifyBlock.js +50 -7
  61. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  62. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +0 -4
  63. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  64. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +5 -2
  65. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  66. package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts +2 -1
  67. package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
  68. package/lib/chain/blocks/verifyBlocksSanityChecks.js +25 -5
  69. package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
  70. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +24 -0
  71. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -0
  72. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +79 -0
  73. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -0
  74. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -1
  75. package/lib/chain/blocks/verifyPayloadsDataAvailability.js +8 -3
  76. package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -1
  77. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts +1 -1
  78. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts.map +1 -1
  79. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js +2 -11
  80. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js.map +1 -1
  81. package/lib/chain/chain.d.ts +8 -6
  82. package/lib/chain/chain.d.ts.map +1 -1
  83. package/lib/chain/chain.js +21 -6
  84. package/lib/chain/chain.js.map +1 -1
  85. package/lib/chain/emitter.d.ts +3 -14
  86. package/lib/chain/emitter.d.ts.map +1 -1
  87. package/lib/chain/emitter.js +0 -4
  88. package/lib/chain/emitter.js.map +1 -1
  89. package/lib/chain/errors/blockError.d.ts +8 -1
  90. package/lib/chain/errors/blockError.d.ts.map +1 -1
  91. package/lib/chain/errors/blockError.js +2 -0
  92. package/lib/chain/errors/blockError.js.map +1 -1
  93. package/lib/chain/errors/executionPayloadBid.d.ts +5 -0
  94. package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
  95. package/lib/chain/errors/executionPayloadBid.js +1 -0
  96. package/lib/chain/errors/executionPayloadBid.js.map +1 -1
  97. package/lib/chain/errors/executionPayloadEnvelope.d.ts +5 -0
  98. package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
  99. package/lib/chain/errors/executionPayloadEnvelope.js +1 -0
  100. package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
  101. package/lib/chain/errors/index.d.ts +1 -0
  102. package/lib/chain/errors/index.d.ts.map +1 -1
  103. package/lib/chain/errors/index.js +1 -0
  104. package/lib/chain/errors/index.js.map +1 -1
  105. package/lib/chain/errors/proposerPreferences.d.ts +40 -0
  106. package/lib/chain/errors/proposerPreferences.d.ts.map +1 -0
  107. package/lib/chain/errors/proposerPreferences.js +14 -0
  108. package/lib/chain/errors/proposerPreferences.js.map +1 -0
  109. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  110. package/lib/chain/forkChoice/index.js +5 -17
  111. package/lib/chain/forkChoice/index.js.map +1 -1
  112. package/lib/chain/interface.d.ts +7 -5
  113. package/lib/chain/interface.d.ts.map +1 -1
  114. package/lib/chain/interface.js.map +1 -1
  115. package/lib/chain/opPools/payloadAttestationPool.d.ts +3 -2
  116. package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -1
  117. package/lib/chain/opPools/payloadAttestationPool.js +26 -4
  118. package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
  119. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  120. package/lib/chain/prepareNextSlot.js +31 -13
  121. package/lib/chain/prepareNextSlot.js.map +1 -1
  122. package/lib/chain/produceBlock/produceBlockBody.d.ts +11 -1
  123. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  124. package/lib/chain/produceBlock/produceBlockBody.js +52 -14
  125. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  126. package/lib/chain/regen/interface.d.ts +1 -0
  127. package/lib/chain/regen/interface.d.ts.map +1 -1
  128. package/lib/chain/regen/interface.js +1 -0
  129. package/lib/chain/regen/interface.js.map +1 -1
  130. package/lib/chain/regen/queued.d.ts.map +1 -1
  131. package/lib/chain/regen/queued.js +1 -4
  132. package/lib/chain/regen/queued.js.map +1 -1
  133. package/lib/chain/regen/regen.d.ts.map +1 -1
  134. package/lib/chain/regen/regen.js +1 -4
  135. package/lib/chain/regen/regen.js.map +1 -1
  136. package/lib/chain/seenCache/index.d.ts +1 -0
  137. package/lib/chain/seenCache/index.d.ts.map +1 -1
  138. package/lib/chain/seenCache/index.js +1 -0
  139. package/lib/chain/seenCache/index.js.map +1 -1
  140. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +19 -6
  141. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
  142. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +40 -22
  143. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
  144. package/lib/chain/seenCache/seenProposerPreferences.d.ts +16 -0
  145. package/lib/chain/seenCache/seenProposerPreferences.d.ts.map +1 -0
  146. package/lib/chain/seenCache/seenProposerPreferences.js +26 -0
  147. package/lib/chain/seenCache/seenProposerPreferences.js.map +1 -0
  148. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  149. package/lib/chain/stateCache/persistentCheckpointsCache.js +4 -1
  150. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  151. package/lib/chain/validation/block.d.ts.map +1 -1
  152. package/lib/chain/validation/block.js +1 -0
  153. package/lib/chain/validation/block.js.map +1 -1
  154. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  155. package/lib/chain/validation/executionPayloadBid.js +24 -9
  156. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  157. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  158. package/lib/chain/validation/executionPayloadEnvelope.js +19 -9
  159. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  160. package/lib/chain/validation/proposerPreferences.d.ts +8 -0
  161. package/lib/chain/validation/proposerPreferences.d.ts.map +1 -0
  162. package/lib/chain/validation/proposerPreferences.js +91 -0
  163. package/lib/chain/validation/proposerPreferences.js.map +1 -0
  164. package/lib/db/repositories/executionPayloadEnvelopeArchive.js +1 -1
  165. package/lib/db/repositories/executionPayloadEnvelopeArchive.js.map +1 -1
  166. package/lib/execution/engine/http.d.ts.map +1 -1
  167. package/lib/execution/engine/http.js +21 -14
  168. package/lib/execution/engine/http.js.map +1 -1
  169. package/lib/execution/engine/interface.d.ts +1 -0
  170. package/lib/execution/engine/interface.d.ts.map +1 -1
  171. package/lib/execution/engine/mock.d.ts.map +1 -1
  172. package/lib/execution/engine/mock.js +6 -0
  173. package/lib/execution/engine/mock.js.map +1 -1
  174. package/lib/execution/engine/types.d.ts +20 -0
  175. package/lib/execution/engine/types.d.ts.map +1 -1
  176. package/lib/execution/engine/types.js +18 -0
  177. package/lib/execution/engine/types.js.map +1 -1
  178. package/lib/metrics/metrics/lodestar.d.ts +1 -0
  179. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  180. package/lib/metrics/metrics/lodestar.js +4 -0
  181. package/lib/metrics/metrics/lodestar.js.map +1 -1
  182. package/lib/network/gossip/interface.d.ts +7 -1
  183. package/lib/network/gossip/interface.d.ts.map +1 -1
  184. package/lib/network/gossip/interface.js +1 -0
  185. package/lib/network/gossip/interface.js.map +1 -1
  186. package/lib/network/gossip/scoringParameters.d.ts.map +1 -1
  187. package/lib/network/gossip/scoringParameters.js +12 -1
  188. package/lib/network/gossip/scoringParameters.js.map +1 -1
  189. package/lib/network/gossip/topic.d.ts +13 -2
  190. package/lib/network/gossip/topic.d.ts.map +1 -1
  191. package/lib/network/gossip/topic.js +6 -0
  192. package/lib/network/gossip/topic.js.map +1 -1
  193. package/lib/network/interface.d.ts +1 -0
  194. package/lib/network/interface.d.ts.map +1 -1
  195. package/lib/network/network.d.ts +1 -0
  196. package/lib/network/network.d.ts.map +1 -1
  197. package/lib/network/network.js +6 -1
  198. package/lib/network/network.js.map +1 -1
  199. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  200. package/lib/network/processor/gossipHandlers.js +27 -19
  201. package/lib/network/processor/gossipHandlers.js.map +1 -1
  202. package/lib/network/processor/gossipQueues/index.d.ts.map +1 -1
  203. package/lib/network/processor/gossipQueues/index.js +5 -0
  204. package/lib/network/processor/gossipQueues/index.js.map +1 -1
  205. package/lib/network/processor/index.d.ts.map +1 -1
  206. package/lib/network/processor/index.js +6 -5
  207. package/lib/network/processor/index.js.map +1 -1
  208. package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
  209. package/lib/network/reqresp/handlers/beaconBlocksByRange.js +14 -6
  210. package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
  211. package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts.map +1 -1
  212. package/lib/network/reqresp/handlers/blobSidecarsByRange.js +11 -5
  213. package/lib/network/reqresp/handlers/blobSidecarsByRange.js.map +1 -1
  214. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
  215. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +17 -5
  216. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
  217. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -1
  218. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +7 -4
  219. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
  220. package/lib/node/nodejs.js +2 -2
  221. package/lib/node/nodejs.js.map +1 -1
  222. package/lib/sync/range/batch.d.ts +23 -2
  223. package/lib/sync/range/batch.d.ts.map +1 -1
  224. package/lib/sync/range/batch.js +132 -44
  225. package/lib/sync/range/batch.js.map +1 -1
  226. package/lib/sync/range/chain.d.ts +6 -2
  227. package/lib/sync/range/chain.d.ts.map +1 -1
  228. package/lib/sync/range/chain.js +26 -7
  229. package/lib/sync/range/chain.js.map +1 -1
  230. package/lib/sync/range/range.d.ts.map +1 -1
  231. package/lib/sync/range/range.js +17 -6
  232. package/lib/sync/range/range.js.map +1 -1
  233. package/lib/sync/types.d.ts +34 -0
  234. package/lib/sync/types.d.ts.map +1 -1
  235. package/lib/sync/types.js +34 -0
  236. package/lib/sync/types.js.map +1 -1
  237. package/lib/sync/unknownBlock.d.ts +22 -1
  238. package/lib/sync/unknownBlock.d.ts.map +1 -1
  239. package/lib/sync/unknownBlock.js +602 -53
  240. package/lib/sync/unknownBlock.js.map +1 -1
  241. package/lib/sync/utils/downloadByRange.d.ts +46 -10
  242. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  243. package/lib/sync/utils/downloadByRange.js +162 -24
  244. package/lib/sync/utils/downloadByRange.js.map +1 -1
  245. package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
  246. package/lib/sync/utils/downloadByRoot.js +16 -2
  247. package/lib/sync/utils/downloadByRoot.js.map +1 -1
  248. package/lib/sync/utils/pendingBlocksTree.d.ts +0 -1
  249. package/lib/sync/utils/pendingBlocksTree.d.ts.map +1 -1
  250. package/lib/sync/utils/pendingBlocksTree.js +0 -9
  251. package/lib/sync/utils/pendingBlocksTree.js.map +1 -1
  252. package/lib/util/sszBytes.d.ts.map +1 -1
  253. package/lib/util/sszBytes.js +20 -5
  254. package/lib/util/sszBytes.js.map +1 -1
  255. package/package.json +16 -15
  256. package/src/api/impl/beacon/blocks/index.ts +22 -9
  257. package/src/api/impl/beacon/pool/index.ts +83 -1
  258. package/src/api/impl/beacon/state/utils.ts +2 -2
  259. package/src/api/impl/debug/index.ts +0 -1
  260. package/src/api/impl/lodestar/index.ts +1 -1
  261. package/src/api/impl/validator/index.ts +82 -5
  262. package/src/chain/archiveStore/archiveStore.ts +5 -5
  263. package/src/chain/archiveStore/interface.ts +4 -4
  264. package/src/chain/archiveStore/strategies/frequencyStateArchiveStrategy.ts +4 -4
  265. package/src/chain/archiveStore/utils/archiveBlocks.ts +153 -94
  266. package/src/chain/blocks/blockInput/blockInput.ts +4 -1
  267. package/src/chain/blocks/importBlock.ts +24 -38
  268. package/src/chain/blocks/importExecutionPayload.ts +109 -105
  269. package/src/chain/blocks/index.ts +73 -23
  270. package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +10 -2
  271. package/src/chain/blocks/payloadEnvelopeInput/types.ts +1 -0
  272. package/src/chain/blocks/payloadEnvelopeProcessor.ts +2 -2
  273. package/src/chain/blocks/types.ts +15 -25
  274. package/src/chain/blocks/utils/chainSegment.ts +114 -17
  275. package/src/chain/blocks/verifyBlock.ts +70 -9
  276. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +6 -4
  277. package/src/chain/blocks/verifyBlocksSanityChecks.ts +26 -7
  278. package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +134 -0
  279. package/src/chain/blocks/verifyPayloadsDataAvailability.ts +7 -4
  280. package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +9 -18
  281. package/src/chain/chain.ts +38 -19
  282. package/src/chain/emitter.ts +3 -14
  283. package/src/chain/errors/blockError.ts +4 -1
  284. package/src/chain/errors/executionPayloadBid.ts +6 -0
  285. package/src/chain/errors/executionPayloadEnvelope.ts +6 -0
  286. package/src/chain/errors/index.ts +1 -0
  287. package/src/chain/errors/proposerPreferences.ts +47 -0
  288. package/src/chain/forkChoice/index.ts +2 -22
  289. package/src/chain/interface.ts +11 -3
  290. package/src/chain/opPools/payloadAttestationPool.ts +29 -8
  291. package/src/chain/prepareNextSlot.ts +36 -14
  292. package/src/chain/produceBlock/produceBlockBody.ts +63 -13
  293. package/src/chain/regen/interface.ts +1 -0
  294. package/src/chain/regen/queued.ts +2 -7
  295. package/src/chain/regen/regen.ts +2 -7
  296. package/src/chain/seenCache/index.ts +1 -0
  297. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +47 -25
  298. package/src/chain/seenCache/seenProposerPreferences.ts +32 -0
  299. package/src/chain/stateCache/persistentCheckpointsCache.ts +4 -1
  300. package/src/chain/validation/block.ts +1 -0
  301. package/src/chain/validation/executionPayloadBid.ts +25 -8
  302. package/src/chain/validation/executionPayloadEnvelope.ts +20 -10
  303. package/src/chain/validation/proposerPreferences.ts +110 -0
  304. package/src/db/repositories/executionPayloadEnvelopeArchive.ts +1 -1
  305. package/src/execution/engine/http.ts +21 -14
  306. package/src/execution/engine/interface.ts +1 -0
  307. package/src/execution/engine/mock.ts +8 -1
  308. package/src/execution/engine/types.ts +41 -0
  309. package/src/metrics/metrics/lodestar.ts +4 -0
  310. package/src/network/gossip/interface.ts +6 -0
  311. package/src/network/gossip/scoringParameters.ts +14 -1
  312. package/src/network/gossip/topic.ts +6 -0
  313. package/src/network/interface.ts +1 -0
  314. package/src/network/network.ts +12 -1
  315. package/src/network/processor/gossipHandlers.ts +38 -20
  316. package/src/network/processor/gossipQueues/index.ts +5 -0
  317. package/src/network/processor/index.ts +6 -5
  318. package/src/network/reqresp/handlers/beaconBlocksByRange.ts +14 -6
  319. package/src/network/reqresp/handlers/blobSidecarsByRange.ts +11 -5
  320. package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +17 -5
  321. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +7 -4
  322. package/src/node/nodejs.ts +2 -2
  323. package/src/sync/range/batch.ts +188 -49
  324. package/src/sync/range/chain.ts +37 -9
  325. package/src/sync/range/range.ts +18 -6
  326. package/src/sync/types.ts +72 -0
  327. package/src/sync/unknownBlock.ts +760 -57
  328. package/src/sync/utils/downloadByRange.ts +272 -39
  329. package/src/sync/utils/downloadByRoot.ts +24 -2
  330. package/src/sync/utils/pendingBlocksTree.ts +0 -15
  331. package/src/util/sszBytes.ts +25 -5
@@ -1,29 +1,126 @@
1
1
  import {ChainForkConfig} from "@lodestar/config";
2
- import {ssz} from "@lodestar/types";
2
+ import {ProtoBlock} from "@lodestar/fork-choice";
3
+ import {Slot, isGloasBeaconBlock, ssz} from "@lodestar/types";
4
+ import {toRootHex} from "@lodestar/utils";
3
5
  import {BlockError, BlockErrorCode} from "../../errors/index.js";
4
6
  import {IBlockInput} from "../blockInput/types.js";
7
+ import {PayloadEnvelopeInput} from "../payloadEnvelopeInput/payloadEnvelopeInput.js";
8
+
9
+ export type OrphanedPayloadEnvelope = {
10
+ slot: Slot;
11
+ payloadEnvelopeInput: PayloadEnvelopeInput;
12
+ };
13
+
14
+ export type ChainSegmentResult = {warnings: OrphanedPayloadEnvelope[] | null};
5
15
 
6
16
  /**
7
- * Assert this chain segment of blocks is linear with slot numbers and hashes
17
+ * Assert this chain segment of blocks is linear with slot numbers and hashes,
18
+ * and that the provided envelopes are consistent with their respective blocks.
19
+ *
20
+ * Must be called after verifyBlocksSanityChecks so that parentBlock (from forkchoice)
21
+ * is available to seed the execution hash chain.
22
+ *
23
+ * For each block:
24
+ * - Verifies parent root + slot linearity
25
+ * - For gloas: verifies bid.parentBlockHash matches the tracked execution hash; if not, the
26
+ * previous FULL envelope is treated as orphaned (segment continues as if previous slot was EMPTY)
27
+ * - If an envelope exists for this slot: verifies it references this block's root
28
+ * - Advances the tracked execution hash (FULL if envelope present, EMPTY if not)
8
29
  */
30
+ export function assertLinearChainSegment(
31
+ config: ChainForkConfig,
32
+ blocks: IBlockInput[],
33
+ payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
34
+ parentBlock: ProtoBlock
35
+ ): ChainSegmentResult {
36
+ const warnings: OrphanedPayloadEnvelope[] = [];
9
37
 
10
- export function assertLinearChainSegment(config: ChainForkConfig, blocks: IBlockInput[]): void {
11
- for (let i = 0; i < blocks.length - 1; i++) {
38
+ // Track the expected execution payload block hash through the segment.
39
+ // Starts from the known forkchoice parent's execution hash.
40
+ // - FULL variant (envelope present for slot): advances to envelope.payload.blockHash
41
+ // - EMPTY variant (no envelope for slot): execution hash is unchanged
42
+ // null only for pre-merge parents, which cannot precede gloas blocks.
43
+ let currentExecHash: string | null = parentBlock.executionPayloadBlockHash;
44
+ // Checkpoint sync first batch: parent is the anchor PENDING whose executionPayloadBlockHash
45
+ // is the inherited parentBlockHash semantic (= grandparent's payload), not its own payload.
46
+ // If parent's own payload envelope arrives in this batch, advance currentExecHash to that
47
+ // payload's blockHash so the segment validation sees the true EL chain head.
48
+ const parentPayloadInput = payloadEnvelopes?.get(parentBlock.slot);
49
+ if (parentPayloadInput?.hasPayloadEnvelope()) {
50
+ currentExecHash = parentPayloadInput.getBlockHashHex();
51
+ }
52
+ // Track the execution hash before the last FULL advancement so we can recover
53
+ // if the next block reveals that envelope was orphaned.
54
+ let prevExecHash: string | null = currentExecHash;
55
+ // The slot whose envelope last advanced currentExecHash (for warning context).
56
+ let lastFullSlot: Slot | null = null;
57
+
58
+ for (let i = 0; i < blocks.length; i++) {
12
59
  const block = blocks[i].getBlock();
13
- const child = blocks[i + 1].getBlock();
14
- // If this block has a child in this chain segment, ensure that its parent root matches
15
- // the root of this block.
16
- if (
17
- !ssz.Root.equals(
18
- config.getForkTypes(block.message.slot).BeaconBlock.hashTreeRoot(block.message),
19
- child.message.parentRoot
20
- )
21
- ) {
22
- throw new BlockError(block, {code: BlockErrorCode.NON_LINEAR_PARENT_ROOTS});
60
+ const slot = block.message.slot;
61
+
62
+ if (i > 0) {
63
+ const prevBlock = blocks[i - 1].getBlock();
64
+ // Ensure parent root matches the previous block's root
65
+ if (
66
+ !ssz.Root.equals(
67
+ config.getForkTypes(prevBlock.message.slot).BeaconBlock.hashTreeRoot(prevBlock.message),
68
+ block.message.parentRoot
69
+ )
70
+ ) {
71
+ throw new BlockError(block, {code: BlockErrorCode.NON_LINEAR_PARENT_ROOTS});
72
+ }
73
+ // Ensure slots are strictly increasing
74
+ if (slot <= prevBlock.message.slot) {
75
+ throw new BlockError(block, {code: BlockErrorCode.NON_LINEAR_SLOTS});
76
+ }
23
77
  }
24
- // Ensure that the slots are strictly increasing throughout the chain segment.
25
- if (child.message.slot <= block.message.slot) {
26
- throw new BlockError(block, {code: BlockErrorCode.NON_LINEAR_SLOTS});
78
+
79
+ if (isGloasBeaconBlock(block.message) && currentExecHash !== null) {
80
+ // Verify the bid's parentBlockHash matches the tracked execution hash.
81
+ // This ensures the block was built on the correct FULL or EMPTY variant of its parent.
82
+ const bidParentHash = toRootHex(block.message.body.signedExecutionPayloadBid.message.parentBlockHash);
83
+ if (bidParentHash !== currentExecHash) {
84
+ // Maybe the previous slot's FULL envelope was orphaned — try falling back.
85
+ // If even prevExecHash doesn't match, the segment is non-linear.
86
+ if (bidParentHash !== prevExecHash) {
87
+ throw new BlockError(block, {
88
+ code: BlockErrorCode.PARENT_PAYLOAD_UNKNOWN,
89
+ parentRoot: toRootHex(block.message.parentRoot),
90
+ parentBlockHash: bidParentHash,
91
+ });
92
+ }
93
+ if (lastFullSlot !== null && payloadEnvelopes !== null) {
94
+ const orphanedInput = payloadEnvelopes.get(lastFullSlot);
95
+ if (orphanedInput != null) {
96
+ warnings.push({slot: lastFullSlot, payloadEnvelopeInput: orphanedInput});
97
+ }
98
+ }
99
+ currentExecHash = prevExecHash;
100
+ }
101
+
102
+ const payloadInput = payloadEnvelopes?.get(slot) ?? null;
103
+ const payloadEnvelope = payloadInput?.hasPayloadEnvelope() ? payloadInput.getPayloadEnvelope() : null;
104
+ if (payloadEnvelope !== null) {
105
+ // Verify the envelope references this block's root
106
+ const blockRoot = toRootHex(config.getForkTypes(slot).BeaconBlock.hashTreeRoot(block.message));
107
+ const envelopeBlockRoot = toRootHex(payloadEnvelope.message.beaconBlockRoot);
108
+ if (blockRoot !== envelopeBlockRoot) {
109
+ throw new BlockError(block, {
110
+ code: BlockErrorCode.ENVELOPE_BLOCK_ROOT_MISMATCH,
111
+ envelopeBlockRoot,
112
+ blockRoot,
113
+ });
114
+ }
115
+
116
+ // FULL variant: save state before advancing, then advance
117
+ prevExecHash = currentExecHash;
118
+ lastFullSlot = slot;
119
+ currentExecHash = toRootHex(payloadEnvelope.message.payload.blockHash);
120
+ }
121
+ // EMPTY variant: currentExecHash unchanged
27
122
  }
28
123
  }
124
+
125
+ return {warnings: warnings.length > 0 ? warnings : null};
29
126
  }
@@ -1,12 +1,14 @@
1
1
  import {ExecutionStatus, ProtoBlock} from "@lodestar/fork-choice";
2
- import {ForkName, isForkPostFulu} from "@lodestar/params";
2
+ import {ForkName, ForkSeq, isForkPostFulu} from "@lodestar/params";
3
3
  import {DataAvailabilityStatus, IBeaconStateView, computeEpochAtSlot} from "@lodestar/state-transition";
4
- import {IndexedAttestation, deneb} from "@lodestar/types";
4
+ import {IndexedAttestation, Slot, deneb} from "@lodestar/types";
5
+ import {getBlobKzgCommitments} from "../../util/dataColumns.js";
5
6
  import type {BeaconChain} from "../chain.js";
6
7
  import {BlockError, BlockErrorCode} from "../errors/index.js";
7
8
  import {BlockProcessOpts} from "../options.js";
8
9
  import {RegenCaller} from "../regen/index.js";
9
10
  import {DAType, IBlockInput} from "./blockInput/index.js";
11
+ import {PayloadEnvelopeInput} from "./payloadEnvelopeInput/payloadEnvelopeInput.js";
10
12
  import {ImportBlockOpts} from "./types.js";
11
13
  import {DENEB_BLOWFISH_BANNER} from "./utils/blowfishBanner.js";
12
14
  import {ELECTRA_GIRAFFE_BANNER} from "./utils/giraffeBanner.js";
@@ -16,6 +18,7 @@ import {verifyBlocksDataAvailability} from "./verifyBlocksDataAvailability.js";
16
18
  import {SegmentExecStatus, verifyBlocksExecutionPayload} from "./verifyBlocksExecutionPayloads.js";
17
19
  import {verifyBlocksSignatures} from "./verifyBlocksSignatures.js";
18
20
  import {verifyBlocksStateTransitionOnly} from "./verifyBlocksStateTransitionOnly.js";
21
+ import {verifyPayloadsDataAvailability} from "./verifyPayloadsDataAvailability.js";
19
22
 
20
23
  /**
21
24
  * Verifies 1 or more blocks are fully valid; from a linear sequence of blocks.
@@ -32,12 +35,14 @@ export async function verifyBlocksInEpoch(
32
35
  this: BeaconChain,
33
36
  parentBlock: ProtoBlock,
34
37
  blockInputs: IBlockInput[],
38
+ payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
35
39
  opts: BlockProcessOpts & ImportBlockOpts
36
40
  ): Promise<{
37
41
  postStates: IBeaconStateView[];
38
42
  proposerBalanceDeltas: number[];
39
43
  segmentExecStatus: SegmentExecStatus;
40
- dataAvailabilityStatuses: DataAvailabilityStatus[];
44
+ blockDAStatuses: DataAvailabilityStatus[];
45
+ payloadDAStatuses: Map<Slot, DataAvailabilityStatus>;
41
46
  indexedAttestationsByBlock: IndexedAttestation[][];
42
47
  }> {
43
48
  const blocks = blockInputs.map((blockInput) => blockInput.getBlock());
@@ -110,17 +115,61 @@ export async function verifyBlocksInEpoch(
110
115
  });
111
116
  }
112
117
 
118
+ // Pick the data-availability source by fork:
119
+ // - Pre-Gloas: blob/Fulu-column data lives in IBlockInput → verifyBlocksDataAvailability.
120
+ // - Post-Gloas: verifyPayloadsDataAvailability (payload-level DA, keyed by slot).
121
+ const daAvailabilityPromise: Promise<{
122
+ blockDAStatuses: DataAvailabilityStatus[];
123
+ payloadDAStatuses: Map<Slot, DataAvailabilityStatus>;
124
+ availableTime: number;
125
+ }> =
126
+ fork >= ForkSeq.gloas
127
+ ? (async () => {
128
+ // Validate DA for ALL payloads in the Map, not just those paired with blockInputs.
129
+ // A checkpoint-sync batch may include a payload for a slot whose block was filtered
130
+ // out of relevantBlocks (e.g., the anchor at the finalized slot); that payload still
131
+ // needs DA validation so it can be imported in processBlocks.
132
+ const payloadInputsForDa: PayloadEnvelopeInput[] =
133
+ payloadEnvelopes !== null ? Array.from(payloadEnvelopes.values()) : [];
134
+ const {dataAvailabilityStatuses, availableTime} = await verifyPayloadsDataAvailability(
135
+ payloadInputsForDa,
136
+ abortController.signal
137
+ );
138
+
139
+ const payloadDAStatuses = new Map<Slot, DataAvailabilityStatus>();
140
+ for (let i = 0; i < payloadInputsForDa.length; i++) {
141
+ payloadDAStatuses.set(payloadInputsForDa[i].slot, dataAvailabilityStatuses[i]);
142
+ }
143
+ return {
144
+ // post-gloas, DataAvailabilityStatus is NotRequired for forkChoice.onBlock() ProtoBlock
145
+ blockDAStatuses: blockInputs.map(() => DataAvailabilityStatus.NotRequired),
146
+ payloadDAStatuses,
147
+ availableTime,
148
+ };
149
+ })()
150
+ : (async () => {
151
+ const {dataAvailabilityStatuses, availableTime} = await verifyBlocksDataAvailability(
152
+ blockInputs,
153
+ abortController.signal
154
+ );
155
+ return {
156
+ blockDAStatuses: dataAvailabilityStatuses,
157
+ payloadDAStatuses: new Map<Slot, DataAvailabilityStatus>(),
158
+ availableTime,
159
+ };
160
+ })();
161
+
113
162
  // batch all I/O operations to reduce overhead
114
163
  const [
115
164
  segmentExecStatus,
116
- {dataAvailabilityStatuses, availableTime},
165
+ {blockDAStatuses, payloadDAStatuses, availableTime},
117
166
  {postStates, proposerBalanceDeltas, verifyStateTime},
118
167
  {verifySignaturesTime},
119
168
  ] = await Promise.all([
120
169
  verifyExecutionPayloadsPromise,
121
170
 
122
- // data availability for the blobs
123
- verifyBlocksDataAvailability(blockInputs, abortController.signal),
171
+ // data availability (fork-specific; see daAvailabilityPromise above)
172
+ daAvailabilityPromise,
124
173
 
125
174
  // Run state transition only
126
175
  // TODO: Ensure it yields to allow flushing to workers and engine API
@@ -149,6 +198,9 @@ export async function verifyBlocksInEpoch(
149
198
  opts
150
199
  )
151
200
  : Promise.resolve({verifySignaturesTime: Date.now()}),
201
+
202
+ // TODO GLOAS: can verify payload signatures in batch too
203
+ // maybe chain with the above verifyBlocksSignatures()
152
204
  ]);
153
205
 
154
206
  if (opts.verifyOnly !== true) {
@@ -200,7 +252,9 @@ export async function verifyBlocksInEpoch(
200
252
  blockInputs.length === 1 &&
201
253
  // gossip blocks have seenTimestampSec
202
254
  opts.seenTimestampSec !== undefined &&
255
+ // PreData (pre-deneb) and NoData (gloas) carry no blob data on the block — skip metric
203
256
  blockInputs[0].type !== DAType.PreData &&
257
+ blockInputs[0].type !== DAType.NoData &&
204
258
  executionStatuses[0] === ExecutionStatus.Valid
205
259
  ) {
206
260
  // Find the max time when the block was actually verified
@@ -209,8 +263,8 @@ export async function verifyBlocksInEpoch(
209
263
  this.metrics?.gossipBlock.receivedToFullyVerifiedTime.observe(recvTofullyVerifedTime);
210
264
 
211
265
  const verifiedToBlobsAvailabiltyTime = Math.max(availableTime - fullyVerifiedTime, 0) / 1000;
212
- const block = blockInputs[0].getBlock() as deneb.SignedBeaconBlock;
213
- const numBlobs = block.message.body.blobKzgCommitments.length;
266
+ const block = blockInputs[0].getBlock();
267
+ const numBlobs = getBlobKzgCommitments(blockInputs[0].forkName, block as deneb.SignedBeaconBlock).length;
214
268
 
215
269
  this.metrics?.gossipBlock.verifiedToBlobsAvailabiltyTime.observe({numBlobs}, verifiedToBlobsAvailabiltyTime);
216
270
  this.logger.verbose("Verified blockInput fully with blobs availability", {
@@ -229,7 +283,14 @@ export async function verifyBlocksInEpoch(
229
283
  );
230
284
  }
231
285
 
232
- return {postStates, dataAvailabilityStatuses, proposerBalanceDeltas, segmentExecStatus, indexedAttestationsByBlock};
286
+ return {
287
+ postStates,
288
+ blockDAStatuses,
289
+ payloadDAStatuses,
290
+ proposerBalanceDeltas,
291
+ segmentExecStatus,
292
+ indexedAttestationsByBlock,
293
+ };
233
294
  } finally {
234
295
  abortController.abort();
235
296
  }
@@ -46,8 +46,7 @@ type VerifyBlockExecutionResponse =
46
46
  | VerifyExecutionErrorResponse
47
47
  | {executionStatus: ExecutionStatus.Valid; lvhResponse: LVHValidResponse; execError: null}
48
48
  | {executionStatus: ExecutionStatus.Syncing; lvhResponse?: LVHValidResponse; execError: null}
49
- | {executionStatus: ExecutionStatus.PreMerge; lvhResponse: undefined; execError: null}
50
- | {executionStatus: ExecutionStatus.PayloadSeparated; lvhResponse: undefined; execError: null};
49
+ | {executionStatus: ExecutionStatus.PreMerge; lvhResponse: undefined; execError: null};
51
50
 
52
51
  /**
53
52
  * Verifies 1 or more execution payloads from a linear sequence of blocks.
@@ -145,9 +144,10 @@ export async function verifyBlockExecutionPayload(
145
144
  ): Promise<VerifyBlockExecutionResponse> {
146
145
  const block = blockInput.getBlock();
147
146
 
148
- // Gloas block doesn't have execution payload. Return right away
147
+ // Gloas block doesn't have execution payload. Return Syncing as a placeholder; the actual
148
+ // status for gloas PENDING/EMPTY is derived from parent's chain in importBlock.
149
149
  if (isBlockInputNoData(blockInput)) {
150
- return {executionStatus: ExecutionStatus.PayloadSeparated, lvhResponse: undefined, execError: null};
150
+ return {executionStatus: ExecutionStatus.Syncing, lvhResponse: undefined, execError: null};
151
151
  }
152
152
 
153
153
  /** Not null if execution is enabled */
@@ -198,6 +198,7 @@ export async function verifyBlockExecutionPayload(
198
198
  executionStatus,
199
199
  latestValidExecHash: execResult.latestValidHash,
200
200
  invalidateFromParentBlockRoot: blockInput.parentRootHex,
201
+ invalidateFromParentBlockHash: toRootHex(executionPayloadEnabled.parentHash),
201
202
  };
202
203
  const execError = new BlockError(block, {
203
204
  code: BlockErrorCode.EXECUTION_ENGINE_ERROR,
@@ -281,6 +282,7 @@ function getSegmentErrorResponse(
281
282
  executionStatus: ExecutionStatus.Invalid,
282
283
  latestValidExecHash: lvhResponse.latestValidExecHash,
283
284
  invalidateFromParentBlockRoot: parentBlock.blockRoot,
285
+ invalidateFromParentBlockHash: parentBlock.executionPayloadBlockHash,
284
286
  };
285
287
  }
286
288
  }
@@ -7,6 +7,7 @@ import {IClock} from "../../util/clock.js";
7
7
  import {BlockError, BlockErrorCode} from "../errors/index.js";
8
8
  import {IChainOptions} from "../options.js";
9
9
  import {IBlockInput} from "./blockInput/types.js";
10
+ import {PayloadEnvelopeInput} from "./payloadEnvelopeInput/payloadEnvelopeInput.js";
10
11
  import {ImportBlockOpts} from "./types.js";
11
12
 
12
13
  /**
@@ -30,6 +31,7 @@ export function verifyBlocksSanityChecks(
30
31
  blacklistedBlocks: Map<RootHex, Slot | null>;
31
32
  },
32
33
  blocks: IBlockInput[],
34
+ payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
33
35
  opts: ImportBlockOpts
34
36
  ): {
35
37
  relevantBlocks: IBlockInput[];
@@ -90,15 +92,32 @@ export function verifyBlocksSanityChecks(
90
92
  } else {
91
93
  // When importing a block segment, only the first NON-IGNORED block must be known to the fork-choice.
92
94
  const parentRoot = toRootHex(block.message.parentRoot);
93
- parentBlock = isGloasBeaconBlock(block.message)
94
- ? chain.forkChoice.getBlockHexAndBlockHash(
95
- parentRoot,
96
- toRootHex(block.message.body.signedExecutionPayloadBid.message.parentBlockHash)
97
- )
98
- : chain.forkChoice.getBlockHexDefaultStatus(parentRoot);
99
- if (!parentBlock) {
95
+ const parentBlockDefaultStatus = chain.forkChoice.getBlockHexDefaultStatus(parentRoot);
96
+ if (!parentBlockDefaultStatus) {
100
97
  throw new BlockError(block, {code: BlockErrorCode.PARENT_UNKNOWN, parentRoot});
101
98
  }
99
+
100
+ parentBlock = parentBlockDefaultStatus;
101
+ if (isGloasBeaconBlock(block.message)) {
102
+ const parentBlockHash = toRootHex(block.message.body.signedExecutionPayloadBid.message.parentBlockHash);
103
+ const parentBlockWithPayload = chain.forkChoice.getBlockHexAndBlockHash(parentRoot, parentBlockHash);
104
+ if (!parentBlockWithPayload) {
105
+ // Checkpoint sync: parent's FULL variant may not be in fork-choice yet because the
106
+ // anchor block is initialized with PENDING+EMPTY only. The parent's payload arrives
107
+ // in the same batch via payloadEnvelopes and will be imported by processBlocks. If
108
+ // a matching payload is in the Map, accept the parent as known.
109
+ const parentPayloadInput = payloadEnvelopes?.get(parentBlockDefaultStatus.slot);
110
+ if (parentPayloadInput?.getBlockHashHex() !== parentBlockHash) {
111
+ throw new BlockError(block, {
112
+ code: BlockErrorCode.PARENT_PAYLOAD_UNKNOWN,
113
+ parentRoot,
114
+ parentBlockHash,
115
+ });
116
+ }
117
+ } else {
118
+ parentBlock = parentBlockWithPayload;
119
+ }
120
+ }
102
121
  // Parent is known to the fork-choice
103
122
  parentBlockSlot = parentBlock.slot;
104
123
  }
@@ -0,0 +1,134 @@
1
+ import {BeaconConfig} from "@lodestar/config";
2
+ import {
3
+ type IBeaconStateViewGloas,
4
+ type PubkeyCache,
5
+ computeTimeAtSlot,
6
+ getExecutionPayloadEnvelopeSignatureSet,
7
+ } from "@lodestar/state-transition";
8
+ import {gloas, ssz} from "@lodestar/types";
9
+ import {byteArrayEquals, toHex, toRootHex} from "@lodestar/utils";
10
+ import {IBlsVerifier} from "../bls/index.js";
11
+
12
+ export type VerifyExecutionPayloadEnvelopeOpts = {
13
+ verifyExecutionRequestsRoot?: boolean;
14
+ };
15
+
16
+ /**
17
+ * Verify execution payload envelope fields against the post-block state.
18
+ *
19
+ * Signature verification and the execution engine call (`verify_and_notify_new_payload`) are
20
+ * performed outside this function, see `verifyExecutionPayloadEnvelopeSignature` and
21
+ * `importExecutionPayload` which run both in parallel with this check.
22
+ *
23
+ * Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/fork-choice.md#new-verify_execution_payload_envelope
24
+ */
25
+ export function verifyExecutionPayloadEnvelope(
26
+ config: BeaconConfig,
27
+ state: IBeaconStateViewGloas,
28
+ envelope: gloas.ExecutionPayloadEnvelope,
29
+ opts?: VerifyExecutionPayloadEnvelopeOpts
30
+ ): void {
31
+ const {verifyExecutionRequestsRoot = true} = opts ?? {};
32
+ const payload = envelope.payload;
33
+
34
+ // Verify consistency with the beacon block.
35
+ // Compute header root on a clone of latestBlockHeader to avoid mutating state.
36
+ const headerValue = ssz.phase0.BeaconBlockHeader.clone(state.latestBlockHeader);
37
+ if (byteArrayEquals(headerValue.stateRoot, ssz.Root.defaultValue())) {
38
+ headerValue.stateRoot = state.hashTreeRoot();
39
+ }
40
+ const headerRoot = ssz.phase0.BeaconBlockHeader.hashTreeRoot(headerValue);
41
+ if (!byteArrayEquals(envelope.beaconBlockRoot, headerRoot)) {
42
+ throw new Error(
43
+ `Envelope's block is not the latest block header envelope=${toRootHex(envelope.beaconBlockRoot)} latestBlockHeader=${toRootHex(headerRoot)}`
44
+ );
45
+ }
46
+ if (!byteArrayEquals(envelope.parentBeaconBlockRoot, state.latestBlockHeader.parentRoot)) {
47
+ throw new Error(
48
+ `Envelope's parent_beacon_block_root mismatch envelope=${toRootHex(envelope.parentBeaconBlockRoot)} state=${toRootHex(state.latestBlockHeader.parentRoot)}`
49
+ );
50
+ }
51
+
52
+ // Verify consistency with the committed bid
53
+ const bid = state.latestExecutionPayloadBid;
54
+ if (envelope.builderIndex !== bid.builderIndex) {
55
+ throw new Error(
56
+ `Builder index mismatch between envelope and committed bid envelope=${envelope.builderIndex} bid=${bid.builderIndex}`
57
+ );
58
+ }
59
+ if (!byteArrayEquals(bid.prevRandao, payload.prevRandao)) {
60
+ throw new Error(
61
+ `Prev randao mismatch between bid and payload bid=${toHex(bid.prevRandao)} payload=${toHex(payload.prevRandao)}`
62
+ );
63
+ }
64
+ if (Number(bid.gasLimit) !== payload.gasLimit) {
65
+ throw new Error(
66
+ `Gas limit mismatch between payload and bid payload=${payload.gasLimit} bid=${Number(bid.gasLimit)}`
67
+ );
68
+ }
69
+ if (!byteArrayEquals(bid.blockHash, payload.blockHash)) {
70
+ throw new Error(
71
+ `Block hash mismatch between payload and bid payload=${toRootHex(payload.blockHash)} bid=${toRootHex(bid.blockHash)}`
72
+ );
73
+ }
74
+ // Verify execution_requests_root matches bid commitment.
75
+ // Can be skipped if already verified during gossip validation.
76
+ if (verifyExecutionRequestsRoot) {
77
+ const requestsRoot = ssz.electra.ExecutionRequests.hashTreeRoot(envelope.executionRequests);
78
+ if (!byteArrayEquals(requestsRoot, bid.executionRequestsRoot)) {
79
+ throw new Error(
80
+ `Execution requests root mismatch envelope=${toRootHex(requestsRoot)} bid=${toRootHex(bid.executionRequestsRoot)}`
81
+ );
82
+ }
83
+ }
84
+
85
+ // Verify the execution payload is valid
86
+ if (payload.slotNumber !== state.slot) {
87
+ throw new Error(`Slot mismatch between payload and state payload=${payload.slotNumber} state=${state.slot}`);
88
+ }
89
+ if (!byteArrayEquals(payload.parentHash, state.latestBlockHash)) {
90
+ throw new Error(
91
+ `Parent hash mismatch between payload and state payload=${toRootHex(payload.parentHash)} state=${toRootHex(state.latestBlockHash)}`
92
+ );
93
+ }
94
+ const expectedTimestamp = computeTimeAtSlot(config, state.slot, state.genesisTime);
95
+ if (payload.timestamp !== expectedTimestamp) {
96
+ throw new Error(
97
+ `Timestamp mismatch between payload and state payload=${payload.timestamp} state=${expectedTimestamp}`
98
+ );
99
+ }
100
+
101
+ // Verify consistency with expected withdrawals
102
+ const payloadWithdrawalsRoot = ssz.capella.Withdrawals.hashTreeRoot(payload.withdrawals);
103
+ const expectedWithdrawalsRoot = ssz.capella.Withdrawals.hashTreeRoot(state.payloadExpectedWithdrawals);
104
+ if (!byteArrayEquals(payloadWithdrawalsRoot, expectedWithdrawalsRoot)) {
105
+ throw new Error(
106
+ `Withdrawals mismatch between payload and expected payload=${toRootHex(payloadWithdrawalsRoot)} expected=${toRootHex(expectedWithdrawalsRoot)}`
107
+ );
108
+ }
109
+
110
+ // Execution engine verification (verify_and_notify_new_payload) is done externally by the caller
111
+ }
112
+
113
+ /**
114
+ * Verify the BLS signature of an execution payload envelope.
115
+ *
116
+ * Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/fork-choice.md#new-verify_execution_payload_envelope_signature
117
+ */
118
+ export async function verifyExecutionPayloadEnvelopeSignature(
119
+ config: BeaconConfig,
120
+ state: IBeaconStateViewGloas,
121
+ pubkeyCache: PubkeyCache,
122
+ signedEnvelope: gloas.SignedExecutionPayloadEnvelope,
123
+ proposerIndex: number,
124
+ bls: IBlsVerifier
125
+ ): Promise<boolean> {
126
+ const signatureSet = getExecutionPayloadEnvelopeSignatureSet(
127
+ config,
128
+ pubkeyCache,
129
+ state,
130
+ signedEnvelope,
131
+ proposerIndex
132
+ );
133
+ return bls.verifySignatureSets([signatureSet]);
134
+ }
@@ -28,11 +28,14 @@ export async function verifyPayloadsDataAvailability(
28
28
  await Promise.all(promises);
29
29
 
30
30
  const availableTime = Math.max(0, Math.max(...payloadInputs.map((payloadInput) => payloadInput.getTimeComplete())));
31
- const dataAvailabilityStatuses: DataAvailabilityStatus[] = payloadInputs.map((payloadInput) =>
32
- payloadInput.getBlobKzgCommitments().length === 0
31
+ const dataAvailabilityStatuses: DataAvailabilityStatus[] = payloadInputs.map((payloadInput) => {
32
+ if (payloadInput.daOutOfRange) {
33
+ return DataAvailabilityStatus.OutOfRange;
34
+ }
35
+ return payloadInput.getBlobKzgCommitments().length === 0
33
36
  ? DataAvailabilityStatus.NotRequired
34
- : DataAvailabilityStatus.Available
35
- );
37
+ : DataAvailabilityStatus.Available;
38
+ });
36
39
 
37
40
  return {dataAvailabilityStatuses, availableTime};
38
41
  }
@@ -5,7 +5,7 @@ import {writeDataColumnsToDb} from "./writeBlockInputToDb.js";
5
5
  /**
6
6
  * Persists payload envelope data to DB. This operation must be eventually completed if a payload is imported.
7
7
  *
8
- * TODO GLOAS: Persist envelope metadata (stateRoot, executionRequests, builderIndex, etc.) without the full
8
+ * TODO GLOAS: Persist envelope metadata (executionRequests, builderIndex, etc.) without the full
9
9
  * execution payload body — only keep the blockHash reference. The EL already stores the payload.
10
10
  * See https://github.com/ChainSafe/lodestar/issues/5671
11
11
  */
@@ -33,23 +33,14 @@ export async function persistPayloadEnvelopeInput(
33
33
  this: BeaconChain,
34
34
  payloadInput: PayloadEnvelopeInput
35
35
  ): Promise<void> {
36
- await writePayloadEnvelopeInputToDb
37
- .call(this, payloadInput)
38
- .catch((e) => {
39
- this.logger.error(
40
- "Error persisting payload envelope in hot db",
41
- {
42
- slot: payloadInput.slot,
43
- root: payloadInput.blockRootHex,
44
- },
45
- e
46
- );
47
- })
48
- .finally(() => {
49
- this.seenPayloadEnvelopeInputCache.prune(payloadInput.blockRootHex);
50
- this.logger.debug("Pruned payload envelope input", {
36
+ await writePayloadEnvelopeInputToDb.call(this, payloadInput).catch((e) => {
37
+ this.logger.error(
38
+ "Error persisting payload envelope in hot db",
39
+ {
51
40
  slot: payloadInput.slot,
52
41
  root: payloadInput.blockRootHex,
53
- });
54
- });
42
+ },
43
+ e
44
+ );
45
+ });
55
46
  }