@lodestar/beacon-node 1.42.0-rc.0 → 1.43.0-dev.07875b3e0c

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 (320) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +21 -4
  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 +4 -0
  6. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  7. package/lib/api/impl/beacon/state/index.d.ts.map +1 -1
  8. package/lib/api/impl/beacon/state/index.js +13 -10
  9. package/lib/api/impl/beacon/state/index.js.map +1 -1
  10. package/lib/api/impl/beacon/state/utils.d.ts +2 -2
  11. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  12. package/lib/api/impl/beacon/state/utils.js.map +1 -1
  13. package/lib/api/impl/lodestar/attesterSlashing.d.ts +8 -0
  14. package/lib/api/impl/lodestar/attesterSlashing.d.ts.map +1 -0
  15. package/lib/api/impl/lodestar/attesterSlashing.js +29 -0
  16. package/lib/api/impl/lodestar/attesterSlashing.js.map +1 -0
  17. package/lib/api/impl/lodestar/index.d.ts.map +1 -1
  18. package/lib/api/impl/lodestar/index.js +39 -0
  19. package/lib/api/impl/lodestar/index.js.map +1 -1
  20. package/lib/api/impl/validator/index.d.ts.map +1 -1
  21. package/lib/api/impl/validator/index.js +8 -5
  22. package/lib/api/impl/validator/index.js.map +1 -1
  23. package/lib/chain/GetBlobsTracker.d.ts +1 -1
  24. package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
  25. package/lib/chain/GetBlobsTracker.js +1 -2
  26. package/lib/chain/GetBlobsTracker.js.map +1 -1
  27. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  28. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  29. package/lib/chain/archiveStore/interface.d.ts +4 -4
  30. package/lib/chain/archiveStore/interface.d.ts.map +1 -1
  31. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts +4 -4
  32. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts.map +1 -1
  33. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js +2 -4
  34. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js.map +1 -1
  35. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +2 -2
  36. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
  37. package/lib/chain/archiveStore/utils/archiveBlocks.js +110 -58
  38. package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
  39. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  40. package/lib/chain/blocks/importBlock.js +29 -35
  41. package/lib/chain/blocks/importBlock.js.map +1 -1
  42. package/lib/chain/blocks/importExecutionPayload.d.ts +15 -14
  43. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  44. package/lib/chain/blocks/importExecutionPayload.js +69 -82
  45. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  46. package/lib/chain/blocks/index.d.ts.map +1 -1
  47. package/lib/chain/blocks/index.js +1 -2
  48. package/lib/chain/blocks/index.js.map +1 -1
  49. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +3 -0
  50. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
  51. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +20 -0
  52. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
  53. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +5 -0
  54. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -1
  55. package/lib/chain/blocks/payloadEnvelopeProcessor.js +6 -4
  56. package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
  57. package/lib/chain/blocks/types.d.ts +15 -21
  58. package/lib/chain/blocks/types.d.ts.map +1 -1
  59. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  60. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +3 -2
  61. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  62. package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
  63. package/lib/chain/blocks/verifyBlocksSignatures.js +4 -2
  64. package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
  65. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +24 -0
  66. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -0
  67. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +76 -0
  68. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -0
  69. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts +14 -0
  70. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -0
  71. package/lib/chain/blocks/verifyPayloadsDataAvailability.js +25 -0
  72. package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -0
  73. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts +1 -1
  74. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts.map +1 -1
  75. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js +2 -11
  76. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js.map +1 -1
  77. package/lib/chain/chain.d.ts +5 -4
  78. package/lib/chain/chain.d.ts.map +1 -1
  79. package/lib/chain/chain.js +32 -38
  80. package/lib/chain/chain.js.map +1 -1
  81. package/lib/chain/emitter.d.ts +16 -4
  82. package/lib/chain/emitter.d.ts.map +1 -1
  83. package/lib/chain/emitter.js +5 -0
  84. package/lib/chain/emitter.js.map +1 -1
  85. package/lib/chain/errors/attestationError.d.ts +8 -1
  86. package/lib/chain/errors/attestationError.d.ts.map +1 -1
  87. package/lib/chain/errors/attestationError.js +4 -0
  88. package/lib/chain/errors/attestationError.js.map +1 -1
  89. package/lib/chain/errors/blockError.d.ts +11 -1
  90. package/lib/chain/errors/blockError.d.ts.map +1 -1
  91. package/lib/chain/errors/blockError.js +4 -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/forkChoice/index.d.ts.map +1 -1
  102. package/lib/chain/forkChoice/index.js +21 -23
  103. package/lib/chain/forkChoice/index.js.map +1 -1
  104. package/lib/chain/interface.d.ts +4 -3
  105. package/lib/chain/interface.d.ts.map +1 -1
  106. package/lib/chain/interface.js.map +1 -1
  107. package/lib/chain/lightClient/index.d.ts +2 -2
  108. package/lib/chain/lightClient/index.d.ts.map +1 -1
  109. package/lib/chain/lightClient/index.js +7 -0
  110. package/lib/chain/lightClient/index.js.map +1 -1
  111. package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
  112. package/lib/chain/opPools/aggregatedAttestationPool.js +5 -2
  113. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  114. package/lib/chain/opPools/executionPayloadBidPool.d.ts +2 -2
  115. package/lib/chain/opPools/executionPayloadBidPool.d.ts.map +1 -1
  116. package/lib/chain/opPools/executionPayloadBidPool.js +2 -2
  117. package/lib/chain/opPools/executionPayloadBidPool.js.map +1 -1
  118. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  119. package/lib/chain/prepareNextSlot.js +32 -11
  120. package/lib/chain/prepareNextSlot.js.map +1 -1
  121. package/lib/chain/produceBlock/computeNewStateRoot.d.ts +1 -7
  122. package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
  123. package/lib/chain/produceBlock/computeNewStateRoot.js +1 -28
  124. package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
  125. package/lib/chain/produceBlock/produceBlockBody.d.ts +5 -10
  126. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  127. package/lib/chain/produceBlock/produceBlockBody.js +49 -19
  128. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  129. package/lib/chain/regen/errors.d.ts +1 -11
  130. package/lib/chain/regen/errors.d.ts.map +1 -1
  131. package/lib/chain/regen/errors.js +0 -2
  132. package/lib/chain/regen/errors.js.map +1 -1
  133. package/lib/chain/regen/interface.d.ts +6 -12
  134. package/lib/chain/regen/interface.d.ts.map +1 -1
  135. package/lib/chain/regen/queued.d.ts +6 -11
  136. package/lib/chain/regen/queued.d.ts.map +1 -1
  137. package/lib/chain/regen/queued.js +8 -40
  138. package/lib/chain/regen/queued.js.map +1 -1
  139. package/lib/chain/regen/regen.d.ts +0 -5
  140. package/lib/chain/regen/regen.d.ts.map +1 -1
  141. package/lib/chain/regen/regen.js +7 -34
  142. package/lib/chain/regen/regen.js.map +1 -1
  143. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +11 -4
  144. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
  145. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +20 -18
  146. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
  147. package/lib/chain/stateCache/datastore/db.d.ts +5 -4
  148. package/lib/chain/stateCache/datastore/db.d.ts.map +1 -1
  149. package/lib/chain/stateCache/datastore/db.js +10 -32
  150. package/lib/chain/stateCache/datastore/db.js.map +1 -1
  151. package/lib/chain/stateCache/datastore/file.d.ts +1 -1
  152. package/lib/chain/stateCache/datastore/file.d.ts.map +1 -1
  153. package/lib/chain/stateCache/datastore/file.js +5 -5
  154. package/lib/chain/stateCache/datastore/file.js.map +1 -1
  155. package/lib/chain/stateCache/datastore/types.d.ts +1 -1
  156. package/lib/chain/stateCache/datastore/types.d.ts.map +1 -1
  157. package/lib/chain/stateCache/fifoBlockStateCache.d.ts +1 -7
  158. package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
  159. package/lib/chain/stateCache/fifoBlockStateCache.js +0 -8
  160. package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
  161. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +13 -30
  162. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  163. package/lib/chain/stateCache/persistentCheckpointsCache.js +120 -216
  164. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  165. package/lib/chain/stateCache/types.d.ts +8 -15
  166. package/lib/chain/stateCache/types.d.ts.map +1 -1
  167. package/lib/chain/stateCache/types.js.map +1 -1
  168. package/lib/chain/validation/aggregateAndProof.js +12 -0
  169. package/lib/chain/validation/aggregateAndProof.js.map +1 -1
  170. package/lib/chain/validation/attestation.d.ts.map +1 -1
  171. package/lib/chain/validation/attestation.js +12 -0
  172. package/lib/chain/validation/attestation.js.map +1 -1
  173. package/lib/chain/validation/block.d.ts.map +1 -1
  174. package/lib/chain/validation/block.js +27 -5
  175. package/lib/chain/validation/block.js.map +1 -1
  176. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  177. package/lib/chain/validation/executionPayloadBid.js +19 -4
  178. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  179. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  180. package/lib/chain/validation/executionPayloadEnvelope.js +27 -12
  181. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  182. package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
  183. package/lib/chain/validation/payloadAttestationMessage.js +8 -4
  184. package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
  185. package/lib/chain/validation/syncCommittee.d.ts.map +1 -1
  186. package/lib/chain/validation/syncCommittee.js +4 -0
  187. package/lib/chain/validation/syncCommittee.js.map +1 -1
  188. package/lib/chain/validation/syncCommitteeContributionAndProof.js +4 -1
  189. package/lib/chain/validation/syncCommitteeContributionAndProof.js.map +1 -1
  190. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  191. package/lib/chain/validatorMonitor.js +3 -3
  192. package/lib/chain/validatorMonitor.js.map +1 -1
  193. package/lib/db/repositories/executionPayloadEnvelopeArchive.js +1 -1
  194. package/lib/db/repositories/executionPayloadEnvelopeArchive.js.map +1 -1
  195. package/lib/execution/engine/http.d.ts.map +1 -1
  196. package/lib/execution/engine/http.js +21 -14
  197. package/lib/execution/engine/http.js.map +1 -1
  198. package/lib/execution/engine/interface.d.ts +1 -0
  199. package/lib/execution/engine/interface.d.ts.map +1 -1
  200. package/lib/execution/engine/mock.d.ts.map +1 -1
  201. package/lib/execution/engine/mock.js +6 -0
  202. package/lib/execution/engine/mock.js.map +1 -1
  203. package/lib/execution/engine/types.d.ts +20 -0
  204. package/lib/execution/engine/types.d.ts.map +1 -1
  205. package/lib/execution/engine/types.js +18 -0
  206. package/lib/execution/engine/types.js.map +1 -1
  207. package/lib/network/gossip/topic.d.ts +3 -2
  208. package/lib/network/gossip/topic.d.ts.map +1 -1
  209. package/lib/network/network.js +1 -1
  210. package/lib/network/network.js.map +1 -1
  211. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  212. package/lib/network/processor/gossipHandlers.js +26 -6
  213. package/lib/network/processor/gossipHandlers.js.map +1 -1
  214. package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
  215. package/lib/network/reqresp/handlers/beaconBlocksByRange.js +2 -1
  216. package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
  217. package/lib/network/reqresp/handlers/beaconBlocksByRoot.d.ts.map +1 -1
  218. package/lib/network/reqresp/handlers/beaconBlocksByRoot.js +2 -0
  219. package/lib/network/reqresp/handlers/beaconBlocksByRoot.js.map +1 -1
  220. package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts +2 -2
  221. package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts.map +1 -1
  222. package/lib/network/reqresp/handlers/blobSidecarsByRange.js +7 -3
  223. package/lib/network/reqresp/handlers/blobSidecarsByRange.js.map +1 -1
  224. package/lib/network/reqresp/handlers/blobSidecarsByRoot.d.ts.map +1 -1
  225. package/lib/network/reqresp/handlers/blobSidecarsByRoot.js +6 -0
  226. package/lib/network/reqresp/handlers/blobSidecarsByRoot.js.map +1 -1
  227. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts +2 -2
  228. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
  229. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +7 -3
  230. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
  231. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -1
  232. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +2 -1
  233. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
  234. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.d.ts.map +1 -1
  235. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js +3 -8
  236. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js.map +1 -1
  237. package/lib/node/nodejs.d.ts.map +1 -1
  238. package/lib/node/nodejs.js +6 -1
  239. package/lib/node/nodejs.js.map +1 -1
  240. package/lib/node/notifier.d.ts.map +1 -1
  241. package/lib/node/notifier.js +2 -2
  242. package/lib/node/notifier.js.map +1 -1
  243. package/lib/util/sszBytes.d.ts.map +1 -1
  244. package/lib/util/sszBytes.js +16 -3
  245. package/lib/util/sszBytes.js.map +1 -1
  246. package/package.json +16 -16
  247. package/src/api/impl/beacon/blocks/index.ts +30 -4
  248. package/src/api/impl/beacon/pool/index.ts +4 -0
  249. package/src/api/impl/beacon/state/index.ts +15 -15
  250. package/src/api/impl/beacon/state/utils.ts +2 -2
  251. package/src/api/impl/lodestar/attesterSlashing.ts +43 -0
  252. package/src/api/impl/lodestar/index.ts +51 -1
  253. package/src/api/impl/validator/index.ts +10 -6
  254. package/src/chain/GetBlobsTracker.ts +1 -2
  255. package/src/chain/archiveStore/archiveStore.ts +5 -5
  256. package/src/chain/archiveStore/interface.ts +4 -4
  257. package/src/chain/archiveStore/strategies/frequencyStateArchiveStrategy.ts +6 -8
  258. package/src/chain/archiveStore/utils/archiveBlocks.ts +153 -94
  259. package/src/chain/blocks/importBlock.ts +33 -42
  260. package/src/chain/blocks/importExecutionPayload.ts +83 -99
  261. package/src/chain/blocks/index.ts +1 -2
  262. package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +27 -0
  263. package/src/chain/blocks/payloadEnvelopeProcessor.ts +6 -5
  264. package/src/chain/blocks/types.ts +15 -26
  265. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +2 -1
  266. package/src/chain/blocks/verifyBlocksSignatures.ts +9 -2
  267. package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +129 -0
  268. package/src/chain/blocks/verifyPayloadsDataAvailability.ts +38 -0
  269. package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +9 -18
  270. package/src/chain/chain.ts +47 -62
  271. package/src/chain/emitter.ts +15 -3
  272. package/src/chain/errors/attestationError.ts +6 -1
  273. package/src/chain/errors/blockError.ts +7 -1
  274. package/src/chain/errors/executionPayloadBid.ts +6 -0
  275. package/src/chain/errors/executionPayloadEnvelope.ts +6 -0
  276. package/src/chain/forkChoice/index.ts +19 -28
  277. package/src/chain/interface.ts +7 -2
  278. package/src/chain/lightClient/index.ts +15 -3
  279. package/src/chain/opPools/aggregatedAttestationPool.ts +6 -1
  280. package/src/chain/opPools/executionPayloadBidPool.ts +3 -3
  281. package/src/chain/prepareNextSlot.ts +38 -11
  282. package/src/chain/produceBlock/computeNewStateRoot.ts +1 -37
  283. package/src/chain/produceBlock/produceBlockBody.ts +74 -23
  284. package/src/chain/regen/errors.ts +1 -6
  285. package/src/chain/regen/interface.ts +6 -12
  286. package/src/chain/regen/queued.ts +12 -48
  287. package/src/chain/regen/regen.ts +8 -36
  288. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +22 -20
  289. package/src/chain/stateCache/datastore/db.ts +10 -33
  290. package/src/chain/stateCache/datastore/file.ts +5 -6
  291. package/src/chain/stateCache/datastore/types.ts +2 -3
  292. package/src/chain/stateCache/fifoBlockStateCache.ts +1 -10
  293. package/src/chain/stateCache/persistentCheckpointsCache.ts +139 -247
  294. package/src/chain/stateCache/types.ts +8 -14
  295. package/src/chain/validation/aggregateAndProof.ts +13 -0
  296. package/src/chain/validation/attestation.ts +13 -0
  297. package/src/chain/validation/block.ts +30 -7
  298. package/src/chain/validation/executionPayloadBid.ts +21 -3
  299. package/src/chain/validation/executionPayloadEnvelope.ts +32 -13
  300. package/src/chain/validation/payloadAttestationMessage.ts +9 -3
  301. package/src/chain/validation/syncCommittee.ts +5 -1
  302. package/src/chain/validation/syncCommitteeContributionAndProof.ts +5 -1
  303. package/src/chain/validatorMonitor.ts +3 -2
  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/network/network.ts +1 -1
  310. package/src/network/processor/gossipHandlers.ts +31 -10
  311. package/src/network/reqresp/handlers/beaconBlocksByRange.ts +3 -1
  312. package/src/network/reqresp/handlers/beaconBlocksByRoot.ts +3 -0
  313. package/src/network/reqresp/handlers/blobSidecarsByRange.ts +15 -3
  314. package/src/network/reqresp/handlers/blobSidecarsByRoot.ts +11 -0
  315. package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +19 -3
  316. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +3 -1
  317. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRoot.ts +3 -12
  318. package/src/node/nodejs.ts +7 -2
  319. package/src/node/notifier.ts +7 -2
  320. package/src/util/sszBytes.ts +21 -3
