@lodestar/beacon-node 1.42.0-dev.5007abf468 → 1.42.0-dev.5295e30d5c

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 (291) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +24 -12
  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/debug/index.js.map +1 -1
  11. package/lib/api/impl/lodestar/index.d.ts.map +1 -1
  12. package/lib/api/impl/lodestar/index.js +4 -0
  13. package/lib/api/impl/lodestar/index.js.map +1 -1
  14. package/lib/api/impl/validator/index.d.ts.map +1 -1
  15. package/lib/api/impl/validator/index.js +7 -1
  16. package/lib/api/impl/validator/index.js.map +1 -1
  17. package/lib/chain/ColumnReconstructionTracker.d.ts +2 -1
  18. package/lib/chain/ColumnReconstructionTracker.d.ts.map +1 -1
  19. package/lib/chain/ColumnReconstructionTracker.js +5 -5
  20. package/lib/chain/ColumnReconstructionTracker.js.map +1 -1
  21. package/lib/chain/GetBlobsTracker.d.ts +2 -1
  22. package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
  23. package/lib/chain/GetBlobsTracker.js +14 -12
  24. package/lib/chain/GetBlobsTracker.js.map +1 -1
  25. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  26. package/lib/chain/archiveStore/archiveStore.js +1 -0
  27. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  28. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts +3 -3
  29. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
  30. package/lib/chain/archiveStore/historicalState/getHistoricalState.js +6 -4
  31. package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
  32. package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts +2 -2
  33. package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts.map +1 -1
  34. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -0
  35. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
  36. package/lib/chain/archiveStore/historicalState/types.d.ts +2 -0
  37. package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
  38. package/lib/chain/archiveStore/historicalState/types.js.map +1 -1
  39. package/lib/chain/archiveStore/historicalState/worker.js +1 -4
  40. package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
  41. package/lib/chain/archiveStore/interface.d.ts +1 -0
  42. package/lib/chain/archiveStore/interface.d.ts.map +1 -1
  43. package/lib/chain/blocks/blockInput/blockInput.d.ts +5 -5
  44. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  45. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  46. package/lib/chain/blocks/blockInput/types.d.ts +4 -4
  47. package/lib/chain/blocks/blockInput/types.d.ts.map +1 -1
  48. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  49. package/lib/chain/blocks/importBlock.js +34 -20
  50. package/lib/chain/blocks/importBlock.js.map +1 -1
  51. package/lib/chain/blocks/importExecutionPayload.d.ts +10 -8
  52. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  53. package/lib/chain/blocks/importExecutionPayload.js +86 -49
  54. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  55. package/lib/chain/blocks/index.d.ts.map +1 -1
  56. package/lib/chain/blocks/index.js +2 -1
  57. package/lib/chain/blocks/index.js.map +1 -1
  58. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +14 -6
  59. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
  60. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +33 -2
  61. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
  62. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +2 -1
  63. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
  64. package/lib/chain/blocks/types.d.ts +20 -14
  65. package/lib/chain/blocks/types.d.ts.map +1 -1
  66. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +2 -2
  67. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  68. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +4 -3
  69. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  70. package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
  71. package/lib/chain/blocks/verifyBlocksSignatures.js +4 -2
  72. package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
  73. package/lib/chain/chain.d.ts +3 -2
  74. package/lib/chain/chain.d.ts.map +1 -1
  75. package/lib/chain/chain.js +64 -24
  76. package/lib/chain/chain.js.map +1 -1
  77. package/lib/chain/emitter.d.ts +29 -7
  78. package/lib/chain/emitter.d.ts.map +1 -1
  79. package/lib/chain/emitter.js +12 -3
  80. package/lib/chain/emitter.js.map +1 -1
  81. package/lib/chain/errors/dataColumnSidecarError.d.ts +31 -1
  82. package/lib/chain/errors/dataColumnSidecarError.d.ts.map +1 -1
  83. package/lib/chain/errors/dataColumnSidecarError.js +7 -0
  84. package/lib/chain/errors/dataColumnSidecarError.js.map +1 -1
  85. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  86. package/lib/chain/forkChoice/index.js +10 -8
  87. package/lib/chain/forkChoice/index.js.map +1 -1
  88. package/lib/chain/interface.d.ts +4 -2
  89. package/lib/chain/interface.d.ts.map +1 -1
  90. package/lib/chain/lightClient/index.d.ts +2 -2
  91. package/lib/chain/lightClient/index.d.ts.map +1 -1
  92. package/lib/chain/lightClient/index.js +7 -0
  93. package/lib/chain/lightClient/index.js.map +1 -1
  94. package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
  95. package/lib/chain/opPools/aggregatedAttestationPool.js +5 -2
  96. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  97. package/lib/chain/opPools/executionPayloadBidPool.d.ts +2 -2
  98. package/lib/chain/opPools/executionPayloadBidPool.d.ts.map +1 -1
  99. package/lib/chain/opPools/executionPayloadBidPool.js +2 -2
  100. package/lib/chain/opPools/executionPayloadBidPool.js.map +1 -1
  101. package/lib/chain/options.d.ts +1 -0
  102. package/lib/chain/options.d.ts.map +1 -1
  103. package/lib/chain/options.js +1 -0
  104. package/lib/chain/options.js.map +1 -1
  105. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  106. package/lib/chain/prepareNextSlot.js +7 -1
  107. package/lib/chain/prepareNextSlot.js.map +1 -1
  108. package/lib/chain/produceBlock/computeNewStateRoot.d.ts +2 -2
  109. package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
  110. package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
  111. package/lib/chain/produceBlock/produceBlockBody.d.ts +3 -3
  112. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  113. package/lib/chain/produceBlock/produceBlockBody.js +10 -1
  114. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  115. package/lib/chain/seenCache/seenGossipBlockInput.d.ts +1 -1
  116. package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
  117. package/lib/chain/seenCache/seenGossipBlockInput.js +2 -2
  118. package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
  119. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +1 -1
  120. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
  121. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +2 -2
  122. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
  123. package/lib/chain/validation/block.d.ts.map +1 -1
  124. package/lib/chain/validation/block.js +2 -2
  125. package/lib/chain/validation/block.js.map +1 -1
  126. package/lib/chain/validation/dataColumnSidecar.d.ts +11 -4
  127. package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
  128. package/lib/chain/validation/dataColumnSidecar.js +184 -5
  129. package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
  130. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  131. package/lib/chain/validation/executionPayloadBid.js +7 -4
  132. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  133. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  134. package/lib/chain/validation/executionPayloadEnvelope.js +4 -1
  135. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  136. package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
  137. package/lib/chain/validation/payloadAttestationMessage.js +4 -1
  138. package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
  139. package/lib/chain/validation/syncCommittee.d.ts.map +1 -1
  140. package/lib/chain/validation/syncCommittee.js +4 -0
  141. package/lib/chain/validation/syncCommittee.js.map +1 -1
  142. package/lib/chain/validation/syncCommitteeContributionAndProof.js +4 -1
  143. package/lib/chain/validation/syncCommitteeContributionAndProof.js.map +1 -1
  144. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  145. package/lib/chain/validatorMonitor.js +3 -3
  146. package/lib/chain/validatorMonitor.js.map +1 -1
  147. package/lib/db/buckets.d.ts +2 -2
  148. package/lib/db/buckets.d.ts.map +1 -1
  149. package/lib/db/buckets.js +2 -2
  150. package/lib/db/buckets.js.map +1 -1
  151. package/lib/db/repositories/blockArchiveIndex.d.ts +2 -2
  152. package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
  153. package/lib/db/repositories/dataColumnSidecar.d.ts.map +1 -1
  154. package/lib/db/repositories/dataColumnSidecar.js +4 -2
  155. package/lib/db/repositories/dataColumnSidecar.js.map +1 -1
  156. package/lib/db/repositories/dataColumnSidecarArchive.d.ts.map +1 -1
  157. package/lib/db/repositories/dataColumnSidecarArchive.js +4 -2
  158. package/lib/db/repositories/dataColumnSidecarArchive.js.map +1 -1
  159. package/lib/metrics/metrics/lodestar.d.ts +20 -0
  160. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  161. package/lib/metrics/metrics/lodestar.js +33 -0
  162. package/lib/metrics/metrics/lodestar.js.map +1 -1
  163. package/lib/network/gossip/topic.d.ts +727 -0
  164. package/lib/network/gossip/topic.d.ts.map +1 -1
  165. package/lib/network/interface.d.ts +3 -2
  166. package/lib/network/interface.d.ts.map +1 -1
  167. package/lib/network/libp2p/index.d.ts.map +1 -1
  168. package/lib/network/libp2p/index.js +19 -13
  169. package/lib/network/libp2p/index.js.map +1 -1
  170. package/lib/network/network.d.ts +3 -2
  171. package/lib/network/network.d.ts.map +1 -1
  172. package/lib/network/network.js +3 -0
  173. package/lib/network/network.js.map +1 -1
  174. package/lib/network/options.d.ts.map +1 -1
  175. package/lib/network/options.js +7 -2
  176. package/lib/network/options.js.map +1 -1
  177. package/lib/network/processor/extractSlotRootFns.d.ts +1 -1
  178. package/lib/network/processor/extractSlotRootFns.d.ts.map +1 -1
  179. package/lib/network/processor/extractSlotRootFns.js +25 -5
  180. package/lib/network/processor/extractSlotRootFns.js.map +1 -1
  181. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  182. package/lib/network/processor/gossipHandlers.js +260 -73
  183. package/lib/network/processor/gossipHandlers.js.map +1 -1
  184. package/lib/network/processor/index.d.ts +11 -1
  185. package/lib/network/processor/index.d.ts.map +1 -1
  186. package/lib/network/processor/index.js +234 -22
  187. package/lib/network/processor/index.js.map +1 -1
  188. package/lib/network/reqresp/types.d.ts +3 -3
  189. package/lib/network/reqresp/types.d.ts.map +1 -1
  190. package/lib/network/reqresp/types.js +9 -3
  191. package/lib/network/reqresp/types.js.map +1 -1
  192. package/lib/node/nodejs.d.ts.map +1 -1
  193. package/lib/node/nodejs.js +4 -1
  194. package/lib/node/nodejs.js.map +1 -1
  195. package/lib/node/notifier.d.ts.map +1 -1
  196. package/lib/node/notifier.js +2 -2
  197. package/lib/node/notifier.js.map +1 -1
  198. package/lib/sync/unknownBlock.js +2 -2
  199. package/lib/sync/unknownBlock.js.map +1 -1
  200. package/lib/sync/utils/downloadByRange.d.ts +3 -3
  201. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  202. package/lib/sync/utils/downloadByRange.js +4 -2
  203. package/lib/sync/utils/downloadByRange.js.map +1 -1
  204. package/lib/sync/utils/downloadByRoot.d.ts +3 -3
  205. package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
  206. package/lib/sync/utils/downloadByRoot.js +10 -5
  207. package/lib/sync/utils/downloadByRoot.js.map +1 -1
  208. package/lib/util/blobs.d.ts +3 -3
  209. package/lib/util/blobs.d.ts.map +1 -1
  210. package/lib/util/blobs.js +21 -10
  211. package/lib/util/blobs.js.map +1 -1
  212. package/lib/util/dataColumns.d.ts +18 -11
  213. package/lib/util/dataColumns.d.ts.map +1 -1
  214. package/lib/util/dataColumns.js +51 -17
  215. package/lib/util/dataColumns.js.map +1 -1
  216. package/lib/util/execution.d.ts +6 -2
  217. package/lib/util/execution.d.ts.map +1 -1
  218. package/lib/util/execution.js +49 -25
  219. package/lib/util/execution.js.map +1 -1
  220. package/lib/util/sszBytes.d.ts +25 -1
  221. package/lib/util/sszBytes.d.ts.map +1 -1
  222. package/lib/util/sszBytes.js +189 -2
  223. package/lib/util/sszBytes.js.map +1 -1
  224. package/package.json +15 -15
  225. package/src/api/impl/beacon/blocks/index.ts +32 -15
  226. package/src/api/impl/beacon/pool/index.ts +4 -0
  227. package/src/api/impl/beacon/state/index.ts +15 -15
  228. package/src/api/impl/debug/index.ts +2 -2
  229. package/src/api/impl/lodestar/index.ts +4 -0
  230. package/src/api/impl/validator/index.ts +7 -0
  231. package/src/chain/ColumnReconstructionTracker.ts +6 -5
  232. package/src/chain/GetBlobsTracker.ts +14 -12
  233. package/src/chain/archiveStore/archiveStore.ts +1 -0
  234. package/src/chain/archiveStore/historicalState/getHistoricalState.ts +6 -5
  235. package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +2 -1
  236. package/src/chain/archiveStore/historicalState/types.ts +2 -0
  237. package/src/chain/archiveStore/historicalState/worker.ts +1 -5
  238. package/src/chain/archiveStore/interface.ts +1 -0
  239. package/src/chain/blocks/blockInput/blockInput.ts +8 -8
  240. package/src/chain/blocks/blockInput/types.ts +4 -4
  241. package/src/chain/blocks/importBlock.ts +45 -23
  242. package/src/chain/blocks/importExecutionPayload.ts +94 -53
  243. package/src/chain/blocks/index.ts +2 -1
  244. package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +53 -12
  245. package/src/chain/blocks/payloadEnvelopeInput/types.ts +2 -1
  246. package/src/chain/blocks/types.ts +25 -14
  247. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +6 -5
  248. package/src/chain/blocks/verifyBlocksSignatures.ts +9 -2
  249. package/src/chain/chain.ts +73 -28
  250. package/src/chain/emitter.ts +25 -7
  251. package/src/chain/errors/dataColumnSidecarError.ts +32 -1
  252. package/src/chain/forkChoice/index.ts +11 -8
  253. package/src/chain/interface.ts +4 -2
  254. package/src/chain/lightClient/index.ts +15 -3
  255. package/src/chain/opPools/aggregatedAttestationPool.ts +6 -1
  256. package/src/chain/opPools/executionPayloadBidPool.ts +3 -3
  257. package/src/chain/options.ts +2 -0
  258. package/src/chain/prepareNextSlot.ts +8 -0
  259. package/src/chain/produceBlock/computeNewStateRoot.ts +2 -1
  260. package/src/chain/produceBlock/produceBlockBody.ts +25 -5
  261. package/src/chain/seenCache/seenGossipBlockInput.ts +2 -2
  262. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +2 -2
  263. package/src/chain/validation/block.ts +2 -1
  264. package/src/chain/validation/dataColumnSidecar.ts +230 -7
  265. package/src/chain/validation/executionPayloadBid.ts +7 -3
  266. package/src/chain/validation/executionPayloadEnvelope.ts +8 -1
  267. package/src/chain/validation/payloadAttestationMessage.ts +4 -0
  268. package/src/chain/validation/syncCommittee.ts +5 -1
  269. package/src/chain/validation/syncCommitteeContributionAndProof.ts +5 -1
  270. package/src/chain/validatorMonitor.ts +3 -2
  271. package/src/db/buckets.ts +2 -2
  272. package/src/db/repositories/dataColumnSidecar.ts +4 -2
  273. package/src/db/repositories/dataColumnSidecarArchive.ts +4 -2
  274. package/src/metrics/metrics/lodestar.ts +34 -0
  275. package/src/network/interface.ts +3 -2
  276. package/src/network/libp2p/index.ts +21 -15
  277. package/src/network/network.ts +7 -4
  278. package/src/network/options.ts +7 -2
  279. package/src/network/processor/extractSlotRootFns.ts +32 -6
  280. package/src/network/processor/gossipHandlers.ts +325 -86
  281. package/src/network/processor/index.ts +304 -22
  282. package/src/network/reqresp/types.ts +13 -5
  283. package/src/node/nodejs.ts +5 -2
  284. package/src/node/notifier.ts +7 -2
  285. package/src/sync/unknownBlock.ts +3 -3
  286. package/src/sync/utils/downloadByRange.ts +9 -7
  287. package/src/sync/utils/downloadByRoot.ts +16 -12
  288. package/src/util/blobs.ts +35 -15
  289. package/src/util/dataColumns.ts +69 -25
  290. package/src/util/execution.ts +49 -30
  291. package/src/util/sszBytes.ts +245 -3
