@lodestar/beacon-node 1.43.0-dev.4fb05c546d → 1.43.0-dev.549a5b8115

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 (305) 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/pool/index.d.ts.map +1 -1
  4. package/lib/api/impl/beacon/pool/index.js +45 -2
  5. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  6. package/lib/api/impl/beacon/state/utils.d.ts +2 -2
  7. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  8. package/lib/api/impl/beacon/state/utils.js.map +1 -1
  9. package/lib/api/impl/lodestar/index.js +1 -1
  10. package/lib/api/impl/lodestar/index.js.map +1 -1
  11. package/lib/api/impl/validator/index.d.ts.map +1 -1
  12. package/lib/api/impl/validator/index.js +66 -5
  13. package/lib/api/impl/validator/index.js.map +1 -1
  14. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  15. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  16. package/lib/chain/archiveStore/interface.d.ts +4 -4
  17. package/lib/chain/archiveStore/interface.d.ts.map +1 -1
  18. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts +4 -4
  19. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts.map +1 -1
  20. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js.map +1 -1
  21. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +2 -2
  22. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
  23. package/lib/chain/archiveStore/utils/archiveBlocks.js +110 -58
  24. package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
  25. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  26. package/lib/chain/blocks/importBlock.js +3 -2
  27. package/lib/chain/blocks/importBlock.js.map +1 -1
  28. package/lib/chain/blocks/importExecutionPayload.d.ts +28 -14
  29. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  30. package/lib/chain/blocks/importExecutionPayload.js +86 -86
  31. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  32. package/lib/chain/blocks/index.d.ts +5 -3
  33. package/lib/chain/blocks/index.d.ts.map +1 -1
  34. package/lib/chain/blocks/index.js +31 -11
  35. package/lib/chain/blocks/index.js.map +1 -1
  36. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +1 -0
  37. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
  38. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +4 -1
  39. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
  40. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +1 -0
  41. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
  42. package/lib/chain/blocks/payloadEnvelopeProcessor.js +2 -2
  43. package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
  44. package/lib/chain/blocks/types.d.ts +14 -20
  45. package/lib/chain/blocks/types.d.ts.map +1 -1
  46. package/lib/chain/blocks/utils/chainSegment.d.ts +23 -2
  47. package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
  48. package/lib/chain/blocks/utils/chainSegment.js +81 -12
  49. package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
  50. package/lib/chain/blocks/verifyBlock.d.ts +5 -3
  51. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  52. package/lib/chain/blocks/verifyBlock.js +51 -7
  53. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  54. package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
  55. package/lib/chain/blocks/verifyBlocksSanityChecks.js +15 -4
  56. package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
  57. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +24 -0
  58. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -0
  59. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +76 -0
  60. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -0
  61. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -1
  62. package/lib/chain/blocks/verifyPayloadsDataAvailability.js +8 -3
  63. package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -1
  64. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts +1 -1
  65. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts.map +1 -1
  66. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js +2 -11
  67. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js.map +1 -1
  68. package/lib/chain/chain.d.ts +8 -6
  69. package/lib/chain/chain.d.ts.map +1 -1
  70. package/lib/chain/chain.js +21 -6
  71. package/lib/chain/chain.js.map +1 -1
  72. package/lib/chain/emitter.d.ts +3 -3
  73. package/lib/chain/emitter.d.ts.map +1 -1
  74. package/lib/chain/errors/blockError.d.ts +8 -1
  75. package/lib/chain/errors/blockError.d.ts.map +1 -1
  76. package/lib/chain/errors/blockError.js +2 -0
  77. package/lib/chain/errors/blockError.js.map +1 -1
  78. package/lib/chain/errors/executionPayloadBid.d.ts +5 -0
  79. package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
  80. package/lib/chain/errors/executionPayloadBid.js +1 -0
  81. package/lib/chain/errors/executionPayloadBid.js.map +1 -1
  82. package/lib/chain/errors/executionPayloadEnvelope.d.ts +5 -0
  83. package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
  84. package/lib/chain/errors/executionPayloadEnvelope.js +1 -0
  85. package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
  86. package/lib/chain/errors/index.d.ts +1 -0
  87. package/lib/chain/errors/index.d.ts.map +1 -1
  88. package/lib/chain/errors/index.js +1 -0
  89. package/lib/chain/errors/index.js.map +1 -1
  90. package/lib/chain/errors/proposerPreferences.d.ts +33 -0
  91. package/lib/chain/errors/proposerPreferences.d.ts.map +1 -0
  92. package/lib/chain/errors/proposerPreferences.js +13 -0
  93. package/lib/chain/errors/proposerPreferences.js.map +1 -0
  94. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  95. package/lib/chain/forkChoice/index.js +5 -17
  96. package/lib/chain/forkChoice/index.js.map +1 -1
  97. package/lib/chain/interface.d.ts +7 -5
  98. package/lib/chain/interface.d.ts.map +1 -1
  99. package/lib/chain/interface.js.map +1 -1
  100. package/lib/chain/opPools/payloadAttestationPool.d.ts +3 -2
  101. package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -1
  102. package/lib/chain/opPools/payloadAttestationPool.js +26 -4
  103. package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
  104. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  105. package/lib/chain/prepareNextSlot.js +30 -10
  106. package/lib/chain/prepareNextSlot.js.map +1 -1
  107. package/lib/chain/produceBlock/produceBlockBody.d.ts +3 -2
  108. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  109. package/lib/chain/produceBlock/produceBlockBody.js +40 -15
  110. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  111. package/lib/chain/regen/interface.d.ts +1 -0
  112. package/lib/chain/regen/interface.d.ts.map +1 -1
  113. package/lib/chain/regen/interface.js +1 -0
  114. package/lib/chain/regen/interface.js.map +1 -1
  115. package/lib/chain/seenCache/index.d.ts +1 -0
  116. package/lib/chain/seenCache/index.d.ts.map +1 -1
  117. package/lib/chain/seenCache/index.js +1 -0
  118. package/lib/chain/seenCache/index.js.map +1 -1
  119. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +19 -6
  120. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
  121. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +28 -20
  122. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
  123. package/lib/chain/seenCache/seenProposerPreferences.d.ts +15 -0
  124. package/lib/chain/seenCache/seenProposerPreferences.d.ts.map +1 -0
  125. package/lib/chain/seenCache/seenProposerPreferences.js +25 -0
  126. package/lib/chain/seenCache/seenProposerPreferences.js.map +1 -0
  127. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  128. package/lib/chain/stateCache/persistentCheckpointsCache.js +4 -1
  129. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  130. package/lib/chain/validation/block.d.ts.map +1 -1
  131. package/lib/chain/validation/block.js +1 -0
  132. package/lib/chain/validation/block.js.map +1 -1
  133. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  134. package/lib/chain/validation/executionPayloadBid.js +13 -1
  135. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  136. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  137. package/lib/chain/validation/executionPayloadEnvelope.js +19 -9
  138. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  139. package/lib/chain/validation/proposerPreferences.d.ts +8 -0
  140. package/lib/chain/validation/proposerPreferences.d.ts.map +1 -0
  141. package/lib/chain/validation/proposerPreferences.js +69 -0
  142. package/lib/chain/validation/proposerPreferences.js.map +1 -0
  143. package/lib/db/repositories/executionPayloadEnvelopeArchive.js +1 -1
  144. package/lib/db/repositories/executionPayloadEnvelopeArchive.js.map +1 -1
  145. package/lib/execution/engine/http.d.ts.map +1 -1
  146. package/lib/execution/engine/http.js +21 -14
  147. package/lib/execution/engine/http.js.map +1 -1
  148. package/lib/execution/engine/interface.d.ts +1 -0
  149. package/lib/execution/engine/interface.d.ts.map +1 -1
  150. package/lib/execution/engine/mock.d.ts.map +1 -1
  151. package/lib/execution/engine/mock.js +6 -0
  152. package/lib/execution/engine/mock.js.map +1 -1
  153. package/lib/execution/engine/types.d.ts +20 -0
  154. package/lib/execution/engine/types.d.ts.map +1 -1
  155. package/lib/execution/engine/types.js +18 -0
  156. package/lib/execution/engine/types.js.map +1 -1
  157. package/lib/metrics/metrics/lodestar.d.ts +1 -0
  158. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  159. package/lib/metrics/metrics/lodestar.js +4 -0
  160. package/lib/metrics/metrics/lodestar.js.map +1 -1
  161. package/lib/network/gossip/interface.d.ts +7 -1
  162. package/lib/network/gossip/interface.d.ts.map +1 -1
  163. package/lib/network/gossip/interface.js +1 -0
  164. package/lib/network/gossip/interface.js.map +1 -1
  165. package/lib/network/gossip/scoringParameters.d.ts.map +1 -1
  166. package/lib/network/gossip/scoringParameters.js +12 -1
  167. package/lib/network/gossip/scoringParameters.js.map +1 -1
  168. package/lib/network/gossip/topic.d.ts +11 -2
  169. package/lib/network/gossip/topic.d.ts.map +1 -1
  170. package/lib/network/gossip/topic.js +6 -0
  171. package/lib/network/gossip/topic.js.map +1 -1
  172. package/lib/network/interface.d.ts +1 -0
  173. package/lib/network/interface.d.ts.map +1 -1
  174. package/lib/network/network.d.ts +1 -0
  175. package/lib/network/network.d.ts.map +1 -1
  176. package/lib/network/network.js +6 -1
  177. package/lib/network/network.js.map +1 -1
  178. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  179. package/lib/network/processor/gossipHandlers.js +17 -12
  180. package/lib/network/processor/gossipHandlers.js.map +1 -1
  181. package/lib/network/processor/gossipQueues/index.d.ts.map +1 -1
  182. package/lib/network/processor/gossipQueues/index.js +5 -0
  183. package/lib/network/processor/gossipQueues/index.js.map +1 -1
  184. package/lib/network/processor/index.d.ts.map +1 -1
  185. package/lib/network/processor/index.js +1 -0
  186. package/lib/network/processor/index.js.map +1 -1
  187. package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
  188. package/lib/network/reqresp/handlers/beaconBlocksByRange.js +14 -6
  189. package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
  190. package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts.map +1 -1
  191. package/lib/network/reqresp/handlers/blobSidecarsByRange.js +11 -5
  192. package/lib/network/reqresp/handlers/blobSidecarsByRange.js.map +1 -1
  193. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
  194. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +17 -5
  195. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
  196. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -1
  197. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +7 -4
  198. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
  199. package/lib/node/notifier.js +7 -1
  200. package/lib/node/notifier.js.map +1 -1
  201. package/lib/sync/range/batch.d.ts +12 -2
  202. package/lib/sync/range/batch.d.ts.map +1 -1
  203. package/lib/sync/range/batch.js +56 -30
  204. package/lib/sync/range/batch.js.map +1 -1
  205. package/lib/sync/range/chain.d.ts +6 -2
  206. package/lib/sync/range/chain.d.ts.map +1 -1
  207. package/lib/sync/range/chain.js +4 -3
  208. package/lib/sync/range/chain.js.map +1 -1
  209. package/lib/sync/range/range.d.ts.map +1 -1
  210. package/lib/sync/range/range.js +17 -6
  211. package/lib/sync/range/range.js.map +1 -1
  212. package/lib/sync/types.d.ts +34 -0
  213. package/lib/sync/types.d.ts.map +1 -1
  214. package/lib/sync/types.js +34 -0
  215. package/lib/sync/types.js.map +1 -1
  216. package/lib/sync/unknownBlock.d.ts +24 -1
  217. package/lib/sync/unknownBlock.d.ts.map +1 -1
  218. package/lib/sync/unknownBlock.js +649 -53
  219. package/lib/sync/unknownBlock.js.map +1 -1
  220. package/lib/sync/utils/downloadByRange.d.ts +46 -10
  221. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  222. package/lib/sync/utils/downloadByRange.js +147 -24
  223. package/lib/sync/utils/downloadByRange.js.map +1 -1
  224. package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
  225. package/lib/sync/utils/downloadByRoot.js +6 -2
  226. package/lib/sync/utils/downloadByRoot.js.map +1 -1
  227. package/lib/sync/utils/pendingBlocksTree.d.ts +0 -1
  228. package/lib/sync/utils/pendingBlocksTree.d.ts.map +1 -1
  229. package/lib/sync/utils/pendingBlocksTree.js +0 -9
  230. package/lib/sync/utils/pendingBlocksTree.js.map +1 -1
  231. package/lib/util/sszBytes.d.ts.map +1 -1
  232. package/lib/util/sszBytes.js +16 -3
  233. package/lib/util/sszBytes.js.map +1 -1
  234. package/package.json +16 -15
  235. package/src/api/impl/beacon/blocks/index.ts +9 -9
  236. package/src/api/impl/beacon/pool/index.ts +83 -1
  237. package/src/api/impl/beacon/state/utils.ts +2 -2
  238. package/src/api/impl/lodestar/index.ts +1 -1
  239. package/src/api/impl/validator/index.ts +80 -4
  240. package/src/chain/archiveStore/archiveStore.ts +5 -5
  241. package/src/chain/archiveStore/interface.ts +4 -4
  242. package/src/chain/archiveStore/strategies/frequencyStateArchiveStrategy.ts +4 -4
  243. package/src/chain/archiveStore/utils/archiveBlocks.ts +153 -94
  244. package/src/chain/blocks/importBlock.ts +3 -2
  245. package/src/chain/blocks/importExecutionPayload.ts +107 -101
  246. package/src/chain/blocks/index.ts +54 -15
  247. package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +5 -1
  248. package/src/chain/blocks/payloadEnvelopeInput/types.ts +1 -0
  249. package/src/chain/blocks/payloadEnvelopeProcessor.ts +2 -2
  250. package/src/chain/blocks/types.ts +14 -25
  251. package/src/chain/blocks/utils/chainSegment.ts +106 -17
  252. package/src/chain/blocks/verifyBlock.ts +68 -9
  253. package/src/chain/blocks/verifyBlocksSanityChecks.ts +16 -7
  254. package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +129 -0
  255. package/src/chain/blocks/verifyPayloadsDataAvailability.ts +7 -4
  256. package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +9 -18
  257. package/src/chain/chain.ts +38 -19
  258. package/src/chain/emitter.ts +3 -3
  259. package/src/chain/errors/blockError.ts +4 -1
  260. package/src/chain/errors/executionPayloadBid.ts +6 -0
  261. package/src/chain/errors/executionPayloadEnvelope.ts +6 -0
  262. package/src/chain/errors/index.ts +1 -0
  263. package/src/chain/errors/proposerPreferences.ts +39 -0
  264. package/src/chain/forkChoice/index.ts +2 -22
  265. package/src/chain/interface.ts +11 -3
  266. package/src/chain/opPools/payloadAttestationPool.ts +29 -8
  267. package/src/chain/prepareNextSlot.ts +42 -12
  268. package/src/chain/produceBlock/produceBlockBody.ts +47 -13
  269. package/src/chain/regen/interface.ts +1 -0
  270. package/src/chain/seenCache/index.ts +1 -0
  271. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +35 -23
  272. package/src/chain/seenCache/seenProposerPreferences.ts +29 -0
  273. package/src/chain/stateCache/persistentCheckpointsCache.ts +4 -1
  274. package/src/chain/validation/block.ts +1 -0
  275. package/src/chain/validation/executionPayloadBid.ts +14 -0
  276. package/src/chain/validation/executionPayloadEnvelope.ts +20 -10
  277. package/src/chain/validation/proposerPreferences.ts +91 -0
  278. package/src/db/repositories/executionPayloadEnvelopeArchive.ts +1 -1
  279. package/src/execution/engine/http.ts +21 -14
  280. package/src/execution/engine/interface.ts +1 -0
  281. package/src/execution/engine/mock.ts +8 -1
  282. package/src/execution/engine/types.ts +41 -0
  283. package/src/metrics/metrics/lodestar.ts +4 -0
  284. package/src/network/gossip/interface.ts +6 -0
  285. package/src/network/gossip/scoringParameters.ts +14 -1
  286. package/src/network/gossip/topic.ts +6 -0
  287. package/src/network/interface.ts +1 -0
  288. package/src/network/network.ts +12 -1
  289. package/src/network/processor/gossipHandlers.ts +26 -13
  290. package/src/network/processor/gossipQueues/index.ts +5 -0
  291. package/src/network/processor/index.ts +1 -0
  292. package/src/network/reqresp/handlers/beaconBlocksByRange.ts +14 -6
  293. package/src/network/reqresp/handlers/blobSidecarsByRange.ts +11 -5
  294. package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +17 -5
  295. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +7 -4
  296. package/src/node/notifier.ts +8 -1
  297. package/src/sync/range/batch.ts +90 -35
  298. package/src/sync/range/chain.ts +13 -5
  299. package/src/sync/range/range.ts +18 -6
  300. package/src/sync/types.ts +72 -0
  301. package/src/sync/unknownBlock.ts +810 -57
  302. package/src/sync/utils/downloadByRange.ts +256 -39
  303. package/src/sync/utils/downloadByRoot.ts +12 -2
  304. package/src/sync/utils/pendingBlocksTree.ts +0 -15
  305. package/src/util/sszBytes.ts +21 -3
