@lodestar/beacon-node 1.43.0-dev.433e692fd9 → 1.43.0-dev.4358217e12

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 (311) hide show
  1. package/lib/api/impl/beacon/blocks/index.js +7 -9
  2. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  3. package/lib/api/impl/beacon/state/utils.d.ts +2 -2
  4. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  5. package/lib/api/impl/beacon/state/utils.js.map +1 -1
  6. package/lib/api/impl/lodestar/index.js +1 -1
  7. package/lib/api/impl/lodestar/index.js.map +1 -1
  8. package/lib/api/impl/validator/index.d.ts.map +1 -1
  9. package/lib/api/impl/validator/index.js +0 -4
  10. package/lib/api/impl/validator/index.js.map +1 -1
  11. package/lib/chain/GetBlobsTracker.d.ts +1 -1
  12. package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
  13. package/lib/chain/GetBlobsTracker.js +1 -2
  14. package/lib/chain/GetBlobsTracker.js.map +1 -1
  15. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  16. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  17. package/lib/chain/archiveStore/interface.d.ts +4 -4
  18. package/lib/chain/archiveStore/interface.d.ts.map +1 -1
  19. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts +4 -4
  20. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts.map +1 -1
  21. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js.map +1 -1
  22. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +2 -2
  23. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
  24. package/lib/chain/archiveStore/utils/archiveBlocks.js +110 -58
  25. package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
  26. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  27. package/lib/chain/blocks/importBlock.js +9 -10
  28. package/lib/chain/blocks/importBlock.js.map +1 -1
  29. package/lib/chain/blocks/importExecutionPayload.d.ts +26 -13
  30. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  31. package/lib/chain/blocks/importExecutionPayload.js +86 -84
  32. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  33. package/lib/chain/blocks/index.d.ts +5 -3
  34. package/lib/chain/blocks/index.d.ts.map +1 -1
  35. package/lib/chain/blocks/index.js +28 -10
  36. package/lib/chain/blocks/index.js.map +1 -1
  37. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +3 -0
  38. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
  39. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +20 -0
  40. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
  41. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +5 -0
  42. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -1
  43. package/lib/chain/blocks/payloadEnvelopeProcessor.js +7 -5
  44. package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
  45. package/lib/chain/blocks/types.d.ts +14 -20
  46. package/lib/chain/blocks/types.d.ts.map +1 -1
  47. package/lib/chain/blocks/utils/chainSegment.d.ts +23 -2
  48. package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
  49. package/lib/chain/blocks/utils/chainSegment.js +81 -12
  50. package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
  51. package/lib/chain/blocks/verifyBlock.d.ts +3 -2
  52. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  53. package/lib/chain/blocks/verifyBlock.js +30 -5
  54. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  55. package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
  56. package/lib/chain/blocks/verifyBlocksSanityChecks.js +15 -4
  57. package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
  58. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +24 -0
  59. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -0
  60. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +76 -0
  61. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -0
  62. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts +14 -0
  63. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -0
  64. package/lib/chain/blocks/verifyPayloadsDataAvailability.js +25 -0
  65. package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -0
  66. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts +1 -1
  67. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts.map +1 -1
  68. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js +2 -11
  69. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js.map +1 -1
  70. package/lib/chain/chain.d.ts +8 -6
  71. package/lib/chain/chain.d.ts.map +1 -1
  72. package/lib/chain/chain.js +19 -6
  73. package/lib/chain/chain.js.map +1 -1
  74. package/lib/chain/emitter.d.ts +16 -4
  75. package/lib/chain/emitter.d.ts.map +1 -1
  76. package/lib/chain/emitter.js +5 -0
  77. package/lib/chain/emitter.js.map +1 -1
  78. package/lib/chain/errors/blockError.d.ts +8 -1
  79. package/lib/chain/errors/blockError.d.ts.map +1 -1
  80. package/lib/chain/errors/blockError.js +2 -0
  81. package/lib/chain/errors/blockError.js.map +1 -1
  82. package/lib/chain/errors/executionPayloadBid.d.ts +5 -0
  83. package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
  84. package/lib/chain/errors/executionPayloadBid.js +1 -0
  85. package/lib/chain/errors/executionPayloadBid.js.map +1 -1
  86. package/lib/chain/errors/executionPayloadEnvelope.d.ts +5 -0
  87. package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
  88. package/lib/chain/errors/executionPayloadEnvelope.js +1 -0
  89. package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
  90. package/lib/chain/errors/index.d.ts +1 -0
  91. package/lib/chain/errors/index.d.ts.map +1 -1
  92. package/lib/chain/errors/index.js +1 -0
  93. package/lib/chain/errors/index.js.map +1 -1
  94. package/lib/chain/errors/proposerPreferences.d.ts +33 -0
  95. package/lib/chain/errors/proposerPreferences.d.ts.map +1 -0
  96. package/lib/chain/errors/proposerPreferences.js +13 -0
  97. package/lib/chain/errors/proposerPreferences.js.map +1 -0
  98. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  99. package/lib/chain/forkChoice/index.js +11 -19
  100. package/lib/chain/forkChoice/index.js.map +1 -1
  101. package/lib/chain/interface.d.ts +7 -5
  102. package/lib/chain/interface.d.ts.map +1 -1
  103. package/lib/chain/interface.js.map +1 -1
  104. package/lib/chain/opPools/payloadAttestationPool.d.ts +2 -2
  105. package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -1
  106. package/lib/chain/opPools/payloadAttestationPool.js +4 -4
  107. package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
  108. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  109. package/lib/chain/prepareNextSlot.js +46 -16
  110. package/lib/chain/prepareNextSlot.js.map +1 -1
  111. package/lib/chain/produceBlock/produceBlockBody.d.ts +4 -2
  112. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  113. package/lib/chain/produceBlock/produceBlockBody.js +56 -26
  114. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  115. package/lib/chain/regen/interface.d.ts +1 -0
  116. package/lib/chain/regen/interface.d.ts.map +1 -1
  117. package/lib/chain/regen/interface.js +1 -0
  118. package/lib/chain/regen/interface.js.map +1 -1
  119. package/lib/chain/seenCache/index.d.ts +1 -0
  120. package/lib/chain/seenCache/index.d.ts.map +1 -1
  121. package/lib/chain/seenCache/index.js +1 -0
  122. package/lib/chain/seenCache/index.js.map +1 -1
  123. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +11 -4
  124. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
  125. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +20 -18
  126. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
  127. package/lib/chain/seenCache/seenProposerPreferences.d.ts +15 -0
  128. package/lib/chain/seenCache/seenProposerPreferences.d.ts.map +1 -0
  129. package/lib/chain/seenCache/seenProposerPreferences.js +25 -0
  130. package/lib/chain/seenCache/seenProposerPreferences.js.map +1 -0
  131. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  132. package/lib/chain/stateCache/persistentCheckpointsCache.js +4 -1
  133. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  134. package/lib/chain/validation/block.d.ts.map +1 -1
  135. package/lib/chain/validation/block.js +1 -0
  136. package/lib/chain/validation/block.js.map +1 -1
  137. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  138. package/lib/chain/validation/executionPayloadBid.js +13 -1
  139. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  140. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  141. package/lib/chain/validation/executionPayloadEnvelope.js +19 -9
  142. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  143. package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
  144. package/lib/chain/validation/payloadAttestationMessage.js +4 -3
  145. package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
  146. package/lib/chain/validation/proposerPreferences.d.ts +8 -0
  147. package/lib/chain/validation/proposerPreferences.d.ts.map +1 -0
  148. package/lib/chain/validation/proposerPreferences.js +69 -0
  149. package/lib/chain/validation/proposerPreferences.js.map +1 -0
  150. package/lib/db/repositories/executionPayloadEnvelopeArchive.js +1 -1
  151. package/lib/db/repositories/executionPayloadEnvelopeArchive.js.map +1 -1
  152. package/lib/execution/engine/http.d.ts.map +1 -1
  153. package/lib/execution/engine/http.js +21 -14
  154. package/lib/execution/engine/http.js.map +1 -1
  155. package/lib/execution/engine/interface.d.ts +1 -0
  156. package/lib/execution/engine/interface.d.ts.map +1 -1
  157. package/lib/execution/engine/mock.d.ts.map +1 -1
  158. package/lib/execution/engine/mock.js +6 -0
  159. package/lib/execution/engine/mock.js.map +1 -1
  160. package/lib/execution/engine/types.d.ts +20 -0
  161. package/lib/execution/engine/types.d.ts.map +1 -1
  162. package/lib/execution/engine/types.js +18 -0
  163. package/lib/execution/engine/types.js.map +1 -1
  164. package/lib/metrics/metrics/lodestar.d.ts +1 -0
  165. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  166. package/lib/metrics/metrics/lodestar.js +4 -0
  167. package/lib/metrics/metrics/lodestar.js.map +1 -1
  168. package/lib/network/gossip/interface.d.ts +7 -1
  169. package/lib/network/gossip/interface.d.ts.map +1 -1
  170. package/lib/network/gossip/interface.js +1 -0
  171. package/lib/network/gossip/interface.js.map +1 -1
  172. package/lib/network/gossip/scoringParameters.d.ts.map +1 -1
  173. package/lib/network/gossip/scoringParameters.js +12 -1
  174. package/lib/network/gossip/scoringParameters.js.map +1 -1
  175. package/lib/network/gossip/topic.d.ts +11 -2
  176. package/lib/network/gossip/topic.d.ts.map +1 -1
  177. package/lib/network/gossip/topic.js +6 -0
  178. package/lib/network/gossip/topic.js.map +1 -1
  179. package/lib/network/network.js +1 -1
  180. package/lib/network/network.js.map +1 -1
  181. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  182. package/lib/network/processor/gossipHandlers.js +32 -12
  183. package/lib/network/processor/gossipHandlers.js.map +1 -1
  184. package/lib/network/processor/gossipQueues/index.d.ts.map +1 -1
  185. package/lib/network/processor/gossipQueues/index.js +5 -0
  186. package/lib/network/processor/gossipQueues/index.js.map +1 -1
  187. package/lib/network/processor/index.d.ts.map +1 -1
  188. package/lib/network/processor/index.js +1 -0
  189. package/lib/network/processor/index.js.map +1 -1
  190. package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
  191. package/lib/network/reqresp/handlers/beaconBlocksByRange.js +14 -6
  192. package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
  193. package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts.map +1 -1
  194. package/lib/network/reqresp/handlers/blobSidecarsByRange.js +11 -5
  195. package/lib/network/reqresp/handlers/blobSidecarsByRange.js.map +1 -1
  196. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
  197. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +17 -5
  198. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
  199. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -1
  200. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +7 -4
  201. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
  202. package/lib/node/nodejs.d.ts.map +1 -1
  203. package/lib/node/nodejs.js +4 -2
  204. package/lib/node/nodejs.js.map +1 -1
  205. package/lib/node/notifier.js +7 -1
  206. package/lib/node/notifier.js.map +1 -1
  207. package/lib/sync/range/batch.d.ts +12 -2
  208. package/lib/sync/range/batch.d.ts.map +1 -1
  209. package/lib/sync/range/batch.js +56 -30
  210. package/lib/sync/range/batch.js.map +1 -1
  211. package/lib/sync/range/chain.d.ts +6 -2
  212. package/lib/sync/range/chain.d.ts.map +1 -1
  213. package/lib/sync/range/chain.js +4 -3
  214. package/lib/sync/range/chain.js.map +1 -1
  215. package/lib/sync/range/range.d.ts.map +1 -1
  216. package/lib/sync/range/range.js +17 -6
  217. package/lib/sync/range/range.js.map +1 -1
  218. package/lib/sync/types.d.ts +34 -0
  219. package/lib/sync/types.d.ts.map +1 -1
  220. package/lib/sync/types.js +34 -0
  221. package/lib/sync/types.js.map +1 -1
  222. package/lib/sync/unknownBlock.d.ts +24 -1
  223. package/lib/sync/unknownBlock.d.ts.map +1 -1
  224. package/lib/sync/unknownBlock.js +649 -53
  225. package/lib/sync/unknownBlock.js.map +1 -1
  226. package/lib/sync/utils/downloadByRange.d.ts +46 -10
  227. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  228. package/lib/sync/utils/downloadByRange.js +147 -24
  229. package/lib/sync/utils/downloadByRange.js.map +1 -1
  230. package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
  231. package/lib/sync/utils/downloadByRoot.js +6 -2
  232. package/lib/sync/utils/downloadByRoot.js.map +1 -1
  233. package/lib/sync/utils/pendingBlocksTree.d.ts +0 -1
  234. package/lib/sync/utils/pendingBlocksTree.d.ts.map +1 -1
  235. package/lib/sync/utils/pendingBlocksTree.js +0 -9
  236. package/lib/sync/utils/pendingBlocksTree.js.map +1 -1
  237. package/lib/util/sszBytes.d.ts.map +1 -1
  238. package/lib/util/sszBytes.js +16 -3
  239. package/lib/util/sszBytes.js.map +1 -1
  240. package/package.json +17 -16
  241. package/src/api/impl/beacon/blocks/index.ts +9 -9
  242. package/src/api/impl/beacon/state/utils.ts +2 -2
  243. package/src/api/impl/lodestar/index.ts +1 -1
  244. package/src/api/impl/validator/index.ts +0 -4
  245. package/src/chain/GetBlobsTracker.ts +1 -2
  246. package/src/chain/archiveStore/archiveStore.ts +5 -5
  247. package/src/chain/archiveStore/interface.ts +4 -4
  248. package/src/chain/archiveStore/strategies/frequencyStateArchiveStrategy.ts +4 -4
  249. package/src/chain/archiveStore/utils/archiveBlocks.ts +153 -94
  250. package/src/chain/blocks/importBlock.ts +7 -13
  251. package/src/chain/blocks/importExecutionPayload.ts +106 -103
  252. package/src/chain/blocks/index.ts +44 -13
  253. package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +27 -0
  254. package/src/chain/blocks/payloadEnvelopeProcessor.ts +7 -6
  255. package/src/chain/blocks/types.ts +14 -25
  256. package/src/chain/blocks/utils/chainSegment.ts +106 -17
  257. package/src/chain/blocks/verifyBlock.ts +35 -6
  258. package/src/chain/blocks/verifyBlocksSanityChecks.ts +16 -7
  259. package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +129 -0
  260. package/src/chain/blocks/verifyPayloadsDataAvailability.ts +38 -0
  261. package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +9 -18
  262. package/src/chain/chain.ts +36 -19
  263. package/src/chain/emitter.ts +15 -3
  264. package/src/chain/errors/blockError.ts +4 -1
  265. package/src/chain/errors/executionPayloadBid.ts +6 -0
  266. package/src/chain/errors/executionPayloadEnvelope.ts +6 -0
  267. package/src/chain/errors/index.ts +1 -0
  268. package/src/chain/errors/proposerPreferences.ts +39 -0
  269. package/src/chain/forkChoice/index.ts +8 -24
  270. package/src/chain/interface.ts +11 -3
  271. package/src/chain/opPools/payloadAttestationPool.ts +4 -8
  272. package/src/chain/prepareNextSlot.ts +60 -17
  273. package/src/chain/produceBlock/produceBlockBody.ts +77 -23
  274. package/src/chain/regen/interface.ts +1 -0
  275. package/src/chain/seenCache/index.ts +1 -0
  276. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +22 -20
  277. package/src/chain/seenCache/seenProposerPreferences.ts +29 -0
  278. package/src/chain/stateCache/persistentCheckpointsCache.ts +4 -1
  279. package/src/chain/validation/block.ts +1 -0
  280. package/src/chain/validation/executionPayloadBid.ts +14 -0
  281. package/src/chain/validation/executionPayloadEnvelope.ts +20 -10
  282. package/src/chain/validation/payloadAttestationMessage.ts +5 -3
  283. package/src/chain/validation/proposerPreferences.ts +91 -0
  284. package/src/db/repositories/executionPayloadEnvelopeArchive.ts +1 -1
  285. package/src/execution/engine/http.ts +21 -14
  286. package/src/execution/engine/interface.ts +1 -0
  287. package/src/execution/engine/mock.ts +8 -1
  288. package/src/execution/engine/types.ts +41 -0
  289. package/src/metrics/metrics/lodestar.ts +4 -0
  290. package/src/network/gossip/interface.ts +6 -0
  291. package/src/network/gossip/scoringParameters.ts +14 -1
  292. package/src/network/gossip/topic.ts +6 -0
  293. package/src/network/network.ts +1 -1
  294. package/src/network/processor/gossipHandlers.ts +41 -16
  295. package/src/network/processor/gossipQueues/index.ts +5 -0
  296. package/src/network/processor/index.ts +1 -0
  297. package/src/network/reqresp/handlers/beaconBlocksByRange.ts +14 -6
  298. package/src/network/reqresp/handlers/blobSidecarsByRange.ts +11 -5
  299. package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +17 -5
  300. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +7 -4
  301. package/src/node/nodejs.ts +4 -2
  302. package/src/node/notifier.ts +8 -1
  303. package/src/sync/range/batch.ts +90 -35
  304. package/src/sync/range/chain.ts +13 -5
  305. package/src/sync/range/range.ts +18 -6
  306. package/src/sync/types.ts +72 -0
  307. package/src/sync/unknownBlock.ts +810 -57
  308. package/src/sync/utils/downloadByRange.ts +256 -39
  309. package/src/sync/utils/downloadByRoot.ts +12 -2
  310. package/src/sync/utils/pendingBlocksTree.ts +0 -15
  311. package/src/util/sszBytes.ts +21 -3