@@ -1,6 +1,7 @@
1
1
  import {routes} from "@lodestar/api";
2
- import {ForkName} from "@lodestar/params";
3
- import {getExecutionPayloadEnvelopeSignatureSet} from "@lodestar/state-transition";
2
+ import {ExecutionStatus, PayloadExecutionStatus} from "@lodestar/fork-choice";
3
+ import {SLOTS_PER_EPOCH} from "@lodestar/params";
4
+ import {getExecutionPayloadEnvelopeSignatureSet, isStatePostGloas} from "@lodestar/state-transition";
4
5
  import {byteArrayEquals, fromHex, toRootHex} from "@lodestar/utils";
5
6
  import {ExecutionPayloadStatus} from "../../execution/index.js";
6
7
  import {isQueueErrorAborted} from "../../util/queue/index.js";
@@ -51,18 +52,33 @@ export class PayloadError extends Error {
51
52
  }
52
53
  }
53
54
 
55
+ function toForkChoiceExecutionStatus(status: ExecutionPayloadStatus): PayloadExecutionStatus {
56
+ switch (status) {
57
+ case ExecutionPayloadStatus.VALID:
58
+ return ExecutionStatus.Valid;
59
+ // TODO GLOAS: Handle optimistic import for payload
60
+ case ExecutionPayloadStatus.SYNCING:
61
+ case ExecutionPayloadStatus.ACCEPTED:
62
+ return ExecutionStatus.Syncing;
63
+ default:
64
+ throw new Error(`Unexpected execution payload status for fork choice: ${status}`);
65
+ }
66
+ }
67
+
54
68
  /**
55
69
  * Import an execution payload envelope after all data is available.
56
70
  *
57
71
  * This function:
58
- * 1. Gets the ProtoBlock from fork choice
59
- * 2. Applies write-queue backpressure (waitForSpace) early, before verification
60
- * 3. Regenerates the block state
61
- * 4. Runs EL verification (notifyNewPayload) in parallel with signature verification and processExecutionPayloadEnvelope
62
- * 5. Persists verified payload envelope to hot DB
63
- * 6. Updates fork choice
64
- * 7. Caches the post-execution payload state
65
- * 8. Records metrics for column sources
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
66
82
  *
67
83
  */