@@ -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;
@@ -333,6 +336,8 @@ export class BeaconChain implements IBeaconChain {
333
336
  logger,
334
337
  });
335
338
  this.seenPayloadEnvelopeInputCache = new SeenPayloadEnvelopeInput({
339
+ config,
340
+ clock,
336
341
  chainEvents: emitter,
337
342
  signal,
338
343
  serializedCache: this.serializedCache,
@@ -680,7 +685,7 @@ export class BeaconChain implements IBeaconChain {
680
685
  }
681
686
 
682
687
  getStateByCheckpoint(
683
- checkpoint: CheckpointWithPayloadStatus
688
+ checkpoint: CheckpointWithHex
684
689
  ): {state: IBeaconStateView; executionOptimistic: boolean; finalized: boolean} | null {
685
690
  // finalized or justified checkpoint states maynot be available with PersistentCheckpointStateCache, use getCheckpointStateOrBytes() api to get Uint8Array
686
691
  const checkpointHex = {epoch: checkpoint.epoch, rootHex: checkpoint.rootHex};
@@ -701,7 +706,7 @@ export class BeaconChain implements IBeaconChain {
701
706
  }
702
707
 
703
708
  async getStateOrBytesByCheckpoint(
704
- checkpoint: CheckpointWithPayloadStatus
709
+ checkpoint: CheckpointWithHex
705
710
  ): Promise<{state: IBeaconStateView | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null> {
706
711
  const checkpointHex = {epoch: checkpoint.epoch, rootHex: checkpoint.rootHex};
707
712
  const cachedStateCtx = await this.regen.getCheckpointStateOrBytes(checkpointHex);
@@ -886,6 +891,21 @@ export class BeaconChain implements IBeaconChain {
886
891
  );
887
892
  }
888
893
 
894
+ async getParentExecutionRequests(
895
+ parentBlockSlot: Slot,
896
+ parentBlockRootHex: RootHex
897
+ ): Promise<electra.ExecutionRequests> {
898
+ // at the fork boundary, parent is pre-gloas
899
+ if (!isForkPostGloas(this.config.getForkName(parentBlockSlot))) {
900
+ return ssz.electra.ExecutionRequests.defaultValue();
901
+ }
902
+ const envelope = await this.getExecutionPayloadEnvelope(parentBlockSlot, parentBlockRootHex);
903
+ if (envelope === null) {
904
+ throw Error(`Parent execution payload envelope not found slot=${parentBlockSlot}, root=${parentBlockRootHex}`);
905
+ }
906
+ return envelope.message.executionRequests;
907
+ }
908
+
889
909
  async getDataColumnSidecars(blockSlot: Slot, blockRootHex: string): Promise<DataColumnSidecar[]> {
890
910
  const fork = this.config.getForkName(blockSlot);
891
911
 
@@ -1082,11 +1102,15 @@ export class BeaconChain implements IBeaconChain {
1082
1102
  }
1083
1103
 
1084
1104
  async processBlock(block: IBlockInput, opts?: ImportBlockOpts): Promise<void> {
1085
- return this.blockProcessor.processBlocksJob([block], opts);
1105
+ return this.blockProcessor.processBlocksJob([block], null, opts);
1086
1106
  }
1087
1107
 
1088
- async processChainSegment(blocks: IBlockInput[], opts?: ImportBlockOpts): Promise<void> {
1089
- return this.blockProcessor.processBlocksJob(blocks, opts);
1108
+ async processChainSegment(
1109
+ blocks: IBlockInput[],
1110
+ payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
1111
+ opts?: ImportBlockOpts
1112
+ ): Promise<void> {
1113
+ await this.blockProcessor.processBlocksJob(blocks, payloadEnvelopes, opts);
1090
1114
  }
1091
1115
 
1092
1116
  async processExecutionPayload(payloadInput: PayloadEnvelopeInput, opts?: ImportPayloadOpts): Promise<void> {
@@ -1277,7 +1301,7 @@ export class BeaconChain implements IBeaconChain {
1277
1301
  * @param blockState state that declares justified checkpoint `checkpoint`
1278
1302
  */
1279
1303
  private justifiedBalancesGetter(
1280
- checkpoint: CheckpointWithPayloadStatus,
1304
+ checkpoint: CheckpointWithHex,
1281
1305
  blockState: IBeaconStateView
1282
1306
  ): EffectiveBalanceIncrements {
1283
1307
  this.metrics?.balancesCache.requests.inc();
@@ -1316,7 +1340,7 @@ export class BeaconChain implements IBeaconChain {
1316
1340
  * @param blockState state that declares justified checkpoint `checkpoint`
1317
1341
  */
1318
1342
  private closestJustifiedBalancesStateToCheckpoint(
1319
- checkpoint: CheckpointWithPayloadStatus,
1343
+ checkpoint: CheckpointWithHex,
1320
1344
  blockState: IBeaconStateView
1321
1345
  ): {state: IBeaconStateView; stateId: string; shouldWarn: boolean} {
1322
1346
  const checkpointHex = {epoch: checkpoint.epoch, rootHex: checkpoint.rootHex};
@@ -1331,10 +1355,7 @@ export class BeaconChain implements IBeaconChain {
1331
1355
  }
1332
1356
 
1333
1357
  // 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
- )) {
1358
+ for (const descendantBlock of this.forkChoice.forwardIterateDescendantsDefaultStatus(checkpoint.rootHex)) {
1338
1359
  if (computeEpochAtSlot(descendantBlock.slot) === checkpoint.epoch) {
1339
1360
  const descendantBlockState = this.regen.getStateSync(descendantBlock.stateRoot);
1340
1361
  if (descendantBlockState) {
@@ -1350,10 +1371,7 @@ export class BeaconChain implements IBeaconChain {
1350
1371
 
1351
1372
  // Find a state in the same branch of checkpoint at a latter epoch. Balances are not the same, but should be close
1352
1373
  // 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
- )) {
1374
+ for (const descendantBlock of this.forkChoice.forwardIterateDescendantsDefaultStatus(checkpoint.rootHex)) {
1357
1375
  if (computeEpochAtSlot(descendantBlock.slot) > checkpoint.epoch) {
1358
1376
  const descendantBlockState = this.regen.getStateSync(descendantBlock.stateRoot);
1359
1377
  if (descendantBlockState) {
@@ -1423,6 +1441,7 @@ export class BeaconChain implements IBeaconChain {
1423
1441
  this.payloadAttestationPool.prune(slot);
1424
1442
  this.executionPayloadBidPool.prune(slot);
1425
1443
  this.seenExecutionPayloadBids.prune(slot);
1444
+ this.seenProposerPreferences.prune(slot);
1426
1445
  this.seenAttestationDatas.onSlot(slot);
1427
1446
  this.reprocessController.onSlot(slot);
1428
1447
 
@@ -1457,7 +1476,7 @@ export class BeaconChain implements IBeaconChain {
1457
1476
  this.seenContributionAndProof.prune(head.slot);
1458
1477
  }
1459
1478
 
1460
- private onForkChoiceJustified(this: BeaconChain, cp: CheckpointWithPayloadStatus): void {
1479
+ private onForkChoiceJustified(this: BeaconChain, cp: CheckpointWithHex): void {
1461
1480
  this.logger.verbose("Fork choice justified", {epoch: cp.epoch, root: cp.rootHex});
1462
1481
  }
1463
1482
 
@@ -1468,7 +1487,7 @@ export class BeaconChain implements IBeaconChain {
1468
1487
  });
1469
1488
  }
1470
1489
 
1471
- private async onForkChoiceFinalized(this: BeaconChain, cp: CheckpointWithPayloadStatus): Promise<void> {
1490
+ private async onForkChoiceFinalized(this: BeaconChain, cp: CheckpointWithHex): Promise<void> {
1472
1491
  this.logger.verbose("Fork choice finalized", {epoch: cp.epoch, root: cp.rootHex});
1473
1492
  const finalizedSlot = computeStartSlotAtEpoch(cp.epoch);
1474
1493
  this.seenBlockProposers.prune(finalizedSlot);
@@ -1509,7 +1528,7 @@ export class BeaconChain implements IBeaconChain {
1509
1528
  }
1510
1529
  }
1511
1530
 
1512
- private async updateValidatorsCustodyRequirement(finalizedCheckpoint: CheckpointWithPayloadStatus): Promise<void> {
1531
+ private async updateValidatorsCustodyRequirement(finalizedCheckpoint: CheckpointWithHex): Promise<void> {
1513
1532
  if (this.custodyConfig.targetCustodyGroupCount === this.config.NUMBER_OF_CUSTODY_GROUPS) {
1514
1533
  // Custody requirements can only be increased, we can disable dynamic custody updates
1515
1534
  // if the node already maintains custody of all custody groups in case it is configured
@@ -1,7 +1,7 @@
1
1
  import {EventEmitter} from "node:events";
2
2
  import {StrictEventEmitter} from "strict-event-emitter-types";
3
3
  import {routes} from "@lodestar/api";
4
- import {CheckpointWithPayloadStatus} from "@lodestar/fork-choice";
4
+ import {CheckpointWithHex} from "@lodestar/fork-choice";
5
5
  import {IBeaconStateView} from "@lodestar/state-transition";
6
6
  import {DataColumnSidecar, RootHex, deneb, phase0} from "@lodestar/types";
7
7
  import {SignedExecutionPayloadEnvelope} from "@lodestar/types/gloas";
@@ -110,8 +110,8 @@ export type ChainEventData = {
110
110
  export type IChainEvents = ApiEvents & {
111
111
  [ChainEvent.checkpoint]: (checkpoint: phase0.Checkpoint, state: IBeaconStateView) => void;
112
112
 
113
- [ChainEvent.forkChoiceJustified]: (checkpoint: CheckpointWithPayloadStatus) => void;
114
- [ChainEvent.forkChoiceFinalized]: (checkpoint: CheckpointWithPayloadStatus) => void;
113
+ [ChainEvent.forkChoiceJustified]: (checkpoint: CheckpointWithHex) => void;
114
+ [ChainEvent.forkChoiceFinalized]: (checkpoint: CheckpointWithHex) => void;
115
115
 
116
116
  [ChainEvent.updateTargetCustodyGroupCount]: (targetGroupCount: number) => void;
117
117
 
@@ -74,6 +74,8 @@ export enum BlockErrorCode {
74
74
  PARENT_EXECUTION_INVALID = "BLOCK_ERROR_PARENT_EXECUTION_INVALID",
75
75
  /** The block's parent execution payload (defined by bid.parent_block_hash) has not been seen */
76
76
  PARENT_PAYLOAD_UNKNOWN = "BLOCK_ERROR_PARENT_PAYLOAD_UNKNOWN",
77
+ /** An execution payload envelope in the chain segment references a block root that does not match its slot's block */
78
+ ENVELOPE_BLOCK_ROOT_MISMATCH = "BLOCK_ERROR_ENVELOPE_BLOCK_ROOT_MISMATCH",
77
79
  }
78
80
 
79
81
  type ExecutionErrorStatus = Exclude<
@@ -107,6 +109,7 @@ export type BlockErrorType =
107
109
  | {code: BlockErrorCode.NOT_LATER_THAN_PARENT; parentSlot: Slot; slot: Slot}
108
110
  | {code: BlockErrorCode.NON_LINEAR_PARENT_ROOTS}
109
111
  | {code: BlockErrorCode.NON_LINEAR_SLOTS}
112
+ | {code: BlockErrorCode.ENVELOPE_BLOCK_ROOT_MISMATCH; envelopeBlockRoot: RootHex; blockRoot: RootHex}
110
113
  | {code: BlockErrorCode.PER_BLOCK_PROCESSING_ERROR; error: Error}
111
114
  | {code: BlockErrorCode.BEACON_CHAIN_ERROR; error: Error}
112
115
  | {code: BlockErrorCode.KNOWN_BAD_BLOCK}
@@ -120,7 +123,7 @@ export type BlockErrorType =
120
123
  | {code: BlockErrorCode.TOO_MANY_KZG_COMMITMENTS; blobKzgCommitmentsLen: number; commitmentLimit: number}
121
124
  | {code: BlockErrorCode.BID_PARENT_ROOT_MISMATCH; bidParentRoot: RootHex; blockParentRoot: RootHex}
122
125
  | {code: BlockErrorCode.PARENT_EXECUTION_INVALID; parentRoot: RootHex}
123
- | {code: BlockErrorCode.PARENT_PAYLOAD_UNKNOWN; parentBlockHash: RootHex};
126
+ | {code: BlockErrorCode.PARENT_PAYLOAD_UNKNOWN; parentRoot: RootHex; parentBlockHash: RootHex};
124
127
 
125
128
  export class BlockGossipError extends GossipActionError<BlockErrorType> {}
126
129
 
@@ -7,6 +7,7 @@ export enum ExecutionPayloadBidErrorCode {
7
7
  BID_ALREADY_KNOWN = "EXECUTION_PAYLOAD_BID_ERROR_BID_ALREADY_KNOWN",
8
8
  BID_TOO_LOW = "EXECUTION_PAYLOAD_BID_ERROR_BID_TOO_LOW",
9
9
  BID_TOO_HIGH = "EXECUTION_PAYLOAD_BID_ERROR_BID_TOO_HIGH",
10
+ TOO_MANY_KZG_COMMITMENTS = "EXECUTION_PAYLOAD_BID_ERROR_TOO_MANY_KZG_COMMITMENTS",
10
11
  UNKNOWN_BLOCK_ROOT = "EXECUTION_PAYLOAD_BID_ERROR_UNKNOWN_BLOCK_ROOT",
11
12
  INVALID_SLOT = "EXECUTION_PAYLOAD_BID_ERROR_INVALID_SLOT",
12
13
  INVALID_SIGNATURE = "EXECUTION_PAYLOAD_BID_ERROR_INVALID_SIGNATURE",
@@ -28,6 +29,11 @@ export type ExecutionPayloadBidErrorType =
28
29
  }
29
30
  | {code: ExecutionPayloadBidErrorCode.BID_TOO_LOW; bidValue: number; currentHighestBid: number}
30
31
  | {code: ExecutionPayloadBidErrorCode.BID_TOO_HIGH; bidValue: number; builderBalance: number}
32
+ | {
33
+ code: ExecutionPayloadBidErrorCode.TOO_MANY_KZG_COMMITMENTS;
34
+ blobKzgCommitmentsLen: number;
35
+ commitmentLimit: number;
36
+ }
31
37
  | {code: ExecutionPayloadBidErrorCode.UNKNOWN_BLOCK_ROOT; parentBlockRoot: RootHex}
32
38
  | {code: ExecutionPayloadBidErrorCode.INVALID_SLOT; builderIndex: BuilderIndex; slot: Slot}
33
39
  | {code: ExecutionPayloadBidErrorCode.INVALID_SIGNATURE; builderIndex: BuilderIndex; slot: Slot};
@@ -11,6 +11,7 @@ export enum ExecutionPayloadEnvelopeErrorCode {
11
11
  SLOT_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_SLOT_MISMATCH",
12
12
  BUILDER_INDEX_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_BUILDER_INDEX_MISMATCH",
13
13
  BLOCK_HASH_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_BLOCK_HASH_MISMATCH",
14
+ EXECUTION_REQUESTS_ROOT_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_EXECUTION_REQUESTS_ROOT_MISMATCH",
14
15
  INVALID_SIGNATURE = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_INVALID_SIGNATURE",
15
16
  PAYLOAD_ENVELOPE_INPUT_MISSING = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_PAYLOAD_ENVELOPE_INPUT_MISSING",
16
17
  }
@@ -36,6 +37,11 @@ export type ExecutionPayloadEnvelopeErrorType =
36
37
  envelopeBlockHash: RootHex;
37
38
  bidBlockHash: RootHex | null;
38
39
  }
40
+ | {
41
+ code: ExecutionPayloadEnvelopeErrorCode.EXECUTION_REQUESTS_ROOT_MISMATCH;
42
+ envelopeRequestsRoot: RootHex;
43
+ bidRequestsRoot: RootHex;
44
+ }
39
45
  | {code: ExecutionPayloadEnvelopeErrorCode.INVALID_SIGNATURE}
40
46
  | {code: ExecutionPayloadEnvelopeErrorCode.PAYLOAD_ENVELOPE_INPUT_MISSING; blockRoot: RootHex};
41
47
 
@@ -8,6 +8,7 @@ export * from "./executionPayloadBid.js";
8
8
  export * from "./executionPayloadEnvelope.js";
9
9
  export * from "./gossipValidation.js";
10
10
  export * from "./payloadAttestation.js";
11
+ export * from "./proposerPreferences.js";
11
12
  export * from "./proposerSlashingError.js";
12
13
  export * from "./syncCommitteeError.js";
13
14
  export * from "./voluntaryExitError.js";
@@ -0,0 +1,39 @@
1
+ import {Slot, ValidatorIndex} from "@lodestar/types";
2
+ import {GossipActionError} from "./gossipValidation.js";
3
+
4
+ export enum ProposerPreferencesErrorCode {
5
+ INVALID_EPOCH = "PROPOSER_PREFERENCES_ERROR_INVALID_EPOCH",
6
+ PROPOSAL_SLOT_PASSED = "PROPOSER_PREFERENCES_ERROR_PROPOSAL_SLOT_PASSED",
7
+ INVALID_PROPOSER = "PROPOSER_PREFERENCES_ERROR_INVALID_PROPOSER",
8
+ ALREADY_KNOWN = "PROPOSER_PREFERENCES_ERROR_ALREADY_KNOWN",
9
+ INVALID_SIGNATURE = "PROPOSER_PREFERENCES_ERROR_INVALID_SIGNATURE",
10
+ }
11
+
12
+ export type ProposerPreferencesErrorType =
13
+ | {
14
+ code: ProposerPreferencesErrorCode.INVALID_EPOCH;
15
+ proposalSlot: Slot;
16
+ currentEpoch: number;
17
+ }
18
+ | {
19
+ code: ProposerPreferencesErrorCode.PROPOSAL_SLOT_PASSED;
20
+ proposalSlot: Slot;
21
+ currentSlot: Slot;
22
+ }
23
+ | {
24
+ code: ProposerPreferencesErrorCode.INVALID_PROPOSER;
25
+ proposalSlot: Slot;
26
+ validatorIndex: ValidatorIndex;
27
+ }
28
+ | {
29
+ code: ProposerPreferencesErrorCode.ALREADY_KNOWN;
30
+ proposalSlot: Slot;
31
+ validatorIndex: ValidatorIndex;
32
+ }
33
+ | {
34
+ code: ProposerPreferencesErrorCode.INVALID_SIGNATURE;
35
+ proposalSlot: Slot;
36
+ validatorIndex: ValidatorIndex;
37
+ };
38
+
39
+ export class ProposerPreferencesError extends GossipActionError<ProposerPreferencesErrorType> {}
@@ -8,7 +8,6 @@ import {
8
8
  ProtoArray,
9
9
  ProtoBlock,
10
10
  ForkChoiceOpts as RawForkChoiceOpts,
11
- getCheckpointPayloadStatus,
12
11
  } from "@lodestar/fork-choice";
13
12
  import {ZERO_HASH_HEX} from "@lodestar/params";
14
13
  import {
@@ -104,16 +103,6 @@ export function initializeForkChoiceFromFinalizedState(
104
103
 
105
104
  const isForkPostGloas = computeEpochAtSlot(state.slot) >= config.GLOAS_FORK_EPOCH;
106
105
 
107
- // Determine justified checkpoint payload status
108
- const justifiedPayloadStatus = isForkPostGloas
109
- ? PayloadStatus.PENDING
110
- : getCheckpointPayloadStatus(config, state, justifiedCheckpoint.epoch);
111
-
112
- // Determine finalized checkpoint payload status
113
- const finalizedPayloadStatus = isForkPostGloas
114
- ? PayloadStatus.PENDING
115
- : getCheckpointPayloadStatus(config, state, finalizedCheckpoint.epoch);
116
-
117
106
  return new forkchoiceConstructor(
118
107
  config,
119
108
 
@@ -123,8 +112,6 @@ export function initializeForkChoiceFromFinalizedState(
123
112
  finalizedCheckpoint,
124
113
  justifiedBalances,
125
114
  justifiedBalancesGetter,
126
- justifiedPayloadStatus,
127
- finalizedPayloadStatus,
128
115
  {
129
116
  onJustified: (cp) => emitter.emit(ChainEvent.forkChoiceJustified, cp),
130
117
  onFinalized: (cp) => emitter.emit(ChainEvent.forkChoiceFinalized, cp),
@@ -161,7 +148,7 @@ export function initializeForkChoiceFromFinalizedState(
161
148
  : {executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}),
162
149
 
163
150
  dataAvailabilityStatus: DataAvailabilityStatus.PreData,
164
- payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL, // TODO GLOAS: Post-gloas how do we know if the checkpoint payload is FULL or EMPTY?
151
+ payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL,
165
152
  parentBlockHash: isStatePostGloas(state) ? toRootHex(state.latestBlockHash) : null,
166
153
  },
167
154
  currentSlot
@@ -208,19 +195,12 @@ export function initializeForkChoiceFromUnfinalizedState(
208
195
 
209
196
  const isForkPostGloas = computeEpochAtSlot(unfinalizedState.slot) >= config.GLOAS_FORK_EPOCH;
210
197
 
211
- // For unfinalized state, use getCheckpointPayloadStatus to determine the correct status.
212
- // It checks state.execution_payload_availability to determine EMPTY vs FULL.
213
- const justifiedPayloadStatus = getCheckpointPayloadStatus(config, unfinalizedState, justifiedCheckpoint.epoch);
214
- const finalizedPayloadStatus = getCheckpointPayloadStatus(config, unfinalizedState, finalizedCheckpoint.epoch);
215
-
216
198
  const store = new ForkChoiceStore(
217
199
  currentSlot,
218
200
  justifiedCheckpoint,
219
201
  finalizedCheckpoint,
220
202
  justifiedBalances,
221
203
  justifiedBalancesGetter,
222
- justifiedPayloadStatus,
223
- finalizedPayloadStatus,
224
204
  {
225
205
  onJustified: (cp) => emitter.emit(ChainEvent.forkChoiceJustified, cp),
226
206
  onFinalized: (cp) => emitter.emit(ChainEvent.forkChoiceFinalized, cp),
@@ -260,7 +240,7 @@ export function initializeForkChoiceFromUnfinalizedState(
260
240
  : {executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}),
261
241
 
262
242
  dataAvailabilityStatus: DataAvailabilityStatus.PreData,
263
- payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL, // TODO GLOAS: Post-gloas how do we know if the checkpoint payload is FULL or EMPTY?
243
+ payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL,
264
244
  parentBlockHash: isStatePostGloas(unfinalizedState) ? toRootHex(unfinalizedState.latestBlockHash) : null,
265
245
  };
266
246
 
@@ -1,6 +1,6 @@
1
1
  import {Type} from "@chainsafe/ssz";
2
2
  import {BeaconConfig} from "@lodestar/config";
3
- import {CheckpointWithHex, CheckpointWithPayloadStatus, IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
3
+ import {CheckpointWithHex, IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
4
4
  import {EpochShuffling, IBeaconStateView, PubkeyCache} from "@lodestar/state-transition";
5
5
  import {
6
6
  BeaconBlock,
@@ -18,6 +18,7 @@ import {
18
18
  altair,
19
19
  capella,
20
20
  deneb,
21
+ electra,
21
22
  gloas,
22
23
  phase0,
23
24
  rewards,
@@ -60,6 +61,7 @@ import {
60
61
  SeenContributionAndProof,
61
62
  SeenExecutionPayloadBids,
62
63
  SeenPayloadAttesters,
64
+ SeenProposerPreferences,
63
65
  SeenSyncCommitteeMessages,
64
66
  } from "./seenCache/index.js";
65
67
  import {SeenAggregatedAttestations} from "./seenCache/seenAggregateAndProof.js";
@@ -130,6 +132,7 @@ export interface IBeaconChain {
130
132
  readonly seenPayloadAttesters: SeenPayloadAttesters;
131
133
  readonly seenAggregatedAttestations: SeenAggregatedAttestations;
132
134
  readonly seenExecutionPayloadBids: SeenExecutionPayloadBids;
135
+ readonly seenProposerPreferences: SeenProposerPreferences;
133
136
  readonly seenBlockProposers: SeenBlockProposers;
134
137
  readonly seenSyncCommitteeMessages: SeenSyncCommitteeMessages;
135
138
  readonly seenContributionAndProof: SeenContributionAndProof;
@@ -195,7 +198,7 @@ export interface IBeaconChain {
195
198
  ): {state: IBeaconStateView; executionOptimistic: boolean; finalized: boolean} | null;
196
199
  /** Return state bytes by checkpoint */
197
200
  getStateOrBytesByCheckpoint(
198
- checkpoint: CheckpointWithPayloadStatus
201
+ checkpoint: CheckpointWithHex
199
202
  ): Promise<{state: IBeaconStateView | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null>;
200
203
 
201
204
  /**
@@ -231,6 +234,7 @@ export interface IBeaconChain {
231
234
  blockSlot: Slot,
232
235
  blockRootHex: string
233
236
  ): Promise<gloas.SignedExecutionPayloadEnvelope | null>;
237
+ getParentExecutionRequests(parentBlockSlot: Slot, parentBlockRootHex: RootHex): Promise<electra.ExecutionRequests>;
234
238
 
235
239
  produceCommonBlockBody(blockAttributes: BlockAttributes): Promise<CommonBlockBody>;
236
240
  produceBlock(blockAttributes: BlockAttributes & {commonBlockBodyPromise: Promise<CommonBlockBody>}): Promise<{
@@ -248,7 +252,11 @@ export interface IBeaconChain {
248
252
  /** Process a block until complete */
249
253
  processBlock(block: IBlockInput, opts?: ImportBlockOpts): Promise<void>;
250
254
  /** Process a chain of blocks until complete */
251
- processChainSegment(blocks: IBlockInput[], opts?: ImportBlockOpts): Promise<void>;
255
+ processChainSegment(
256
+ blocks: IBlockInput[],
257
+ payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
258
+ opts?: ImportBlockOpts
259
+ ): Promise<void>;
252
260
 
253
261
  /** Process execution payload envelope: verify, import to fork choice, and persist to DB */
254
262
  processExecutionPayload(payloadInput: PayloadEnvelopeInput, opts?: ImportPayloadOpts): Promise<void>;
@@ -1,7 +1,7 @@
1
1
  import {Signature, aggregateSignatures} from "@chainsafe/blst";
2
2
  import {BitArray} from "@chainsafe/ssz";
3
3
  import {ChainForkConfig} from "@lodestar/config";
4
- import {MAX_COMMITTEES_PER_SLOT, PTC_SIZE} from "@lodestar/params";
4
+ import {MAX_COMMITTEES_PER_SLOT, MAX_PAYLOAD_ATTESTATIONS, PTC_SIZE} from "@lodestar/params";
5
5
  import {RootHex, Slot, gloas} from "@lodestar/types";
6
6
  import {MapDef, toRootHex} from "@lodestar/utils";
7
7
  import {Metrics} from "../../metrics/metrics.js";
@@ -95,13 +95,9 @@ export class PayloadAttestationPool {
95
95
 
96
96
  /**
97
97
  * Get payload attestations to be included in a block.
98
- * Pick the top `maxAttestation` number of attestations with the most votes
98
+ * Pick the top `MAX_PAYLOAD_ATTESTATIONS` aggregates with the most votes.
99
99
  */
100
- getPayloadAttestationsForBlock(
101
- beaconBlockRoot: BlockRootHex,
102
- slot: Slot,
103
- maxAttestation: number
104
- ): gloas.PayloadAttestation[] {
100
+ getPayloadAttestationsForBlock(beaconBlockRoot: BlockRootHex, slot: Slot): gloas.PayloadAttestation[] {
105
101
  const aggregateByDataRootByBlockRoot = this.aggregateByDataRootByBlockRootBySlot.get(slot);
106
102
 
107
103
  if (!aggregateByDataRootByBlockRoot) {
@@ -119,7 +115,32 @@ export class PayloadAttestationPool {
119
115
  return Array.from(aggregateByDataRoot.values())
120
116
  .slice()
121
117
  .sort((a, b) => b.aggregationBits.getTrueBitIndexes().length - a.aggregationBits.getTrueBitIndexes().length)
122
- .slice(0, maxAttestation)
118
+ .slice(0, MAX_PAYLOAD_ATTESTATIONS)
119
+ .map(fastToPayloadAttestation);
120
+ }
121
+
122
+ getAll(slot?: Slot): gloas.PayloadAttestation[] {
123
+ const aggregates: AggregateFast[] = [];
124
+
125
+ const addAggregates = (aggregateByDataRootByBlockRoot: Map<BlockRootHex, Map<DataRootHex, AggregateFast>>) => {
126
+ for (const aggregateByDataRoot of aggregateByDataRootByBlockRoot.values()) {
127
+ aggregates.push(...aggregateByDataRoot.values());
128
+ }
129
+ };
130
+
131
+ if (slot !== undefined) {
132
+ const aggregateByDataRootByBlockRoot = this.aggregateByDataRootByBlockRootBySlot.get(slot);
133
+ if (aggregateByDataRootByBlockRoot) {
134
+ addAggregates(aggregateByDataRootByBlockRoot);
135
+ }
136
+ } else {
137
+ for (const aggregateByDataRootByBlockRoot of this.aggregateByDataRootByBlockRootBySlot.values()) {
138
+ addAggregates(aggregateByDataRootByBlockRoot);
139
+ }
140
+ }
141
+
142
+ return aggregates
143
+ .sort((a, b) => b.aggregationBits.getTrueBitIndexes().length - a.aggregationBits.getTrueBitIndexes().length)
123
144
  .map(fastToPayloadAttestation);
124
145
  }
125
146
 
@@ -10,7 +10,7 @@ import {
10
10
  isStatePostBellatrix,
11
11
  isStatePostGloas,
12
12
  } from "@lodestar/state-transition";
13
- import {Bytes32, Slot} from "@lodestar/types";
13
+ import {Bytes32, Slot, electra} from "@lodestar/types";
14
14
  import {Logger, fromHex, isErrorAborted, sleep} from "@lodestar/utils";
15
15
  import {GENESIS_SLOT, ZERO_HASH_HEX} from "../constants/constants.js";
16
16
  import {BuilderStatus} from "../execution/builder/http.js";
@@ -83,7 +83,7 @@ export class PrepareNextSlotScheduler {
83
83
  const headBlock = this.chain.recomputeForkChoiceHead(ForkchoiceCaller.prepareNextSlot);
84
84
  const {slot: headSlot, blockRoot: headRoot} = headBlock;
85
85
  // may be updated below if we predict a proposer-boost-reorg
86
- let updatedHeadRoot = headRoot;
86
+ let updatedHead = headBlock;
87
87
 
88
88
  // PS: previously this was comparing slots, but that gave no leway on the skipped
89
89
  // slots on epoch bounday. Making it more fluid.
@@ -148,7 +148,7 @@ export class PrepareNextSlotScheduler {
148
148
  {dontTransferCache: !isEpochTransition},
149
149
  RegenCaller.predictProposerHead
150
150
  );
151
- updatedHeadRoot = proposerHeadRoot;
151
+ updatedHead = proposerHead;
152
152
  }
153
153
 
154
154
  // Update the builder status, if enabled shoot an api call to check status
@@ -165,14 +165,19 @@ export class PrepareNextSlotScheduler {
165
165
  }
166
166
 
167
167
  let parentBlockHash: Bytes32;
168
+ let isExtendingPayload = false;
168
169
  if (isStatePostGloas(updatedPrepareState)) {
169
- parentBlockHash = this.chain.forkChoice.shouldExtendPayload(updatedHeadRoot)
170
+ isExtendingPayload = this.chain.forkChoice.shouldExtendPayload(updatedHead.blockRoot);
171
+ parentBlockHash = isExtendingPayload
170
172
  ? updatedPrepareState.latestExecutionPayloadBid.blockHash
171
173
  : updatedPrepareState.latestExecutionPayloadBid.parentBlockHash;
172
174
  } else {
173
175
  parentBlockHash = updatedPrepareState.latestExecutionPayloadHeader.blockHash;
174
176
  }
175
177
 
178
+ // Reused by the SSE emit below to avoid a second DB lookup on cache miss
179
+ let parentExecutionRequests: electra.ExecutionRequests | undefined;
180
+
176
181
  if (feeRecipient) {
177
182
  const preparationTime =
178
183
  computeTimeAtSlot(this.config, prepareSlot, this.chain.genesisTime) - Date.now() / 1000;
@@ -182,6 +187,13 @@ export class PrepareNextSlotScheduler {
182
187
  const finalizedBlockHash =
183
188
  this.chain.forkChoice.getFinalizedBlock().executionPayloadBlockHash ?? ZERO_HASH_HEX;
184
189
 
190
+ if (isExtendingPayload) {
191
+ parentExecutionRequests = await this.chain.getParentExecutionRequests(
192
+ updatedHead.slot,
193
+ updatedHead.blockRoot
194
+ );
195
+ }
196
+
185
197
  // awaiting here instead of throwing an async call because there is no other task
186
198
  // left for scheduler and this gives nice semantics to catch and log errors in the
187
199
  // try/catch wrapper here.
@@ -189,12 +201,13 @@ export class PrepareNextSlotScheduler {
189
201
  this.chain,
190
202
  this.logger,
191
203
  fork as ForkPostBellatrix, // State is of execution type
192
- fromHex(updatedHeadRoot),
204
+ fromHex(updatedHead.blockRoot),
193
205
  parentBlockHash,
194
206
  safeBlockHash,
195
207
  finalizedBlockHash,
196
208
  updatedPrepareState,
197
- feeRecipient
209
+ feeRecipient,
210
+ parentExecutionRequests
198
211
  );
199
212
  this.logger.verbose("PrepareNextSlotScheduler prepared new payload", {
200
213
  prepareSlot,
@@ -203,21 +216,38 @@ export class PrepareNextSlotScheduler {
203
216
  });
204
217
  }
205
218
 
219
+ if (ForkSeq[fork] >= ForkSeq.gloas) {
220
+ // Cutoff = slot of the parent of the block we'll actually build on (post-reorg).
221
+ // Steady state: cache holds just 2 entries — head (parent for next-slot production)
222
+ // and head.parent (proposer-boost-reorg fallback). Anything older is evicted.
223
+ const updatedHeadParent = this.chain.forkChoice.getBlockHexDefaultStatus(updatedHead.parentRoot);
224
+ if (updatedHeadParent) {
225
+ this.chain.seenPayloadEnvelopeInputCache.pruneBelow(updatedHeadParent.slot);
226
+ }
227
+ }
228
+
206
229
  this.computeStateHashTreeRoot(updatedPrepareState, isEpochTransition);
207
230
 
208
- // If emitPayloadAttributes is true emit a SSE payloadAttributes event
231
+ // If emitPayloadAttributes is true emit a SSE payloadAttributes event for
232
+ // every slot. Without the flag, only emit the event if we are proposing in the next slot.
209
233
  if (
210
- this.chain.opts.emitPayloadAttributes === true &&
234
+ (feeRecipient || this.chain.opts.emitPayloadAttributes === true) &&
211
235
  this.chain.emitter.listenerCount(routes.events.EventType.payloadAttributes)
212
236
  ) {
237
+ // if we didn't fetch above (not proposing), SSE still needs it here
238
+ if (!parentExecutionRequests && isExtendingPayload) {
239
+ parentExecutionRequests = await this.chain.getParentExecutionRequests(
240
+ updatedHead.slot,
241
+ updatedHead.blockRoot
242
+ );
243
+ }
213
244
  const data = getPayloadAttributesForSSE(fork as ForkPostBellatrix, this.chain, {
214
245
  prepareState: updatedPrepareState,
215
246
  prepareSlot,
216
- parentBlockRoot: fromHex(headRoot),
247
+ parentBlockRoot: fromHex(updatedHead.blockRoot),
217
248
  parentBlockHash,
218
- // The likely consumers of this API are builders and will anyway ignore the
219
- // feeRecipient, so just pass zero hash for now till a real use case arises
220
- feeRecipient: "0x0000000000000000000000000000000000000000000000000000000000000000",
249
+ feeRecipient: feeRecipient ?? "0x0000000000000000000000000000000000000000",
250
+ parentExecutionRequests,
221
251
  });
222
252
  this.chain.emitter.emit(routes.events.EventType.payloadAttributes, {data, version: fork});
223
253
  }