@@ -1,29 +1,118 @@
1
1
  import {ChainForkConfig} from "@lodestar/config";
2
- import {ssz} from "@lodestar/types";
2
+ import {ProtoBlock} from "@lodestar/fork-choice";
3
+ import {Slot, isGloasBeaconBlock, ssz} from "@lodestar/types";
4
+ import {toRootHex} from "@lodestar/utils";
3
5
  import {BlockError, BlockErrorCode} from "../../errors/index.js";
4
6
  import {IBlockInput} from "../blockInput/types.js";
7
+ import {PayloadEnvelopeInput} from "../payloadEnvelopeInput/payloadEnvelopeInput.js";
8
+
9
+ export type OrphanedPayloadEnvelope = {
10
+ slot: Slot;
11
+ payloadEnvelopeInput: PayloadEnvelopeInput;
12
+ };
13
+
14
+ export type ChainSegmentResult = {warnings: OrphanedPayloadEnvelope[] | null};
5
15
 
6
16
  /**
7
- * Assert this chain segment of blocks is linear with slot numbers and hashes
17
+ * Assert this chain segment of blocks is linear with slot numbers and hashes,
18
+ * and that the provided envelopes are consistent with their respective blocks.
19
+ *
20
+ * Must be called after verifyBlocksSanityChecks so that parentBlock (from forkchoice)
21
+ * is available to seed the execution hash chain.
22
+ *
23
+ * For each block:
24
+ * - Verifies parent root + slot linearity
25
+ * - For gloas: verifies bid.parentBlockHash matches the tracked execution hash; if not, the
26
+ * previous FULL envelope is treated as orphaned (segment continues as if previous slot was EMPTY)
27
+ * - If an envelope exists for this slot: verifies it references this block's root
28
+ * - Advances the tracked execution hash (FULL if envelope present, EMPTY if not)
8
29
  */