68
84
  export async function importExecutionPayload(
@@ -70,10 +86,24 @@ export async function importExecutionPayload(
70
86
  payloadInput: PayloadEnvelopeInput,
71
87
  opts: ImportPayloadOpts = {}
72
88
  ): Promise<void> {
73
- const envelope = payloadInput.getPayloadEnvelope();
89
+ const signedEnvelope = payloadInput.getPayloadEnvelope();
90
+ const envelope = signedEnvelope.message;
74
91
  const blockRootHex = payloadInput.blockRootHex;
92
+ const blockHashHex = payloadInput.getBlockHashHex();
93
+ const fork = this.config.getForkName(envelope.slot);
94
+
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 < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
100
+ this.emitter.emit(routes.events.EventType.executionPayloadAvailable, {
101
+ slot: envelope.slot,
102
+ blockRoot: blockRootHex,
103
+ });
104
+ }
75
105
 
76
- // 1. Get ProtoBlock for parent root lookup
106
+ // 2. Get ProtoBlock for parent root lookup
77
107
  const protoBlock = this.forkChoice.getBlockHexDefaultStatus(blockRootHex);
78
108
  if (!protoBlock) {
79
109
  throw new PayloadError({
@@ -82,11 +112,11 @@ export async function importExecutionPayload(
82
112
  });
83
113
  }
84
114
 
85
- // 2. Apply backpressure from the write queue early, before doing verification work.
115
+ // 3. Apply backpressure from the write queue early, before doing verification work.
86
116
  // The actual DB write is deferred until after verification succeeds.
87
117
  await this.unfinalizedPayloadEnvelopeWrites.waitForSpace();
88
118
 
89
- // 3. Get pre-state for processExecutionPayloadEnvelope
119
+ // 4. Get pre-state for processExecutionPayloadEnvelope
90
120
  // We need the block state (post-block, pre-payload) to process the envelope
91
121
  const blockState = await this.regen.getBlockSlotState(
92
122
  protoBlock,
@@ -94,17 +124,23 @@ export async function importExecutionPayload(
94
124
  {dontTransferCache: true},
95
125
  RegenCaller.processBlock
96
126
  );
127
+ if (!isStatePostGloas(blockState)) {
128
+ throw new PayloadError({
129
+ code: PayloadErrorCode.STATE_TRANSITION_ERROR,
130
+ message: `Expected gloas+ block state for payload import, got fork=${blockState.forkName}`,
131
+ });
132
+ }
97
133
 
98
- // 4. Run verification steps in parallel
134
+ // 5. Run verification steps in parallel
99
135
  // Note: No data availability check needed here - importExecutionPayload is only
100
136
  // called when payloadInput.isComplete() is true, so all data is already available.
101
137
  const [execResult, signatureValid, postPayloadResult] = await Promise.all([
102
138
  this.executionEngine.notifyNewPayload(
103
- ForkName.gloas,
104
- envelope.message.payload,
139
+ fork,
140
+ envelope.payload,
105
141
  payloadInput.getVersionedHashes(),
106
142
  fromHex(protoBlock.parentRoot),
107
- envelope.message.executionRequests
143
+ envelope.executionRequests
108
144
  ),
109
145
 
110
146
  opts.validSignature === true
@@ -114,7 +150,7 @@ export async function importExecutionPayload(
114
150
  this.config,
115
151
  this.pubkeyCache,
116
152
  blockState,
117
- envelope,
153
+ signedEnvelope,
118
154
  payloadInput.proposerIndex
119
155
  );
120
156
  return this.bls.verifySignatureSets([signatureSet]);
@@ -125,7 +161,7 @@ export async function importExecutionPayload(
125
161
  (async () => {
126
162
  try {
127
163
  return {
128
- postPayloadState: blockState.processExecutionPayloadEnvelope(envelope, {
164
+ postPayloadState: blockState.processExecutionPayloadEnvelope(signedEnvelope, {
129
165
  verifySignature: false,
130
166
  verifyStateRoot: false,
131
167
  }),
@@ -142,12 +178,12 @@ export async function importExecutionPayload(
142
178
  })(),
143
179
  ]);
144
180
 
145
- // 4b. Check signature verification result
181
+ // 5a. Check signature verification result
146
182
  if (!signatureValid) {
147
183
  throw new PayloadError({code: PayloadErrorCode.INVALID_SIGNATURE});
148
184
  }
149
185
 
150
- // 5. Handle EL response
186
+ // 5b. Handle EL response
151
187
  switch (execResult.status) {
152
188
  case ExecutionPayloadStatus.VALID:
153
189
  break;
@@ -161,12 +197,7 @@ export async function importExecutionPayload(
161
197
 
162
198
  case ExecutionPayloadStatus.ACCEPTED:
163
199
  case ExecutionPayloadStatus.SYNCING:
164
- // TODO GLOAS: Handle optimistic import for payload - for now treat as error
165
- throw new PayloadError({
166
- code: PayloadErrorCode.EXECUTION_ENGINE_ERROR,
167
- execStatus: execResult.status,
168
- errorMessage: execResult.validationError ?? "EL syncing, payload not yet validated",
169
- });
200
+ break;
170
201
 
171
202
  case ExecutionPayloadStatus.INVALID_BLOCK_HASH:
172
203
  case ExecutionPayloadStatus.ELERROR:
@@ -178,59 +209,69 @@ export async function importExecutionPayload(
178
209
  });
179
210
  }
180
211
 
181
- // 5b. Verify envelope state root matches post-state
212
+ // 5c. Verify envelope state root matches post-state
182
213
  const postPayloadState = postPayloadResult.postPayloadState;
183
214
  const postPayloadStateRoot = postPayloadState.hashTreeRoot();
184
- if (!byteArrayEquals(envelope.message.stateRoot, postPayloadStateRoot)) {
215
+ if (!byteArrayEquals(envelope.stateRoot, postPayloadStateRoot)) {
185
216
  throw new PayloadError({
186
217
  code: PayloadErrorCode.STATE_TRANSITION_ERROR,
187
- message: `Envelope state root mismatch expected=${toRootHex(envelope.message.stateRoot)} actual=${toRootHex(postPayloadStateRoot)}`,
218
+ message: `Envelope state root mismatch expected=${toRootHex(envelope.stateRoot)} actual=${toRootHex(postPayloadStateRoot)}`,
188
219
  });
189
220
  }
190
221
 
191
- // 5c. Persist payload envelope to hot DB (performed asynchronously to avoid blocking)
222
+ // 6. Persist payload envelope to hot DB (performed asynchronously to avoid blocking)
192
223
  this.unfinalizedPayloadEnvelopeWrites.push(payloadInput).catch((e) => {
193
224
  if (!isQueueErrorAborted(e)) {
194
225
  this.logger.error(
195
226
  "Error pushing payload envelope to unfinalized write queue",
196
- {slot: payloadInput.slot, root: blockRootHex},
227
+ {slot: envelope.slot, blockRoot: blockRootHex},
197
228
  e as Error
198
229
  );
199
230
  }
200
231
  });
201
232
 
202
- // 6. Update fork choice
233
+ // 7. Update fork choice
203
234
  this.forkChoice.onExecutionPayload(
204
235
  blockRootHex,
205
- payloadInput.getBlockHashHex(),
206
- envelope.message.payload.blockNumber,
207
- toRootHex(postPayloadStateRoot)
236
+ blockHashHex,
237
+ envelope.payload.blockNumber,
238
+ toRootHex(postPayloadStateRoot),
239
+ toForkChoiceExecutionStatus(execResult.status)
208
240
  );
209
241
 
210
- // 7. Cache payload state
211
- // TODO GLOAS: Enable when PR #8868 merged (adds processPayloadState)
212
- // this.regen.processPayloadState(postPayloadState);
213
- // if epoch boundary also call
214
- // this.regen.addCheckpointState(cp, checkpointState, true);
242
+ // 8. Cache payload state
243
+ this.regen.processPayloadState(postPayloadState);
244
+ if (postPayloadState.slot % SLOTS_PER_EPOCH === 0) {
245
+ const {checkpoint} = postPayloadState.computeAnchorCheckpoint();
246
+ this.regen.addCheckpointState(checkpoint, postPayloadState, true);
247
+ }
215
248
 
216
- // 8. Record metrics for payload envelope and column sources
249
+ // 9. Record metrics for payload envelope and column sources
217
250
  this.metrics?.importPayload.bySource.inc({source: payloadInput.getPayloadEnvelopeSource().source});
218
251
  for (const {source} of payloadInput.getSampledColumnsWithSource()) {
219
252
  this.metrics?.importPayload.columnsBySource.inc({source});
220
253
  }
221
254
 
222
- this.logger.verbose("Execution payload imported", {
223
- slot: payloadInput.slot,
224
- root: blockRootHex,
225
- blockHash: payloadInput.getBlockHashHex(),
226
- });
255
+ const stateRootHex = toRootHex(envelope.stateRoot);
227
256
 
228
- // 9. Emit event after payload is fully verified and imported to fork choice, only for recent enough payloads
229
- const currentSlot = this.clock.currentSlot;
230
- if (currentSlot - payloadInput.slot < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
231
- this.emitter.emit(routes.events.EventType.executionPayloadAvailable, {
232
- slot: payloadInput.slot,
257
+ // 10. Emit event after payload is fully verified and imported to fork choice, only for recent enough payloads
258
+ if (this.clock.currentSlot - envelope.slot < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
259
+ this.emitter.emit(routes.events.EventType.executionPayload, {
260
+ slot: envelope.slot,
261
+ builderIndex: envelope.builderIndex,
262
+ blockHash: blockHashHex,
233
263
  blockRoot: blockRootHex,
264
+ stateRoot: stateRootHex,
265
+ // TODO GLOAS: revisit once we support optimistic import
266
+ executionOptimistic: false,
234
267
  });
235
268
  }
269
+
270
+ this.logger.verbose("Execution payload imported", {
271
+ slot: envelope.slot,
272
+ builderIndex: envelope.builderIndex,
273
+ blockRoot: blockRootHex,
274
+ blockHash: blockHashHex,
275
+ stateRoot: stateRootHex,
276
+ });
236
277
  }
@@ -88,7 +88,8 @@ export async function processBlocks(
88
88
  const fullyVerifiedBlocks = relevantBlocks.map(
89
89
  (block, i): FullyVerifiedBlock => ({
90
90
  blockInput: block,
91
- postState: postStates[i],
91
+ postBlockState: postStates[i],
92
+ postEnvelopeState: null,
92
93
  parentBlockSlot: parentSlots[i],
93
94
  executionStatus: executionStatuses[i],
94
95
  // start supporting optimistic syncing/processing
@@ -1,8 +1,9 @@
1
- import {NUMBER_OF_COLUMNS} from "@lodestar/params";
2
- import {ColumnIndex, DataColumnSidecars, RootHex, Slot, ValidatorIndex, deneb, gloas} from "@lodestar/types";
1
+ import {ForkName, NUMBER_OF_COLUMNS} from "@lodestar/params";
2
+ import {ColumnIndex, RootHex, Slot, ValidatorIndex, deneb, gloas} from "@lodestar/types";
3
3
  import {toRootHex, withTimeout} from "@lodestar/utils";
4
4
  import {VersionedHashes} from "../../../execution/index.js";
5
5
  import {kzgCommitmentToVersionedHash} from "../../../util/blobs.js";
6
+ import {MissingColumnMeta} from "../blockInput/types.js";
6
7
  import {AddPayloadEnvelopeProps, ColumnWithSource, CreateFromBlockProps, SourceMeta} from "./types.js";
7
8
 
8
9
  export type PayloadEnvelopeInputState =
@@ -59,6 +60,7 @@ function createPromise<T>(): PromiseParts<T> {
59
60
  export class PayloadEnvelopeInput {
60
61
  readonly blockRootHex: RootHex;
61
62
  readonly slot: Slot;
63
+ readonly forkName: ForkName;
62
64
  readonly proposerIndex: ValidatorIndex;
63
65
  readonly bid: gloas.ExecutionPayloadBid;
64
66
  readonly versionedHashes: VersionedHashes;
@@ -71,13 +73,14 @@ export class PayloadEnvelopeInput {
71
73
  private timeCreatedSec: number;
72
74
 
73
75
  private readonly payloadEnvelopeDataPromise: PromiseParts<gloas.SignedExecutionPayloadEnvelope>;
74
- private readonly columnsDataPromise: PromiseParts<DataColumnSidecars>;
76
+ private readonly columnsDataPromise: PromiseParts<gloas.DataColumnSidecar[]>;
75
77
 
76
78
  state: PayloadEnvelopeInputState;
77
79
 
78
80
  private constructor(props: {
79
81
  blockRootHex: RootHex;
80
82
  slot: Slot;
83
+ forkName: ForkName;
81
84
  proposerIndex: ValidatorIndex;
82
85
  bid: gloas.ExecutionPayloadBid;
83
86
  sampledColumns: ColumnIndex[];
@@ -86,6 +89,7 @@ export class PayloadEnvelopeInput {
86
89
  }) {
87
90
  this.blockRootHex = props.blockRootHex;
88
91
  this.slot = props.slot;
92
+ this.forkName = props.forkName;
89
93
  this.proposerIndex = props.proposerIndex;
90
94
  this.bid = props.bid;
91
95
  this.versionedHashes = props.bid.blobKzgCommitments.map(kzgCommitmentToVersionedHash);
@@ -112,6 +116,7 @@ export class PayloadEnvelopeInput {
112
116
  return new PayloadEnvelopeInput({
113
117
  blockRootHex: props.blockRootHex,
114
118
  slot: props.block.message.slot,
119
+ forkName: props.forkName,
115
120
  proposerIndex: props.block.message.proposerIndex,
116
121
  bid,
117
122
  sampledColumns: props.sampledColumns,
@@ -173,8 +178,12 @@ export class PayloadEnvelopeInput {
173
178
  }
174
179
  }
175
180
 
176
- addColumn(columnWithSource: ColumnWithSource): void {
181
+ addColumn(columnWithSource: ColumnWithSource): boolean {
177
182
  const {columnSidecar, seenTimestampSec} = columnWithSource;
183
+ if (this.columnsCache.has(columnSidecar.index)) {
184
+ return false;
185
+ }
186
+
178
187
  this.columnsCache.set(columnSidecar.index, columnWithSource);
179
188
 
180
189
  const sampledColumns = this.getSampledColumns();
@@ -191,7 +200,7 @@ export class PayloadEnvelopeInput {
191
200
  sampledColumns.length === this.sampledColumns.length;
192
201
 
193
202
  if (!hasAllData) {
194
- return;
203
+ return true;
195
204
  }
196
205
 
197
206
  if (hasComputedAllData) {
@@ -217,6 +226,20 @@ export class PayloadEnvelopeInput {
217
226
  hasComputedAllData: hasComputedAllData || this.state.hasComputedAllData,
218
227
  };
219
228
  }
229
+
230
+ return true;
231
+ }
232
+
233
+ hasColumn(index: ColumnIndex): boolean {
234
+ return this.columnsCache.has(index);
235
+ }
236
+
237
+ getColumn(index: ColumnIndex): gloas.DataColumnSidecar | undefined {
238
+ return this.columnsCache.get(index)?.columnSidecar;
239
+ }
240
+
241
+ getAllColumns(): gloas.DataColumnSidecar[] {
242
+ return [...this.columnsCache.values()].map(({columnSidecar}) => columnSidecar);
220
243
  }
221
244
 
222
245
  getVersionedHashes(): VersionedHashes {
@@ -237,8 +260,8 @@ export class PayloadEnvelopeInput {
237
260
  return this.state.payloadEnvelopeSource;
238
261
  }
239
262
 
240
- getSampledColumns(): gloas.DataColumnSidecars {
241
- const columns: gloas.DataColumnSidecars = [];
263
+ getSampledColumns(): gloas.DataColumnSidecar[] {
264
+ const columns: gloas.DataColumnSidecar[] = [];
242
265
  for (const index of this.sampledColumns) {
243
266
  const column = this.columnsCache.get(index);
244
267
  if (column) {
@@ -259,8 +282,8 @@ export class PayloadEnvelopeInput {
259
282
  return columns;
260
283
  }
261
284
 
262
- getCustodyColumns(): gloas.DataColumnSidecars {
263
- const columns: gloas.DataColumnSidecars = [];
285
+ getCustodyColumns(): gloas.DataColumnSidecar[] {
286
+ const columns: gloas.DataColumnSidecar[] = [];
264
287
  for (const index of this.custodyColumns) {
265
288
  const column = this.columnsCache.get(index);
266
289
  if (column) {
@@ -270,11 +293,29 @@ export class PayloadEnvelopeInput {
270
293
  return columns;
271
294
  }
272
295
 
296
+ hasAllData(): boolean {
297
+ return this.state.hasAllData;
298
+ }
299
+
300
+ getMissingSampledColumnMeta(): MissingColumnMeta {
301
+ if (this.state.hasAllData) {
302
+ return {missing: [], versionedHashes: this.versionedHashes};
303
+ }
304
+
305
+ const missing: ColumnIndex[] = [];
306
+ for (const index of this.sampledColumns) {
307
+ if (!this.columnsCache.has(index)) {
308
+ missing.push(index);
309
+ }
310
+ }
311
+ return {missing, versionedHashes: this.versionedHashes};
312
+ }
313
+
273
314
  hasComputedAllData(): boolean {
274
315
  return this.state.hasComputedAllData;
275
316
  }
276
317
 
277
- waitForComputedAllData(timeout: number, signal?: AbortSignal): Promise<DataColumnSidecars> {
318
+ waitForComputedAllData(timeout: number, signal?: AbortSignal): Promise<gloas.DataColumnSidecar[]> {
278
319
  if (this.state.hasComputedAllData) {
279
320
  return Promise.resolve(this.getSampledColumns());
280
321
  }
@@ -319,7 +360,7 @@ export class PayloadEnvelopeInput {
319
360
  hasAllData: boolean;
320
361
  hasComputedAllData: boolean;
321
362
  isComplete: boolean;
322
- columnsCount: number;
363
+ receivedColumns: number;
323
364
  sampledColumnsCount: number;
324
365
  } {
325
366
  return {
@@ -329,7 +370,7 @@ export class PayloadEnvelopeInput {
329
370
  hasAllData: this.state.hasAllData,
330
371
  hasComputedAllData: this.state.hasComputedAllData,
331
372
  isComplete: this.isComplete(),
332
- columnsCount: this.columnsCache.size,
373
+ receivedColumns: this.columnsCache.size,
333
374
  sampledColumnsCount: this.sampledColumns.length,
334
375
  };
335
376
  }
@@ -1,4 +1,4 @@
1
- import {ForkPostGloas} from "@lodestar/params";
1
+ import {ForkName, ForkPostGloas} from "@lodestar/params";
2
2
  import {ColumnIndex, RootHex, SignedBeaconBlock, gloas} from "@lodestar/types";
3
3
 
4
4
  export enum PayloadEnvelopeInputSource {
@@ -23,6 +23,7 @@ export type ColumnWithSource = SourceMeta & {
23
23
  export type CreateFromBlockProps = {
24
24
  blockRootHex: RootHex;
25
25
  block: SignedBeaconBlock<ForkPostGloas>;
26
+ forkName: ForkName;
26
27
  sampledColumns: ColumnIndex[];
27
28
  custodyColumns: ColumnIndex[];
28
29
  timeCreatedSec: number;
@@ -1,5 +1,5 @@
1
1
  import type {ChainForkConfig} from "@lodestar/config";
2
- import {MaybeValidExecutionStatus} from "@lodestar/fork-choice";
2
+ import {BlockExecutionStatus, PayloadExecutionStatus} 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";
@@ -88,24 +88,35 @@ export type ImportBlockOpts = {
88
88
  seenTimestampSec?: number;
89
89
  };
90
90
 
91
- /**
92
- * A wrapper around a `SignedBeaconBlock` that indicates that this block is fully verified and ready to import
93
- */
94
- export type FullyVerifiedBlock = {
91
+ type FullyVerifiedBlockBase = {
95
92
  blockInput: IBlockInput;
96
- postState: IBeaconStateView;
93
+ postBlockState: IBeaconStateView;
97
94
  parentBlockSlot: Slot;
98
95
  proposerBalanceDelta: number;
99
- /**
100
- * If the execution payload couldnt be verified because of EL syncing status,
101
- * used in optimistic sync or for merge block
102
- */
103
- executionStatus: MaybeValidExecutionStatus;
104
96
  dataAvailabilityStatus: DataAvailabilityStatus;
105
- /**
106
- * Pre-computed indexed attestations from signature verification to avoid duplicate work
107
- */
97
+ /** Pre-computed indexed attestations from signature verification to avoid duplicate work */
108
98
  indexedAttestations: IndexedAttestation[];
109
99
  /** Seen timestamp seconds */
110
100
  seenTimestampSec: number;
111
101
  };
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
+ );
@@ -1,14 +1,14 @@
1
1
  import {ChainForkConfig} from "@lodestar/config";
2
2
  import {
3
+ BlockExecutionStatus,
3
4
  ExecutionStatus,
4
5
  IForkChoice,
5
6
  LVHInvalidResponse,
6
7
  LVHValidResponse,
7
- MaybeValidExecutionStatus,
8
8
  ProtoBlock,
9
9
  } from "@lodestar/fork-choice";
10
10
  import {ForkSeq} from "@lodestar/params";
11
- import {IBeaconStateView, isExecutionBlockBodyType} from "@lodestar/state-transition";
11
+ import {IBeaconStateView, isExecutionBlockBodyType, isStatePostBellatrix} from "@lodestar/state-transition";
12
12
  import {bellatrix, electra} from "@lodestar/types";
13
13
  import {ErrorAborted, Logger, toRootHex} from "@lodestar/utils";
14
14
  import {ExecutionPayloadStatus, IExecutionEngine} from "../../execution/engine/interface.js";
@@ -33,7 +33,7 @@ type ExecAbortType = {blockIndex: number; execError: BlockError};
33
33
  export type SegmentExecStatus =
34
34
  | {
35
35
  execAborted: null;
36
- executionStatuses: MaybeValidExecutionStatus[];
36
+ executionStatuses: BlockExecutionStatus[];
37
37
  executionTime: number;
38
38
  }
39
39
  | {execAborted: ExecAbortType; invalidSegmentLVH?: LVHInvalidResponse};
@@ -62,7 +62,7 @@ export async function verifyBlocksExecutionPayload(
62
62
  signal: AbortSignal,
63
63
  opts: BlockProcessOpts & ImportBlockOpts
64
64
  ): Promise<SegmentExecStatus> {
65
- const executionStatuses: MaybeValidExecutionStatus[] = [];
65
+ const executionStatuses: BlockExecutionStatus[] = [];
66
66
  const recvToValLatency = Date.now() / 1000 - (opts.seenTimestampSec ?? Date.now() / 1000);
67
67
  const lastBlock = blockInputs.at(-1);
68
68
 
@@ -103,7 +103,7 @@ export async function verifyBlocksExecutionPayload(
103
103
  return getSegmentErrorResponse({verifyResponse, blockIndex}, parentBlock, blockInputs);
104
104
  }
105
105
 
106
- // If we are here then its because executionStatus is one of MaybeValidExecutionStatus
106
+ // If we are here then its because executionStatus is one of BlockExecutionStatus
107
107
  const {executionStatus} = verifyResponse;
108
108
  executionStatuses.push(executionStatus);
109
109
  }
@@ -152,6 +152,7 @@ export async function verifyBlockExecutionPayload(
152
152
 
153
153
  /** Not null if execution is enabled */
154
154
  const executionPayloadEnabled =
155
+ isStatePostBellatrix(preState0) &&
155
156
  preState0.isExecutionStateType &&
156
157
  isExecutionBlockBodyType(block.message.body) &&
157
158
  preState0.isExecutionEnabled(block.message)
@@ -1,5 +1,10 @@
1
1
  import {BeaconConfig} from "@lodestar/config";
2
- import {IBeaconStateView, getBlockSignatureSets} from "@lodestar/state-transition";
2
+ import {
3
+ IBeaconStateView,
4
+ SyncCommitteeCacheEmpty,
5
+ getBlockSignatureSets,
6
+ isStatePostAltair,
7
+ } from "@lodestar/state-transition";
3
8
  import {IndexedAttestation, SignedBeaconBlock} from "@lodestar/types";
4
9
  import {Logger} from "@lodestar/utils";
5
10
  import {Metrics} from "../../metrics/metrics.js";
@@ -27,7 +32,9 @@ export async function verifyBlocksSignatures(
27
32
  ): Promise<{verifySignaturesTime: number}> {
28
33
  const isValidPromises: Promise<boolean>[] = [];
29
34
  const recvToValLatency = Date.now() / 1000 - (opts.seenTimestampSec ?? Date.now() / 1000);
30
- const currentSyncCommitteeIndexed = preState0.currentSyncCommitteeIndexed;
35
+ const currentSyncCommitteeIndexed = isStatePostAltair(preState0)
36
+ ? preState0.currentSyncCommitteeIndexed
37
+ : new SyncCommitteeCacheEmpty();
31
38
 
32
39
  // Verifies signatures after running state transition, so all SyncCommittee signed roots are known at this point.
33
40
  // We must ensure block.slot <= state.slot before running getAllBlockSignatureSets().