@@ -8,7 +8,6 @@ import {
8
8
  ForkChoiceErrorCode,
9
9
  NotReorgedReason,
10
10
  getSafeExecutionBlockHash,
11
- isGloasBlock,
12
11
  } from "@lodestar/fork-choice";
13
12
  import {
14
13
  ForkPostAltair,
@@ -25,6 +24,8 @@ import {
25
24
  computeStartSlotAtEpoch,
26
25
  computeTimeAtSlot,
27
26
  isStartSlotOfEpoch,
27
+ isStatePostAltair,
28
+ isStatePostBellatrix,
28
29
  } from "@lodestar/state-transition";
29
30
  import {
30
31
  Attestation,
@@ -46,7 +47,7 @@ import type {BeaconChain} from "../chain.js";
46
47
  import {ChainEvent, ReorgEventData} from "../emitter.js";
47
48
  import {ForkchoiceCaller} from "../forkChoice/index.js";
48
49
  import {REPROCESS_MIN_TIME_TO_NEXT_SLOT_SEC} from "../reprocess.js";
49
- import {toCheckpointHexPayload} from "../stateCache/persistentCheckpointsCache.js";
50
+ import {toCheckpointHex} from "../stateCache/persistentCheckpointsCache.js";
50
51
  import {isBlockInputBlobs, isBlockInputColumns} from "./blockInput/blockInput.js";
51
52
  import {AttestationImportOpt, FullyVerifiedBlock, ImportBlockOpts} from "./types.js";
52
53
  import {getCheckpointFromState} from "./utils/checkpoint.js";
@@ -85,7 +86,7 @@ export async function importBlock(
85
86
  fullyVerifiedBlock: FullyVerifiedBlock,
86
87
  opts: ImportBlockOpts
87
88
  ): Promise<void> {
88
- const {blockInput, postBlockState, parentBlockSlot, executionStatus, dataAvailabilityStatus, indexedAttestations} =
89
+ const {blockInput, postState, parentBlockSlot, executionStatus, dataAvailabilityStatus, indexedAttestations} =
89
90
  fullyVerifiedBlock;
90
91
  const block = blockInput.getBlock();
91
92
  const source = blockInput.getBlockSource();
@@ -97,7 +98,7 @@ export async function importBlock(
97
98
  const blockEpoch = computeEpochAtSlot(blockSlot);
98
99
  const prevFinalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch;
99
100
  const blockDelaySec =
100
- fullyVerifiedBlock.seenTimestampSec - computeTimeAtSlot(this.config, blockSlot, postBlockState.genesisTime);
101
+ fullyVerifiedBlock.seenTimestampSec - computeTimeAtSlot(this.config, blockSlot, postState.genesisTime);
101
102
  const recvToValLatency = Date.now() / 1000 - (opts.seenTimestampSec ?? Date.now() / 1000);
102
103
  const fork = this.config.getForkSeq(blockSlot);
103
104
 
@@ -120,10 +121,10 @@ export async function importBlock(
120
121
  // 2. Import block to fork choice
121
122
 
122
123
  // Should compute checkpoint balances before forkchoice.onBlock
123
- this.checkpointBalancesCache.processState(blockRootHex, postBlockState);
124
+ this.checkpointBalancesCache.processState(blockRootHex, postState);
124
125
  const blockSummary = this.forkChoice.onBlock(
125
126
  block.message,
126
- postBlockState,
127
+ postState,
127
128
  blockDelaySec,
128
129
  currentSlot,
129
130
  fork >= ForkSeq.gloas ? ExecutionStatus.PayloadSeparated : executionStatus,
@@ -132,11 +133,7 @@ export async function importBlock(
132
133
 
133
134
  // This adds the state necessary to process the next block
134
135
  // Some block event handlers require state being in state cache so need to do this before emitting EventType.block
135
- // Pre-Gloas: blockSummary.payloadStatus is always FULL, payloadPresent = true
136
- // Post-Gloas: blockSummary.payloadStatus is always PENDING, so payloadPresent = false (block state only, no payload processing yet)
137
- const payloadPresent = !isGloasBlock(blockSummary);
138
- // processState manages both block state and payload state variants together for memory/disk management
139
- this.regen.processBlockState(blockRootHex, postBlockState);
136
+ this.regen.processState(blockRootHex, postState);
140
137
 
141
138
  // For Gloas blocks, create PayloadEnvelopeInput so it's available for later payload import
142
139
  if (fork >= ForkSeq.gloas) {
@@ -159,17 +156,9 @@ export async function importBlock(
159
156
  // which is all the information we need so there is no reason to delay until execution payload arrives
160
157
  // TODO GLOAS: If we want EL retries after this initial attempt, add an explicit retry policy here
161
158
  // (for example later in the slot). Do not couple retries to incoming gossip columns.
162
- this.getBlobsTracker.triggerGetBlobs(payloadInput, () => {
163
- // TODO GLOAS: come up with a better mechanism to trigger processExecutionPayload after data becomes available,
164
- // similar to how pre-gloas uses waitForBlockAndAllData with a cutoff timeout and incompleteBlockInput event
165
- this.processExecutionPayload(payloadInput, {validSignature: true}).catch((e) => {
166
- this.logger.debug(
167
- "Error processing execution payload after getBlobs",
168
- {slot: blockSlot, root: blockRootHex},
169
- e as Error
170
- );
171
- });
172
- });
159
+ // Columns fetched here feed payloadInput.addColumn, which resolves waitForAllData for any
160
+ // in-flight importExecutionPayload. No processExecutionPayload trigger needed from this path.
161
+ this.getBlobsTracker.triggerGetBlobs(payloadInput);
173
162
  }
174
163
 
175
164
  this.metrics?.importBlock.bySource.inc({source: source.source});
@@ -189,7 +178,7 @@ export async function importBlock(
189
178
  (opts.importAttestations !== AttestationImportOpt.Skip && blockEpoch >= currentEpoch - FORK_CHOICE_ATT_EPOCH_LIMIT)
190
179
  ) {
191
180
  const attestations = block.message.body.attestations;
192
- const rootCache = new RootCache(postBlockState);
181
+ const rootCache = new RootCache(postState);
193
182
  const invalidAttestationErrorsByCode = new Map<string, {error: Error; count: number}>();
194
183
 
195
184
  const addAttestation = fork >= ForkSeq.electra ? addAttestationPostElectra : addAttestationPreElectra;
@@ -203,7 +192,7 @@ export async function importBlock(
203
192
  const attDataRoot = toRootHex(ssz.phase0.AttestationData.hashTreeRoot(indexedAttestation.data));
204
193
  addAttestation.call(
205
194
  this,
206
- postBlockState,
195
+ postState,
207
196
  target,
208
197
  attDataRoot,
209
198
  attestation as Attestation<ForkPostElectra>,
@@ -318,7 +307,7 @@ export async function importBlock(
318
307
 
319
308
  if (newHead.blockRoot !== oldHead.blockRoot) {
320
309
  // Set head state as strong reference
321
- this.regen.updateHeadState(newHead, postBlockState);
310
+ this.regen.updateHeadState(newHead, postState);
322
311
 
323
312
  try {
324
313
  this.emitter.emit(routes.events.EventType.head, {
@@ -388,11 +377,13 @@ export async function importBlock(
388
377
  // we want to import block asap so do this in the next event loop
389
378
  callInNextEventLoop(() => {
390
379
  try {
391
- this.lightClientServer?.onImportBlockHead(
392
- block.message as BeaconBlock<ForkPostAltair>,
393
- postBlockState,
394
- parentBlockSlot
395
- );
380
+ if (isStatePostAltair(postState)) {
381
+ this.lightClientServer?.onImportBlockHead(
382
+ block.message as BeaconBlock<ForkPostAltair>,
383
+ postState,
384
+ parentBlockSlot
385
+ );
386
+ }
396
387
  } catch (e) {
397
388
  this.logger.verbose("Error lightClientServer.onImportBlock", {slot: blockSlot}, e as Error);
398
389
  }
@@ -411,11 +402,11 @@ export async function importBlock(
411
402
  // and the block is weak and can potentially be reorged out.
412
403
  let shouldOverrideFcu = false;
413
404
 
414
- if (blockSlot >= currentSlot && postBlockState.isExecutionStateType) {
405
+ if (blockSlot >= currentSlot && isStatePostBellatrix(postState) && postState.isExecutionStateType) {
415
406
  let notOverrideFcuReason = NotReorgedReason.Unknown;
416
407
  const proposalSlot = blockSlot + 1;
417
408
  try {
418
- const proposerIndex = postBlockState.getBeaconProposer(proposalSlot);
409
+ const proposerIndex = postState.getBeaconProposer(proposalSlot);
419
410
  const feeRecipient = this.beaconProposerCache.get(proposerIndex);
420
411
 
421
412
  if (feeRecipient) {
@@ -495,27 +486,27 @@ export async function importBlock(
495
486
  }
496
487
  }
497
488
 
498
- if (!postBlockState.isStateValidatorsNodesPopulated()) {
499
- this.logger.verbose("After importBlock caching postState without SSZ cache", {slot: postBlockState.slot});
489
+ if (!postState.isStateValidatorsNodesPopulated()) {
490
+ this.logger.verbose("After importBlock caching postState without SSZ cache", {slot: postState.slot});
500
491
  }
501
492
 
502
493
  // Cache shufflings when crossing an epoch boundary
503
494
  const parentEpoch = computeEpochAtSlot(parentBlockSlot);
504
495
  if (parentEpoch < blockEpoch) {
505
- this.shufflingCache.processState(postBlockState);
496
+ this.shufflingCache.processState(postState);
506
497
  this.logger.verbose("Processed shuffling for next epoch", {parentEpoch, blockEpoch, slot: blockSlot});
507
498
  }
508
499
 
509
500
  if (blockSlot % SLOTS_PER_EPOCH === 0) {
510
501
  // Cache state to preserve epoch transition work
511
- const checkpointState = postBlockState;
502
+ const checkpointState = postState;
512
503
  const cp = getCheckpointFromState(checkpointState);
513
- this.regen.addCheckpointState(cp, checkpointState, payloadPresent);
504
+ this.regen.addCheckpointState(cp, checkpointState);
514
505
  // consumers should not mutate state ever
515
506
  this.emitter.emit(ChainEvent.checkpoint, cp, checkpointState);
516
507
 
517
508
  // Note: in-lined code from previos handler of ChainEvent.checkpoint
518
- this.logger.verbose("Checkpoint processed", toCheckpointHexPayload(cp, payloadPresent));
509
+ this.logger.verbose("Checkpoint processed", toCheckpointHex(cp));
519
510
 
520
511
  const activeValidatorsCount = checkpointState.activeValidatorCount;
521
512
  this.metrics?.currentActiveValidators.set(activeValidatorsCount);
@@ -533,7 +524,7 @@ export async function importBlock(
533
524
  const justifiedEpoch = justifiedCheckpoint.epoch;
534
525
  const preJustifiedEpoch = parentBlockSummary.justifiedEpoch;
535
526
  if (justifiedEpoch > preJustifiedEpoch) {
536
- this.logger.verbose("Checkpoint justified", toCheckpointHexPayload(justifiedCheckpoint, payloadPresent));
527
+ this.logger.verbose("Checkpoint justified", toCheckpointHex(justifiedCheckpoint));
537
528
  this.metrics?.previousJustifiedEpoch.set(checkpointState.previousJustifiedCheckpoint.epoch);
538
529
  this.metrics?.currentJustifiedEpoch.set(justifiedCheckpoint.epoch);
539
530
  }
@@ -547,7 +538,7 @@ export async function importBlock(
547
538
  state: toRootHex(checkpointState.hashTreeRoot()),
548
539
  executionOptimistic: false,
549
540
  });
550
- this.logger.verbose("Checkpoint finalized", toCheckpointHexPayload(finalizedCheckpoint, payloadPresent));
541
+ this.logger.verbose("Checkpoint finalized", toCheckpointHex(finalizedCheckpoint));
551
542
  this.metrics?.finalizedEpoch.set(finalizedCheckpoint.epoch);
552
543
  }
553
544
  }
@@ -598,11 +589,11 @@ export async function importBlock(
598
589
  this.metrics?.parentBlockDistance.observe(blockSlot - parentBlockSlot);
599
590
  this.metrics?.proposerBalanceDeltaAny.observe(fullyVerifiedBlock.proposerBalanceDelta);
600
591
  this.validatorMonitor?.registerImportedBlock(block.message, fullyVerifiedBlock);
601
- if (this.config.getForkSeq(blockSlot) >= ForkSeq.altair) {
592
+ if (isStatePostAltair(fullyVerifiedBlock.postState)) {
602
593
  this.validatorMonitor?.registerSyncAggregateInBlock(
603
594
  blockEpoch,
604
595
  (block as altair.SignedBeaconBlock).message.body.syncAggregate,
605
- fullyVerifiedBlock.postBlockState.currentSyncCommitteeIndexed.validatorIndices
596
+ fullyVerifiedBlock.postState.currentSyncCommitteeIndexed.validatorIndices
606
597
  );
607
598
  }
608
599
 
@@ -1,14 +1,18 @@
1
1
  import {routes} from "@lodestar/api";
2
2
  import {ExecutionStatus, PayloadExecutionStatus} from "@lodestar/fork-choice";
3
- import {SLOTS_PER_EPOCH} from "@lodestar/params";
4
- import {getExecutionPayloadEnvelopeSignatureSet} from "@lodestar/state-transition";
5
- import {byteArrayEquals, fromHex, toRootHex} from "@lodestar/utils";
3
+ import {isStatePostGloas} from "@lodestar/state-transition";
4
+ import {fromHex} from "@lodestar/utils";
6
5
  import {ExecutionPayloadStatus} from "../../execution/index.js";
7
6
  import {isQueueErrorAborted} from "../../util/queue/index.js";
8
7
  import {BeaconChain} from "../chain.js";
9
8
  import {RegenCaller} from "../regen/interface.js";
10
9
  import {PayloadEnvelopeInput} from "../seenCache/seenPayloadEnvelopeInput.js";
11
10
  import {ImportPayloadOpts} from "./types.js";
11
+ import {
12
+ verifyExecutionPayloadEnvelope,
13
+ verifyExecutionPayloadEnvelopeSignature,
14
+ } from "./verifyExecutionPayloadEnvelope.js";
15
+ import {verifyPayloadsDataAvailability} from "./verifyPayloadsDataAvailability.js";
12
16
 
13
17
  const EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS = 64;
14
18
 
@@ -16,7 +20,7 @@ export enum PayloadErrorCode {
16
20
  EXECUTION_ENGINE_INVALID = "PAYLOAD_ERROR_EXECUTION_ENGINE_INVALID",
17
21
  EXECUTION_ENGINE_ERROR = "PAYLOAD_ERROR_EXECUTION_ENGINE_ERROR",
18
22
  BLOCK_NOT_IN_FORK_CHOICE = "PAYLOAD_ERROR_BLOCK_NOT_IN_FORK_CHOICE",
19
- STATE_TRANSITION_ERROR = "PAYLOAD_ERROR_STATE_TRANSITION_ERROR",
23
+ ENVELOPE_VERIFICATION_ERROR = "PAYLOAD_ERROR_ENVELOPE_VERIFICATION_ERROR",
20
24
  INVALID_SIGNATURE = "PAYLOAD_ERROR_INVALID_SIGNATURE",
21
25
  }
22
26
 
@@ -36,7 +40,7 @@ export type PayloadErrorType =
36
40
  blockRootHex: string;
37
41
  }
38
42
  | {
39
- code: PayloadErrorCode.STATE_TRANSITION_ERROR;
43
+ code: PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR;
40
44
  message: string;
41
45
  }
42
46
  | {
@@ -68,37 +72,40 @@ function toForkChoiceExecutionStatus(status: ExecutionPayloadStatus): PayloadExe
68
72
  /**
69
73
  * Import an execution payload envelope after all data is available.
70
74
  *
71
- * This function:
72
- * 1. Emits `execution_payload_available` if payload is for current slot
73
- * 2. Gets the ProtoBlock from fork choice
74
- * 3. Applies write-queue backpressure (waitForSpace) early, before verification
75
- * 4. Regenerates the block state
76
- * 5. Runs EL verification (notifyNewPayload) in parallel with signature verification and processExecutionPayloadEnvelope
77
- * 6. Persists verified payload envelope to hot DB
78
- * 7. Updates fork choice
79
- * 8. Caches the post-execution payload state
80
- * 9. Records metrics for column sources
81
- * 10. Emits `execution_payload` for recent enough payloads after successful import
75
+ * The envelope is only verified here, no state mutation. State effects from the payload
76
+ * are applied on the next block via processParentExecutionPayload.
82
77
  *
78
+ * Steps:
79
+ * 1. Emit `execution_payload_available` event for payload attestation
80
+ * 2. Get the ProtoBlock from fork choice
81
+ * 3. Wait for data columns to be available
82
+ * 4. Regenerate state for envelope verification
83
+ * 5. Verify envelope (fields against state, signature, and EL in parallel where possible)
84
+ * 6. Persist verified payload envelope to hot DB (waits for write-queue space for backpressure)
85
+ * 7. Update fork choice (transitions the block's PENDING variant to FULL)
86
+ * 8. Record metrics for payload envelope and column sources
87
+ * 9. Emit `execution_payload` event
83
88
  */
84
89
  export async function importExecutionPayload(
85
90
  this: BeaconChain,
86
91
  payloadInput: PayloadEnvelopeInput,
92
+ signal: AbortSignal,
87
93
  opts: ImportPayloadOpts = {}
88
94
  ): Promise<void> {
89
95
  const signedEnvelope = payloadInput.getPayloadEnvelope();
90
96
  const envelope = signedEnvelope.message;
97
+ const slot = envelope.payload.slotNumber;
91
98
  const blockRootHex = payloadInput.blockRootHex;
92
99
  const blockHashHex = payloadInput.getBlockHashHex();
93
- const fork = this.config.getForkName(envelope.slot);
100
+ const fork = this.config.getForkName(slot);
94
101
 
95
- // 1. Emit `execution_payload_available` event at the start of import. At this point the payload input
96
- // is already complete, so the payload and required data are available for payload attestation.
97
- // This event is only about availability, not validity of the execution payload, hence we can emit
98
- // it before getting a response from the execution client on whether the payload is valid or not.
99
- if (this.clock.currentSlot === envelope.slot) {
102
+ // 1. Emit `execution_payload_available` event at the start of import. At this point the
103
+ // payload input is already complete, so the payload and required data are available for
104
+ // payload attestation. This event only signals availability (not validity), so we can emit
105
+ // it before getting a response from the EL on whether the payload is valid or not.
106
+ if (this.clock.currentSlot - slot < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
100
107
  this.emitter.emit(routes.events.EventType.executionPayloadAvailable, {
101
- slot: envelope.slot,
108
+ slot,
102
109
  blockRoot: blockRootHex,
103
110
  });
104
111
  }
@@ -112,23 +119,43 @@ export async function importExecutionPayload(
112
119
  });
113
120
  }
114
121
 
115
- // 3. Apply backpressure from the write queue early, before doing verification work.
116
- // The actual DB write is deferred until after verification succeeds.
117
- await this.unfinalizedPayloadEnvelopeWrites.waitForSpace();
122
+ // 3. Wait for data columns to be available.
123
+ // The helper is shared with future gloas sync services; take the single-item batch form here.
124
+ await verifyPayloadsDataAvailability([payloadInput], signal);
118
125
 
119
- // 4. Get pre-state for processExecutionPayloadEnvelope
120
- // We need the block state (post-block, pre-payload) to process the envelope
126
+ // 4. Regenerate state for envelope verification
121
127
  const blockState = await this.regen.getBlockSlotState(
122
128
  protoBlock,
123
129
  protoBlock.slot,
124
130
  {dontTransferCache: true},
125
131
  RegenCaller.processBlock
126
132
  );
133
+ if (!isStatePostGloas(blockState)) {
134
+ throw new PayloadError({
135
+ code: PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR,
136
+ message: `Expected gloas+ state for payload import, got fork=${blockState.forkName}`,
137
+ });
138
+ }
127
139
 
128
- // 5. Run verification steps in parallel
129
- // Note: No data availability check needed here - importExecutionPayload is only
130
- // called when payloadInput.isComplete() is true, so all data is already available.
131
- const [execResult, signatureValid, postPayloadResult] = await Promise.all([
140
+ // 5. Verify envelope fields against state first to fail fast before the EL + BLS work.
141
+ // When validSignature is true, gossip/API has already verified both the signature and the
142
+ // executionRequestsRoot, so we skip those checks here.
143
+ try {
144
+ verifyExecutionPayloadEnvelope(this.config, blockState, envelope, {
145
+ verifyExecutionRequestsRoot: !opts.validSignature,
146
+ });
147
+ } catch (e) {
148
+ throw new PayloadError(
149
+ {
150
+ code: PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR,
151
+ message: (e as Error).message,
152
+ },
153
+ `Envelope verification error: ${(e as Error).message}`
154
+ );
155
+ }
156
+
157
+ // 5a. Run EL and signature verification in parallel
158
+ const [execResult, signatureValid] = await Promise.all([
132
159
  this.executionEngine.notifyNewPayload(
133
160
  fork,
134
161
  envelope.payload,
@@ -139,45 +166,22 @@ export async function importExecutionPayload(
139
166
 
140
167
  opts.validSignature === true
141
168
  ? Promise.resolve(true)
142
- : (async () => {
143
- const signatureSet = getExecutionPayloadEnvelopeSignatureSet(
144
- this.config,
145
- this.pubkeyCache,
146
- blockState,
147
- signedEnvelope,
148
- payloadInput.proposerIndex
149
- );
150
- return this.bls.verifySignatureSets([signatureSet]);
151
- })(),
152
-
153
- // Signature verified separately above.
154
- // State root check is done separately below with better error typing (matching block pipeline pattern).
155
- (async () => {
156
- try {
157
- return {
158
- postPayloadState: blockState.processExecutionPayloadEnvelope(signedEnvelope, {
159
- verifySignature: false,
160
- verifyStateRoot: false,
161
- }),
162
- };
163
- } catch (e) {
164
- throw new PayloadError(
165
- {
166
- code: PayloadErrorCode.STATE_TRANSITION_ERROR,
167
- message: (e as Error).message,
168
- },
169
- `State transition error: ${(e as Error).message}`
170
- );
171
- }
172
- })(),
169
+ : verifyExecutionPayloadEnvelopeSignature(
170
+ this.config,
171
+ blockState,
172
+ this.pubkeyCache,
173
+ signedEnvelope,
174
+ payloadInput.proposerIndex,
175
+ this.bls
176
+ ),
173
177
  ]);
174
178
 
175
- // 5a. Check signature verification result
179
+ // 5b. Check signature verification result
176
180
  if (!signatureValid) {
177
181
  throw new PayloadError({code: PayloadErrorCode.INVALID_SIGNATURE});
178
182
  }
179
183
 
180
- // 5b. Handle EL response
184
+ // 5c. Handle EL response
181
185
  switch (execResult.status) {
182
186
  case ExecutionPayloadStatus.VALID:
183
187
  break;
@@ -203,65 +207,45 @@ export async function importExecutionPayload(
203
207
  });
204
208
  }
205
209
 
206
- // 5c. Verify envelope state root matches post-state
207
- const postPayloadState = postPayloadResult.postPayloadState;
208
- const postPayloadStateRoot = postPayloadState.hashTreeRoot();
209
- if (!byteArrayEquals(envelope.stateRoot, postPayloadStateRoot)) {
210
- throw new PayloadError({
211
- code: PayloadErrorCode.STATE_TRANSITION_ERROR,
212
- message: `Envelope state root mismatch expected=${toRootHex(envelope.stateRoot)} actual=${toRootHex(postPayloadStateRoot)}`,
213
- });
214
- }
215
-
216
- // 6. Persist payload envelope to hot DB (performed asynchronously to avoid blocking)
210
+ // 6. Persist payload envelope to hot DB. Wait for write-queue space here to apply backpressure
211
+ // on the import pipeline during sync, then perform the write asynchronously to avoid blocking.
212
+ await this.unfinalizedPayloadEnvelopeWrites.waitForSpace();
217
213
  this.unfinalizedPayloadEnvelopeWrites.push(payloadInput).catch((e) => {
218
214
  if (!isQueueErrorAborted(e)) {
219
215
  this.logger.error(
220
216
  "Error pushing payload envelope to unfinalized write queue",
221
- {slot: envelope.slot, root: blockRootHex},
217
+ {slot, blockRoot: blockRootHex},
222
218
  e as Error
223
219
  );
224
220
  }
225
221
  });
226
222
 
227
- // 7. Update fork choice
228
- this.forkChoice.onExecutionPayload(
229
- blockRootHex,
230
- blockHashHex,
231
- envelope.payload.blockNumber,
232
- toRootHex(postPayloadStateRoot),
233
- toForkChoiceExecutionStatus(execResult.status)
234
- );
235
-
236
- // 8. Cache payload state
237
- this.regen.processPayloadState(postPayloadState);
238
- if (postPayloadState.slot % SLOTS_PER_EPOCH === 0) {
239
- const {checkpoint} = postPayloadState.computeAnchorCheckpoint();
240
- this.regen.addCheckpointState(checkpoint, postPayloadState, true);
241
- }
223
+ // 7. Update fork choice, transitions the block's PENDING variant to FULL
224
+ const execStatus = toForkChoiceExecutionStatus(execResult.status);
225
+ this.forkChoice.onExecutionPayload(blockRootHex, blockHashHex, envelope.payload.blockNumber, execStatus);
242
226
 
243
- // 9. Record metrics for payload envelope and column sources
227
+ // 8. Record metrics for payload envelope and column sources
244
228
  this.metrics?.importPayload.bySource.inc({source: payloadInput.getPayloadEnvelopeSource().source});
245
229
  for (const {source} of payloadInput.getSampledColumnsWithSource()) {
246
230
  this.metrics?.importPayload.columnsBySource.inc({source});
247
231
  }
248
232
 
249
- // 10. Emit event after payload is fully verified and imported to fork choice, only for recent enough payloads
250
- if (this.clock.currentSlot - envelope.slot < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
233
+ // 9. Emit event after payload is fully verified and imported to fork choice, only for recent enough payloads
234
+ if (this.clock.currentSlot - slot < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
251
235
  this.emitter.emit(routes.events.EventType.executionPayload, {
252
- slot: envelope.slot,
236
+ slot,
253
237
  builderIndex: envelope.builderIndex,
254
238
  blockHash: blockHashHex,
255
239
  blockRoot: blockRootHex,
256
- stateRoot: toRootHex(envelope.stateRoot),
257
240
  // TODO GLOAS: revisit once we support optimistic import
258
241
  executionOptimistic: false,
259
242
  });
260
243
  }
261
244
 
262
245
  this.logger.verbose("Execution payload imported", {
263
- slot: envelope.slot,
264
- root: blockRootHex,
246
+ slot,
247
+ builderIndex: envelope.builderIndex,
248
+ blockRoot: blockRootHex,
265
249
  blockHash: blockHashHex,
266
250
  });
267
251
  }
@@ -88,8 +88,7 @@ export async function processBlocks(
88
88
  const fullyVerifiedBlocks = relevantBlocks.map(
89
89
  (block, i): FullyVerifiedBlock => ({
90
90
  blockInput: block,
91
- postBlockState: postStates[i],
92
- postEnvelopeState: null,
91
+ postState: postStates[i],
93
92
  parentBlockSlot: parentSlots[i],
94
93
  executionStatus: executionStatuses[i],
95
94
  // start supporting optimistic syncing/processing
@@ -73,6 +73,7 @@ export class PayloadEnvelopeInput {
73
73
  private timeCreatedSec: number;
74
74
 
75
75
  private readonly payloadEnvelopeDataPromise: PromiseParts<gloas.SignedExecutionPayloadEnvelope>;
76
+ private readonly allDataPromise: PromiseParts<gloas.DataColumnSidecar[]>;
76
77
  private readonly columnsDataPromise: PromiseParts<gloas.DataColumnSidecar[]>;
77
78
 
78
79
  state: PayloadEnvelopeInputState;
@@ -97,6 +98,7 @@ export class PayloadEnvelopeInput {
97
98
  this.custodyColumns = props.custodyColumns;
98
99
  this.timeCreatedSec = props.timeCreatedSec;
99
100
  this.payloadEnvelopeDataPromise = createPromise();
101
+ this.allDataPromise = createPromise();
100
102
  this.columnsDataPromise = createPromise();
101
103
 
102
104
  const noBlobs = props.bid.blobKzgCommitments.length === 0;
@@ -105,6 +107,7 @@ export class PayloadEnvelopeInput {
105
107
 
106
108
  if (hasAllData) {
107
109
  this.state = {hasPayload: false, hasAllData: true, hasComputedAllData: true};
110
+ this.allDataPromise.resolve(this.getSampledColumns());
108
111
  this.columnsDataPromise.resolve(this.getSampledColumns());
109
112
  } else {
110
113
  this.state = {hasPayload: false, hasAllData: false, hasComputedAllData: false};
@@ -203,6 +206,12 @@ export class PayloadEnvelopeInput {
203
206
  return true;
204
207
  }
205
208
 
209
+ // Resolve allDataPromise on the first transition to hasAllData (either sampled-complete or
210
+ // reconstruction-threshold branch). Guarded so it fires exactly once.
211
+ if (!this.state.hasAllData && hasAllData) {
212
+ this.allDataPromise.resolve(sampledColumns);
213
+ }
214
+
206
215
  if (hasComputedAllData) {
207
216
  this.columnsDataPromise.resolve(sampledColumns);
208
217
  }
@@ -315,6 +324,24 @@ export class PayloadEnvelopeInput {
315
324
  return this.state.hasComputedAllData;
316
325
  }
317
326
 
327
+ waitForAllData(timeout: number, signal?: AbortSignal): Promise<gloas.DataColumnSidecar[]> {
328
+ if (this.state.hasAllData) {
329
+ return Promise.resolve(this.getSampledColumns());
330
+ }
331
+ return withTimeout(() => this.allDataPromise.promise, timeout, signal);
332
+ }
333
+
334
+ async waitForEnvelopeAndAllData(timeout: number, signal?: AbortSignal): Promise<this> {
335
+ if (!this.state.hasPayload || !this.state.hasAllData) {
336
+ await withTimeout(
337
+ () => Promise.all([this.payloadEnvelopeDataPromise.promise, this.allDataPromise.promise]),
338
+ timeout,
339
+ signal
340
+ );
341
+ }
342
+ return this;
343
+ }
344
+
318
345
  waitForComputedAllData(timeout: number, signal?: AbortSignal): Promise<gloas.DataColumnSidecar[]> {
319
346
  if (this.state.hasComputedAllData) {
320
347
  return Promise.resolve(this.getSampledColumns());
@@ -16,6 +16,11 @@ enum PayloadEnvelopeImportStatus {
16
16
 
17
17
  /**
18
18
  * PayloadEnvelopeProcessor processes payload envelope jobs in a queued fashion, one after the other.
19
+ *
20
+ * Jobs are enqueued only on envelope arrival (gossip or API). The envelope may reach us before
21
+ * the sampled data columns; importExecutionPayload awaits `verifyPayloadsDataAvailability`
22
+ * internally, so a queued job can pend for up to `PAYLOAD_DATA_AVAILABILITY_TIMEOUT` while
23
+ * waiting for columns. Duplicate triggers for the same payloadInput are deduped via `importStatus`.
19
24
  */
20
25
  export class PayloadEnvelopeProcessor {
21
26
  readonly jobQueue: JobItemQueue<[PayloadEnvelopeInput, ImportPayloadOpts], void>;
@@ -25,7 +30,7 @@ export class PayloadEnvelopeProcessor {
25
30
  this.jobQueue = new JobItemQueue<[PayloadEnvelopeInput, ImportPayloadOpts], void>(
26
31
  (payloadInput, opts) => {
27
32
  this.importStatus.set(payloadInput, PayloadEnvelopeImportStatus.importing);
28
- return importExecutionPayload.call(chain, payloadInput, opts);
33
+ return importExecutionPayload.call(chain, payloadInput, signal, opts);
29
34
  },
30
35
  {maxLength: QUEUE_MAX_LENGTH, noYieldIfOneItem: true, signal},
31
36
  metrics?.payloadEnvelopeProcessorQueue ?? undefined
@@ -33,10 +38,6 @@ export class PayloadEnvelopeProcessor {
33
38
  }
34
39
 
35
40
  async processPayloadEnvelopeJob(payloadInput: PayloadEnvelopeInput, opts: ImportPayloadOpts = {}): Promise<void> {
36
- if (!payloadInput.isComplete()) {
37
- return;
38
- }
39
-
40
41
  if (this.importStatus.get(payloadInput) !== undefined) {
41
42
  return;
42
43
  }
@@ -1,5 +1,5 @@
1
1
  import type {ChainForkConfig} from "@lodestar/config";
2
- import {BlockExecutionStatus, PayloadExecutionStatus} from "@lodestar/fork-choice";
2
+ import {BlockExecutionStatus} from "@lodestar/fork-choice";
3
3
  import {ForkSeq} from "@lodestar/params";
4
4
  import {DataAvailabilityStatus, IBeaconStateView, computeEpochAtSlot} from "@lodestar/state-transition";
5
5
  import type {IndexedAttestation, Slot, fulu} from "@lodestar/types";
@@ -43,8 +43,9 @@ export enum BlobSidecarValidation {
43
43
 
44
44
  export type ImportPayloadOpts = {
45
45
  /**
46
- * Set to true if envelope signature was already verified (e.g., during gossip/API validation).
47
- * When false/undefined, signature will be verified during import.
46
+ * Set to true when the envelope was already validated upstream (e.g., gossip/API validation):
47
+ * signature is trusted and execution_requests_root was already verified against the bid.
48
+ * When false/undefined, both are verified during import.
48
49
  */
49
50
  validSignature?: boolean;
50
51
  };
@@ -88,9 +89,16 @@ export type ImportBlockOpts = {
88
89
  seenTimestampSec?: number;
89
90
  };
90
91
 
91
- type FullyVerifiedBlockBase = {
92
+ /**
93
+ * A wrapper around a `SignedBeaconBlock` that indicates that this block is fully verified and ready to import.
94
+ *
95
+ * `executionStatus` reflects the outcome of execution payload verification at block-import time:
96
+ * - pre-gloas: Valid | Syncing | PreMerge (from EL notifyNewPayload against the in-block payload)
97
+ * - post-gloas: PayloadSeparated (payload arrives separately as an envelope and is imported later)
98
+ */
99
+ export type FullyVerifiedBlock = {
92
100
  blockInput: IBlockInput;
93
- postBlockState: IBeaconStateView;
101
+ postState: IBeaconStateView;
94
102
  parentBlockSlot: Slot;
95
103
  proposerBalanceDelta: number;
96
104
  dataAvailabilityStatus: DataAvailabilityStatus;
@@ -98,25 +106,6 @@ type FullyVerifiedBlockBase = {
98
106
  indexedAttestations: IndexedAttestation[];
99
107
  /** Seen timestamp seconds */
100
108
  seenTimestampSec: number;
109
+ /** If the execution payload couldn't be verified because of EL syncing status, used in optimistic sync */
110
+ executionStatus: BlockExecutionStatus;
101
111
  };
102
-
103
- /**
104
- * A wrapper around a `SignedBeaconBlock` that indicates that this block is fully verified and ready to import.
105
- *
106
- * Discriminated union on `postEnvelopeState`:
107
- * - `null` → block has no pre-verified envelope; `executionStatus` is any `BlockExecutionStatus`
108
- * - non-null → envelope was pre-verified during state transition; `executionStatus` is narrowed to
109
- * `Valid | Syncing` (matching what `forkChoice.onExecutionPayload` expects)
110
- */
111
- export type FullyVerifiedBlock = FullyVerifiedBlockBase &
112
- (
113
- | {
114
- postEnvelopeState: null;
115
- /** If the execution payload couldn't be verified because of EL syncing status, used in optimistic sync or for merge block */
116
- executionStatus: BlockExecutionStatus;
117
- }
118
- | {
119
- postEnvelopeState: IBeaconStateView;
120
- executionStatus: PayloadExecutionStatus;
121
- }
122
- );