30
+ export function assertLinearChainSegment(
31
+ config: ChainForkConfig,
32
+ blocks: IBlockInput[],
33
+ payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
34
+ parentBlock: ProtoBlock
35
+ ): ChainSegmentResult {
36
+ const warnings: OrphanedPayloadEnvelope[] = [];
9
37
 
10
- export function assertLinearChainSegment(config: ChainForkConfig, blocks: IBlockInput[]): void {
11
- for (let i = 0; i < blocks.length - 1; i++) {
38
+ // Track the expected execution payload block hash through the segment.
39
+ // Starts from the known forkchoice parent's execution hash.
40
+ // - FULL variant (envelope present for slot): advances to envelope.payload.blockHash
41
+ // - EMPTY variant (no envelope for slot): execution hash is unchanged
42
+ // null only for pre-merge parents, which cannot precede gloas blocks.
43
+ let currentExecHash: string | null = parentBlock.executionPayloadBlockHash;
44
+ // Track the execution hash before the last FULL advancement so we can recover
45
+ // if the next block reveals that envelope was orphaned.
46
+ let prevExecHash: string | null = currentExecHash;
47
+ // The slot whose envelope last advanced currentExecHash (for warning context).
48
+ let lastFullSlot: Slot | null = null;
49
+
50
+ for (let i = 0; i < blocks.length; i++) {
12
51
  const block = blocks[i].getBlock();
13
- const child = blocks[i + 1].getBlock();
14
- // If this block has a child in this chain segment, ensure that its parent root matches
15
- // the root of this block.
16
- if (
17
- !ssz.Root.equals(
18
- config.getForkTypes(block.message.slot).BeaconBlock.hashTreeRoot(block.message),
19
- child.message.parentRoot
20
- )
21
- ) {
22
- throw new BlockError(block, {code: BlockErrorCode.NON_LINEAR_PARENT_ROOTS});
52
+ const slot = block.message.slot;
53
+
54
+ if (i > 0) {
55
+ const prevBlock = blocks[i - 1].getBlock();
56
+ // Ensure parent root matches the previous block's root
57
+ if (
58
+ !ssz.Root.equals(
59
+ config.getForkTypes(prevBlock.message.slot).BeaconBlock.hashTreeRoot(prevBlock.message),
60
+ block.message.parentRoot
61
+ )
62
+ ) {
63
+ throw new BlockError(block, {code: BlockErrorCode.NON_LINEAR_PARENT_ROOTS});
64
+ }
65
+ // Ensure slots are strictly increasing
66
+ if (slot <= prevBlock.message.slot) {
67
+ throw new BlockError(block, {code: BlockErrorCode.NON_LINEAR_SLOTS});
68
+ }
23
69
  }
24
- // Ensure that the slots are strictly increasing throughout the chain segment.
25
- if (child.message.slot <= block.message.slot) {
26
- throw new BlockError(block, {code: BlockErrorCode.NON_LINEAR_SLOTS});
70
+
71
+ if (isGloasBeaconBlock(block.message) && currentExecHash !== null) {
72
+ // Verify the bid's parentBlockHash matches the tracked execution hash.
73
+ // This ensures the block was built on the correct FULL or EMPTY variant of its parent.
74
+ const bidParentHash = toRootHex(block.message.body.signedExecutionPayloadBid.message.parentBlockHash);
75
+ if (bidParentHash !== currentExecHash) {
76
+ // Maybe the previous slot's FULL envelope was orphaned — try falling back.
77
+ // If even prevExecHash doesn't match, the segment is non-linear.
78
+ if (bidParentHash !== prevExecHash) {
79
+ throw new BlockError(block, {
80
+ code: BlockErrorCode.PARENT_PAYLOAD_UNKNOWN,
81
+ parentRoot: toRootHex(block.message.parentRoot),
82
+ parentBlockHash: bidParentHash,
83
+ });
84
+ }
85
+ if (lastFullSlot !== null && payloadEnvelopes !== null) {
86
+ const orphanedInput = payloadEnvelopes.get(lastFullSlot);
87
+ if (orphanedInput != null) {
88
+ warnings.push({slot: lastFullSlot, payloadEnvelopeInput: orphanedInput});
89
+ }
90
+ }
91
+ currentExecHash = prevExecHash;
92
+ }
93
+
94
+ const payloadInput = payloadEnvelopes?.get(slot) ?? null;
95
+ const payloadEnvelope = payloadInput?.hasPayloadEnvelope() ? payloadInput.getPayloadEnvelope() : null;
96
+ if (payloadEnvelope !== null) {
97
+ // Verify the envelope references this block's root
98
+ const blockRoot = toRootHex(config.getForkTypes(slot).BeaconBlock.hashTreeRoot(block.message));
99
+ const envelopeBlockRoot = toRootHex(payloadEnvelope.message.beaconBlockRoot);
100
+ if (blockRoot !== envelopeBlockRoot) {
101
+ throw new BlockError(block, {
102
+ code: BlockErrorCode.ENVELOPE_BLOCK_ROOT_MISMATCH,
103
+ envelopeBlockRoot,
104
+ blockRoot,
105
+ });
106
+ }
107
+
108
+ // FULL variant: save state before advancing, then advance
109
+ prevExecHash = currentExecHash;
110
+ lastFullSlot = slot;
111
+ currentExecHash = toRootHex(payloadEnvelope.message.payload.blockHash);
112
+ }
113
+ // EMPTY variant: currentExecHash unchanged
27
114
  }
28
115
  }
116
+
117
+ return {warnings: warnings.length > 0 ? warnings : null};
29
118
  }
@@ -1,12 +1,14 @@
1
1
  import {ExecutionStatus, ProtoBlock} from "@lodestar/fork-choice";
2
- import {ForkName, isForkPostFulu} from "@lodestar/params";
2
+ import {ForkName, ForkSeq, isForkPostFulu} from "@lodestar/params";
3
3
  import {DataAvailabilityStatus, IBeaconStateView, computeEpochAtSlot} from "@lodestar/state-transition";
4
- import {IndexedAttestation, deneb} from "@lodestar/types";
4
+ import {IndexedAttestation, Slot, deneb} from "@lodestar/types";
5
+ import {getBlobKzgCommitments} from "../../util/dataColumns.js";
5
6
  import type {BeaconChain} from "../chain.js";
6
7
  import {BlockError, BlockErrorCode} from "../errors/index.js";
7
8
  import {BlockProcessOpts} from "../options.js";
8
9
  import {RegenCaller} from "../regen/index.js";
9
10
  import {DAType, IBlockInput} from "./blockInput/index.js";
11
+ import {PayloadEnvelopeInput} from "./payloadEnvelopeInput/payloadEnvelopeInput.js";
10
12
  import {ImportBlockOpts} from "./types.js";
11
13
  import {DENEB_BLOWFISH_BANNER} from "./utils/blowfishBanner.js";
12
14
  import {ELECTRA_GIRAFFE_BANNER} from "./utils/giraffeBanner.js";
@@ -16,6 +18,7 @@ import {verifyBlocksDataAvailability} from "./verifyBlocksDataAvailability.js";
16
18
  import {SegmentExecStatus, verifyBlocksExecutionPayload} from "./verifyBlocksExecutionPayloads.js";
17
19
  import {verifyBlocksSignatures} from "./verifyBlocksSignatures.js";
18
20
  import {verifyBlocksStateTransitionOnly} from "./verifyBlocksStateTransitionOnly.js";
21
+ import {verifyPayloadsDataAvailability} from "./verifyPayloadsDataAvailability.js";
19
22
 
20
23
  /**
21
24
  * Verifies 1 or more blocks are fully valid; from a linear sequence of blocks.
@@ -32,6 +35,7 @@ export async function verifyBlocksInEpoch(
32
35
  this: BeaconChain,
33
36
  parentBlock: ProtoBlock,
34
37
  blockInputs: IBlockInput[],
38
+ payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
35
39
  opts: BlockProcessOpts & ImportBlockOpts
36
40
  ): Promise<{
37
41
  postStates: IBeaconStateView[];
@@ -110,6 +114,26 @@ export async function verifyBlocksInEpoch(
110
114
  });
111
115
  }
112
116
 
117
+ // Pick the data-availability source by fork:
118
+ // - Pre-Gloas: blob/Fulu-column data lives in IBlockInput → verifyBlocksDataAvailability.
119
+ // - Post-Gloas: verifyPayloadsDataAvailability
120
+ const daAvailabilityPromise =
121
+ fork >= ForkSeq.gloas
122
+ ? (async () => {
123
+ const payloadInputsForDa: PayloadEnvelopeInput[] = [];
124
+ for (const input of blockInputs) {
125
+ const pi = payloadEnvelopes?.get(input.slot);
126
+ if (pi !== undefined) payloadInputsForDa.push(pi);
127
+ }
128
+ await verifyPayloadsDataAvailability(payloadInputsForDa, abortController.signal);
129
+ return {
130
+ // post-gloas, DataAvailabilityStatus is NotRequired for forkChoice.onBlock() ProtoBlock
131
+ dataAvailabilityStatuses: blockInputs.map(() => DataAvailabilityStatus.NotRequired),
132
+ availableTime: Date.now(),
133
+ };
134
+ })()
135
+ : verifyBlocksDataAvailability(blockInputs, abortController.signal);
136
+
113
137
  // batch all I/O operations to reduce overhead
114
138
  const [
115
139
  segmentExecStatus,
@@ -119,8 +143,8 @@ export async function verifyBlocksInEpoch(
119
143
  ] = await Promise.all([
120
144
  verifyExecutionPayloadsPromise,
121
145
 
122
- // data availability for the blobs
123
- verifyBlocksDataAvailability(blockInputs, abortController.signal),
146
+ // data availability (fork-specific; see daAvailabilityPromise above)
147
+ daAvailabilityPromise,
124
148
 
125
149
  // Run state transition only
126
150
  // TODO: Ensure it yields to allow flushing to workers and engine API
@@ -149,6 +173,9 @@ export async function verifyBlocksInEpoch(
149
173
  opts
150
174
  )
151
175
  : Promise.resolve({verifySignaturesTime: Date.now()}),
176
+
177
+ // TODO GLOAS: can verify payload signatures in batch too
178
+ // maybe chain with the above verifyBlocksSignatures()
152
179
  ]);
153
180
 
154
181
  if (opts.verifyOnly !== true) {
@@ -200,7 +227,9 @@ export async function verifyBlocksInEpoch(
200
227
  blockInputs.length === 1 &&
201
228
  // gossip blocks have seenTimestampSec
202
229
  opts.seenTimestampSec !== undefined &&
230
+ // PreData (pre-deneb) and NoData (gloas) carry no blob data on the block — skip metric
203
231
  blockInputs[0].type !== DAType.PreData &&
232
+ blockInputs[0].type !== DAType.NoData &&
204
233
  executionStatuses[0] === ExecutionStatus.Valid
205
234
  ) {
206
235
  // Find the max time when the block was actually verified
@@ -209,8 +238,8 @@ export async function verifyBlocksInEpoch(
209
238
  this.metrics?.gossipBlock.receivedToFullyVerifiedTime.observe(recvTofullyVerifedTime);
210
239
 
211
240
  const verifiedToBlobsAvailabiltyTime = Math.max(availableTime - fullyVerifiedTime, 0) / 1000;
212
- const block = blockInputs[0].getBlock() as deneb.SignedBeaconBlock;
213
- const numBlobs = block.message.body.blobKzgCommitments.length;
241
+ const block = blockInputs[0].getBlock();
242
+ const numBlobs = getBlobKzgCommitments(blockInputs[0].forkName, block as deneb.SignedBeaconBlock).length;
214
243
 
215
244
  this.metrics?.gossipBlock.verifiedToBlobsAvailabiltyTime.observe({numBlobs}, verifiedToBlobsAvailabiltyTime);
216
245
  this.logger.verbose("Verified blockInput fully with blobs availability", {
@@ -90,15 +90,24 @@ export function verifyBlocksSanityChecks(
90
90
  } else {
91
91
  // When importing a block segment, only the first NON-IGNORED block must be known to the fork-choice.
92
92
  const parentRoot = toRootHex(block.message.parentRoot);
93
- parentBlock = isGloasBeaconBlock(block.message)
94
- ? chain.forkChoice.getBlockHexAndBlockHash(
95
- parentRoot,
96
- toRootHex(block.message.body.signedExecutionPayloadBid.message.parentBlockHash)
97
- )
98
- : chain.forkChoice.getBlockHexDefaultStatus(parentRoot);
99
- if (!parentBlock) {
93
+ const parentBlockDefaultStatus = chain.forkChoice.getBlockHexDefaultStatus(parentRoot);
94
+ if (!parentBlockDefaultStatus) {
100
95
  throw new BlockError(block, {code: BlockErrorCode.PARENT_UNKNOWN, parentRoot});
101
96
  }
97
+
98
+ parentBlock = parentBlockDefaultStatus;
99
+ if (isGloasBeaconBlock(block.message)) {
100
+ const parentBlockHash = toRootHex(block.message.body.signedExecutionPayloadBid.message.parentBlockHash);
101
+ const parentBlockWithPayload = chain.forkChoice.getBlockHexAndBlockHash(parentRoot, parentBlockHash);
102
+ if (!parentBlockWithPayload) {
103
+ throw new BlockError(block, {
104
+ code: BlockErrorCode.PARENT_PAYLOAD_UNKNOWN,
105
+ parentRoot,
106
+ parentBlockHash,
107
+ });
108
+ }
109
+ parentBlock = parentBlockWithPayload;
110
+ }
102
111
  // Parent is known to the fork-choice
103
112
  parentBlockSlot = parentBlock.slot;
104
113
  }
@@ -0,0 +1,129 @@
1
+ import {BeaconConfig} from "@lodestar/config";
2
+ import {
3
+ type IBeaconStateViewGloas,
4
+ type PubkeyCache,
5
+ computeTimeAtSlot,
6
+ getExecutionPayloadEnvelopeSignatureSet,
7
+ } from "@lodestar/state-transition";
8
+ import {gloas, ssz} from "@lodestar/types";
9
+ import {byteArrayEquals, toHex, toRootHex} from "@lodestar/utils";
10
+ import {IBlsVerifier} from "../bls/index.js";
11
+
12
+ export type VerifyExecutionPayloadEnvelopeOpts = {
13
+ verifyExecutionRequestsRoot?: boolean;
14
+ };
15
+
16
+ /**
17
+ * Verify execution payload envelope fields against the post-block state.
18
+ *
19
+ * Signature verification and the execution engine call (`verify_and_notify_new_payload`) are
20
+ * performed outside this function, see `verifyExecutionPayloadEnvelopeSignature` and
21
+ * `importExecutionPayload` which run both in parallel with this check.
22
+ *
23
+ * Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.5/specs/gloas/fork-choice.md#new-verify_execution_payload_envelope
24
+ */
25
+ export function verifyExecutionPayloadEnvelope(
26
+ config: BeaconConfig,
27
+ state: IBeaconStateViewGloas,
28
+ envelope: gloas.ExecutionPayloadEnvelope,
29
+ opts?: VerifyExecutionPayloadEnvelopeOpts
30
+ ): void {
31
+ const {verifyExecutionRequestsRoot = true} = opts ?? {};
32
+ const payload = envelope.payload;
33
+
34
+ // Verify consistency with the beacon block.
35
+ // Compute header root on a clone of latestBlockHeader to avoid mutating state.
36
+ const headerValue = ssz.phase0.BeaconBlockHeader.clone(state.latestBlockHeader);
37
+ if (byteArrayEquals(headerValue.stateRoot, ssz.Root.defaultValue())) {
38
+ headerValue.stateRoot = state.hashTreeRoot();
39
+ }
40
+ const headerRoot = ssz.phase0.BeaconBlockHeader.hashTreeRoot(headerValue);
41
+ if (!byteArrayEquals(envelope.beaconBlockRoot, headerRoot)) {
42
+ throw new Error(
43
+ `Envelope's block is not the latest block header envelope=${toRootHex(envelope.beaconBlockRoot)} latestBlockHeader=${toRootHex(headerRoot)}`
44
+ );
45
+ }
46
+
47
+ // Verify consistency with the committed bid
48
+ const bid = state.latestExecutionPayloadBid;
49
+ if (envelope.builderIndex !== bid.builderIndex) {
50
+ throw new Error(
51
+ `Builder index mismatch between envelope and committed bid envelope=${envelope.builderIndex} bid=${bid.builderIndex}`
52
+ );
53
+ }
54
+ if (!byteArrayEquals(bid.prevRandao, payload.prevRandao)) {
55
+ throw new Error(
56
+ `Prev randao mismatch between bid and payload bid=${toHex(bid.prevRandao)} payload=${toHex(payload.prevRandao)}`
57
+ );
58
+ }
59
+ if (Number(bid.gasLimit) !== payload.gasLimit) {
60
+ throw new Error(
61
+ `Gas limit mismatch between payload and bid payload=${payload.gasLimit} bid=${Number(bid.gasLimit)}`
62
+ );
63
+ }
64
+ if (!byteArrayEquals(bid.blockHash, payload.blockHash)) {
65
+ throw new Error(
66
+ `Block hash mismatch between payload and bid payload=${toRootHex(payload.blockHash)} bid=${toRootHex(bid.blockHash)}`
67
+ );
68
+ }
69
+ // Verify execution_requests_root matches bid commitment.
70
+ // Can be skipped if already verified during gossip validation.
71
+ if (verifyExecutionRequestsRoot) {
72
+ const requestsRoot = ssz.electra.ExecutionRequests.hashTreeRoot(envelope.executionRequests);
73
+ if (!byteArrayEquals(requestsRoot, bid.executionRequestsRoot)) {
74
+ throw new Error(
75
+ `Execution requests root mismatch envelope=${toRootHex(requestsRoot)} bid=${toRootHex(bid.executionRequestsRoot)}`
76
+ );
77
+ }
78
+ }
79
+
80
+ // Verify the execution payload is valid
81
+ if (payload.slotNumber !== state.slot) {
82
+ throw new Error(`Slot mismatch between payload and state payload=${payload.slotNumber} state=${state.slot}`);
83
+ }
84
+ if (!byteArrayEquals(payload.parentHash, state.latestBlockHash)) {
85
+ throw new Error(
86
+ `Parent hash mismatch between payload and state payload=${toRootHex(payload.parentHash)} state=${toRootHex(state.latestBlockHash)}`
87
+ );
88
+ }
89
+ const expectedTimestamp = computeTimeAtSlot(config, state.slot, state.genesisTime);
90
+ if (payload.timestamp !== expectedTimestamp) {
91
+ throw new Error(
92
+ `Timestamp mismatch between payload and state payload=${payload.timestamp} state=${expectedTimestamp}`
93
+ );
94
+ }
95
+
96
+ // Verify consistency with expected withdrawals
97
+ const payloadWithdrawalsRoot = ssz.capella.Withdrawals.hashTreeRoot(payload.withdrawals);
98
+ const expectedWithdrawalsRoot = ssz.capella.Withdrawals.hashTreeRoot(state.payloadExpectedWithdrawals);
99
+ if (!byteArrayEquals(payloadWithdrawalsRoot, expectedWithdrawalsRoot)) {
100
+ throw new Error(
101
+ `Withdrawals mismatch between payload and expected payload=${toRootHex(payloadWithdrawalsRoot)} expected=${toRootHex(expectedWithdrawalsRoot)}`
102
+ );
103
+ }
104
+
105
+ // Execution engine verification (verify_and_notify_new_payload) is done externally by the caller
106
+ }
107
+
108
+ /**
109
+ * Verify the BLS signature of an execution payload envelope.
110
+ *
111
+ * Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.5/specs/gloas/fork-choice.md#new-verify_execution_payload_envelope_signature
112
+ */
113
+ export async function verifyExecutionPayloadEnvelopeSignature(
114
+ config: BeaconConfig,
115
+ state: IBeaconStateViewGloas,
116
+ pubkeyCache: PubkeyCache,
117
+ signedEnvelope: gloas.SignedExecutionPayloadEnvelope,
118
+ proposerIndex: number,
119
+ bls: IBlsVerifier
120
+ ): Promise<boolean> {
121
+ const signatureSet = getExecutionPayloadEnvelopeSignatureSet(
122
+ config,
123
+ pubkeyCache,
124
+ state,
125
+ signedEnvelope,
126
+ proposerIndex
127
+ );
128
+ return bls.verifySignatureSets([signatureSet]);
129
+ }
@@ -0,0 +1,38 @@
1
+ import {DataAvailabilityStatus} from "@lodestar/state-transition";
2
+ import {gloas} from "@lodestar/types";
3
+ import {PayloadEnvelopeInput} from "../seenCache/seenPayloadEnvelopeInput.js";
4
+
5
+ // we can now wait for full 12 seconds because sync and reconstruction will try pulling
6
+ // the data columns from the network anyway while the envelope is being processed
7
+ export const PAYLOAD_DATA_AVAILABILITY_TIMEOUT = 12_000;
8
+
9
+ /**
10
+ * Verifies that all payload envelope inputs have their data columns available.
11
+ * - Waits a max of PAYLOAD_DATA_AVAILABILITY_TIMEOUT for all data to be available
12
+ * - Returns the time at which all data was available
13
+ * - Returns the data availability status for each payload input
14
+ */
15
+ export async function verifyPayloadsDataAvailability(
16
+ payloadInputs: PayloadEnvelopeInput[],
17
+ signal: AbortSignal
18
+ ): Promise<{
19
+ dataAvailabilityStatuses: DataAvailabilityStatus[];
20
+ availableTime: number;
21
+ }> {
22
+ const promises: Promise<gloas.DataColumnSidecar[]>[] = [];
23
+ for (const payloadInput of payloadInputs) {
24
+ if (!payloadInput.hasAllData()) {
25
+ promises.push(payloadInput.waitForAllData(PAYLOAD_DATA_AVAILABILITY_TIMEOUT, signal));
26
+ }
27
+ }
28
+ await Promise.all(promises);
29
+
30
+ const availableTime = Math.max(0, Math.max(...payloadInputs.map((payloadInput) => payloadInput.getTimeComplete())));
31
+ const dataAvailabilityStatuses: DataAvailabilityStatus[] = payloadInputs.map((payloadInput) =>
32
+ payloadInput.getBlobKzgCommitments().length === 0
33
+ ? DataAvailabilityStatus.NotRequired
34
+ : DataAvailabilityStatus.Available
35
+ );
36
+
37
+ return {dataAvailabilityStatuses, availableTime};
38
+ }
@@ -5,7 +5,7 @@ import {writeDataColumnsToDb} from "./writeBlockInputToDb.js";
5
5
  /**
6
6
  * Persists payload envelope data to DB. This operation must be eventually completed if a payload is imported.
7
7
  *
8
- * TODO GLOAS: Persist envelope metadata (stateRoot, executionRequests, builderIndex, etc.) without the full
8
+ * TODO GLOAS: Persist envelope metadata (executionRequests, builderIndex, etc.) without the full
9
9
  * execution payload body — only keep the blockHash reference. The EL already stores the payload.
10
10
  * See https://github.com/ChainSafe/lodestar/issues/5671
11
11
  */
@@ -33,23 +33,14 @@ export async function persistPayloadEnvelopeInput(
33
33
  this: BeaconChain,
34
34
  payloadInput: PayloadEnvelopeInput
35
35
  ): Promise<void> {
36
- await writePayloadEnvelopeInputToDb
37
- .call(this, payloadInput)
38
- .catch((e) => {
39
- this.logger.error(
40
- "Error persisting payload envelope in hot db",
41
- {
42
- slot: payloadInput.slot,
43
- root: payloadInput.blockRootHex,
44
- },
45
- e
46
- );
47
- })
48
- .finally(() => {
49
- this.seenPayloadEnvelopeInputCache.prune(payloadInput.blockRootHex);
50
- this.logger.debug("Pruned payload envelope input", {
36
+ await writePayloadEnvelopeInputToDb.call(this, payloadInput).catch((e) => {
37
+ this.logger.error(
38
+ "Error persisting payload envelope in hot db",
39
+ {
51
40
  slot: payloadInput.slot,
52
41
  root: payloadInput.blockRootHex,
53
- });
54
- });
42
+ },
43
+ e
44
+ );
45
+ });
55
46
  }
@@ -2,7 +2,7 @@ import path from "node:path";
2
2
  import {PrivateKey} from "@libp2p/interface";
3
3
  import {Type} from "@chainsafe/ssz";
4
4
  import {BeaconConfig} from "@lodestar/config";
5
- import {CheckpointWithPayloadStatus, IForkChoice, ProtoBlock, UpdateHeadOpt} from "@lodestar/fork-choice";
5
+ import {CheckpointWithHex, IForkChoice, ProtoBlock, UpdateHeadOpt} from "@lodestar/fork-choice";
6
6
  import {LoggerNode} from "@lodestar/logger/node";
7
7
  import {
8
8
  EFFECTIVE_BALANCE_INCREMENT,
@@ -39,6 +39,7 @@ import {
39
39
  ValidatorIndex,
40
40
  Wei,
41
41
  deneb,
42
+ electra,
42
43
  gloas,
43
44
  isBlindedBeaconBlock,
44
45
  phase0,
@@ -105,6 +106,7 @@ import {
105
106
  SeenExecutionPayloadBids,
106
107
  SeenPayloadAttesters,
107
108
  SeenPayloadEnvelopeInput,
109
+ SeenProposerPreferences,
108
110
  SeenSyncCommitteeMessages,
109
111
  } from "./seenCache/index.js";
110
112
  import {SeenAggregatedAttestations} from "./seenCache/seenAggregateAndProof.js";
@@ -185,6 +187,7 @@ export class BeaconChain implements IBeaconChain {
185
187
  readonly seenPayloadAttesters = new SeenPayloadAttesters();
186
188
  readonly seenAggregatedAttestations: SeenAggregatedAttestations;
187
189
  readonly seenExecutionPayloadBids = new SeenExecutionPayloadBids();
190
+ readonly seenProposerPreferences = new SeenProposerPreferences();
188
191
  readonly seenBlockProposers = new SeenBlockProposers();
189
192
  readonly seenSyncCommitteeMessages = new SeenSyncCommitteeMessages();
190
193
  readonly seenContributionAndProof: SeenContributionAndProof;
@@ -680,7 +683,7 @@ export class BeaconChain implements IBeaconChain {
680
683
  }
681
684
 
682
685
  getStateByCheckpoint(
683
- checkpoint: CheckpointWithPayloadStatus
686
+ checkpoint: CheckpointWithHex
684
687
  ): {state: IBeaconStateView; executionOptimistic: boolean; finalized: boolean} | null {
685
688
  // finalized or justified checkpoint states maynot be available with PersistentCheckpointStateCache, use getCheckpointStateOrBytes() api to get Uint8Array
686
689
  const checkpointHex = {epoch: checkpoint.epoch, rootHex: checkpoint.rootHex};
@@ -701,7 +704,7 @@ export class BeaconChain implements IBeaconChain {
701
704
  }
702
705
 
703
706
  async getStateOrBytesByCheckpoint(
704
- checkpoint: CheckpointWithPayloadStatus
707
+ checkpoint: CheckpointWithHex
705
708
  ): Promise<{state: IBeaconStateView | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null> {
706
709
  const checkpointHex = {epoch: checkpoint.epoch, rootHex: checkpoint.rootHex};
707
710
  const cachedStateCtx = await this.regen.getCheckpointStateOrBytes(checkpointHex);
@@ -886,6 +889,21 @@ export class BeaconChain implements IBeaconChain {
886
889
  );
887
890
  }
888
891
 
892
+ async getParentExecutionRequests(
893
+ parentBlockSlot: Slot,
894
+ parentBlockRootHex: RootHex
895
+ ): Promise<electra.ExecutionRequests> {
896
+ // at the fork boundary, parent is pre-gloas
897
+ if (!isForkPostGloas(this.config.getForkName(parentBlockSlot))) {
898
+ return ssz.electra.ExecutionRequests.defaultValue();
899
+ }
900
+ const envelope = await this.getExecutionPayloadEnvelope(parentBlockSlot, parentBlockRootHex);
901
+ if (envelope === null) {
902
+ throw Error(`Parent execution payload envelope not found slot=${parentBlockSlot}, root=${parentBlockRootHex}`);
903
+ }
904
+ return envelope.message.executionRequests;
905
+ }
906
+
889
907
  async getDataColumnSidecars(blockSlot: Slot, blockRootHex: string): Promise<DataColumnSidecar[]> {
890
908
  const fork = this.config.getForkName(blockSlot);
891
909
 
@@ -1082,11 +1100,15 @@ export class BeaconChain implements IBeaconChain {
1082
1100
  }
1083
1101
 
1084
1102
  async processBlock(block: IBlockInput, opts?: ImportBlockOpts): Promise<void> {
1085
- return this.blockProcessor.processBlocksJob([block], opts);
1103
+ return this.blockProcessor.processBlocksJob([block], null, opts);
1086
1104
  }
1087
1105
 
1088
- async processChainSegment(blocks: IBlockInput[], opts?: ImportBlockOpts): Promise<void> {
1089
- return this.blockProcessor.processBlocksJob(blocks, opts);
1106
+ async processChainSegment(
1107
+ blocks: IBlockInput[],
1108
+ payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
1109
+ opts?: ImportBlockOpts
1110
+ ): Promise<void> {
1111
+ await this.blockProcessor.processBlocksJob(blocks, payloadEnvelopes, opts);
1090
1112
  }
1091
1113
 
1092
1114
  async processExecutionPayload(payloadInput: PayloadEnvelopeInput, opts?: ImportPayloadOpts): Promise<void> {
@@ -1277,7 +1299,7 @@ export class BeaconChain implements IBeaconChain {
1277
1299
  * @param blockState state that declares justified checkpoint `checkpoint`
1278
1300
  */
1279
1301
  private justifiedBalancesGetter(
1280
- checkpoint: CheckpointWithPayloadStatus,
1302
+ checkpoint: CheckpointWithHex,
1281
1303
  blockState: IBeaconStateView
1282
1304
  ): EffectiveBalanceIncrements {
1283
1305
  this.metrics?.balancesCache.requests.inc();
@@ -1316,7 +1338,7 @@ export class BeaconChain implements IBeaconChain {
1316
1338
  * @param blockState state that declares justified checkpoint `checkpoint`
1317
1339
  */
1318
1340
  private closestJustifiedBalancesStateToCheckpoint(
1319
- checkpoint: CheckpointWithPayloadStatus,
1341
+ checkpoint: CheckpointWithHex,
1320
1342
  blockState: IBeaconStateView
1321
1343
  ): {state: IBeaconStateView; stateId: string; shouldWarn: boolean} {
1322
1344
  const checkpointHex = {epoch: checkpoint.epoch, rootHex: checkpoint.rootHex};
@@ -1331,10 +1353,7 @@ export class BeaconChain implements IBeaconChain {
1331
1353
  }
1332
1354
 
1333
1355
  // Find a state in the same branch of checkpoint at same epoch. Balances should exactly the same
1334
- for (const descendantBlock of this.forkChoice.forwardIterateDescendants(
1335
- checkpoint.rootHex,
1336
- checkpoint.payloadStatus
1337
- )) {
1356
+ for (const descendantBlock of this.forkChoice.forwardIterateDescendantsDefaultStatus(checkpoint.rootHex)) {
1338
1357
  if (computeEpochAtSlot(descendantBlock.slot) === checkpoint.epoch) {
1339
1358
  const descendantBlockState = this.regen.getStateSync(descendantBlock.stateRoot);
1340
1359
  if (descendantBlockState) {
@@ -1350,10 +1369,7 @@ export class BeaconChain implements IBeaconChain {
1350
1369
 
1351
1370
  // Find a state in the same branch of checkpoint at a latter epoch. Balances are not the same, but should be close
1352
1371
  // Note: must call .forwardIterateDescendants() again since nodes are not sorted
1353
- for (const descendantBlock of this.forkChoice.forwardIterateDescendants(
1354
- checkpoint.rootHex,
1355
- checkpoint.payloadStatus
1356
- )) {
1372
+ for (const descendantBlock of this.forkChoice.forwardIterateDescendantsDefaultStatus(checkpoint.rootHex)) {
1357
1373
  if (computeEpochAtSlot(descendantBlock.slot) > checkpoint.epoch) {
1358
1374
  const descendantBlockState = this.regen.getStateSync(descendantBlock.stateRoot);
1359
1375
  if (descendantBlockState) {
@@ -1423,6 +1439,7 @@ export class BeaconChain implements IBeaconChain {
1423
1439
  this.payloadAttestationPool.prune(slot);
1424
1440
  this.executionPayloadBidPool.prune(slot);
1425
1441
  this.seenExecutionPayloadBids.prune(slot);
1442
+ this.seenProposerPreferences.prune(slot);
1426
1443
  this.seenAttestationDatas.onSlot(slot);
1427
1444
  this.reprocessController.onSlot(slot);
1428
1445
 
@@ -1457,7 +1474,7 @@ export class BeaconChain implements IBeaconChain {
1457
1474
  this.seenContributionAndProof.prune(head.slot);
1458
1475
  }
1459
1476
 
1460
- private onForkChoiceJustified(this: BeaconChain, cp: CheckpointWithPayloadStatus): void {
1477
+ private onForkChoiceJustified(this: BeaconChain, cp: CheckpointWithHex): void {
1461
1478
  this.logger.verbose("Fork choice justified", {epoch: cp.epoch, root: cp.rootHex});
1462
1479
  }
1463
1480
 
@@ -1468,7 +1485,7 @@ export class BeaconChain implements IBeaconChain {
1468
1485
  });
1469
1486
  }
1470
1487
 
1471
- private async onForkChoiceFinalized(this: BeaconChain, cp: CheckpointWithPayloadStatus): Promise<void> {
1488
+ private async onForkChoiceFinalized(this: BeaconChain, cp: CheckpointWithHex): Promise<void> {
1472
1489
  this.logger.verbose("Fork choice finalized", {epoch: cp.epoch, root: cp.rootHex});
1473
1490
  const finalizedSlot = computeStartSlotAtEpoch(cp.epoch);
1474
1491
  this.seenBlockProposers.prune(finalizedSlot);
@@ -1509,7 +1526,7 @@ export class BeaconChain implements IBeaconChain {
1509
1526
  }
1510
1527
  }
1511
1528
 
1512
- private async updateValidatorsCustodyRequirement(finalizedCheckpoint: CheckpointWithPayloadStatus): Promise<void> {
1529
+ private async updateValidatorsCustodyRequirement(finalizedCheckpoint: CheckpointWithHex): Promise<void> {
1513
1530
  if (this.custodyConfig.targetCustodyGroupCount === this.config.NUMBER_OF_CUSTODY_GROUPS) {
1514
1531
  // Custody requirements can only be increased, we can disable dynamic custody updates
1515
1532
  // if the node already maintains custody of all custody groups in case it is configured