@lodestar/beacon-node 1.43.0-dev.6b7eebbf6d → 1.43.0-dev.6f485b1b61

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 (288) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +16 -5
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
  5. package/lib/api/impl/beacon/pool/index.js +45 -2
  6. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  7. package/lib/api/impl/debug/index.d.ts.map +1 -1
  8. package/lib/api/impl/debug/index.js +0 -1
  9. package/lib/api/impl/debug/index.js.map +1 -1
  10. package/lib/api/impl/lodestar/index.js +1 -1
  11. package/lib/api/impl/lodestar/index.js.map +1 -1
  12. package/lib/api/impl/validator/index.d.ts.map +1 -1
  13. package/lib/api/impl/validator/index.js +68 -2
  14. package/lib/api/impl/validator/index.js.map +1 -1
  15. package/lib/chain/blocks/blockInput/blockInput.d.ts +3 -0
  16. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  17. package/lib/chain/blocks/blockInput/blockInput.js +4 -1
  18. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  19. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  20. package/lib/chain/blocks/importBlock.js +16 -28
  21. package/lib/chain/blocks/importBlock.js.map +1 -1
  22. package/lib/chain/blocks/importExecutionPayload.d.ts +23 -6
  23. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  24. package/lib/chain/blocks/importExecutionPayload.js +57 -24
  25. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  26. package/lib/chain/blocks/index.d.ts +5 -3
  27. package/lib/chain/blocks/index.d.ts.map +1 -1
  28. package/lib/chain/blocks/index.js +58 -25
  29. package/lib/chain/blocks/index.js.map +1 -1
  30. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +12 -1
  31. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
  32. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +28 -2
  33. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
  34. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +17 -0
  35. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
  36. package/lib/chain/blocks/payloadEnvelopeProcessor.js +2 -2
  37. package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
  38. package/lib/chain/blocks/types.d.ts +4 -3
  39. package/lib/chain/blocks/types.d.ts.map +1 -1
  40. package/lib/chain/blocks/utils/chainSegment.d.ts +23 -2
  41. package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
  42. package/lib/chain/blocks/utils/chainSegment.js +89 -12
  43. package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
  44. package/lib/chain/blocks/verifyBlock.d.ts +5 -3
  45. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  46. package/lib/chain/blocks/verifyBlock.js +50 -7
  47. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  48. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +0 -4
  49. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  50. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +5 -2
  51. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  52. package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts +2 -1
  53. package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
  54. package/lib/chain/blocks/verifyBlocksSanityChecks.js +25 -5
  55. package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
  56. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +2 -2
  57. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -1
  58. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +12 -8
  59. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -1
  60. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -1
  61. package/lib/chain/blocks/verifyPayloadsDataAvailability.js +8 -3
  62. package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -1
  63. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts.map +1 -1
  64. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js +1 -10
  65. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js.map +1 -1
  66. package/lib/chain/chain.d.ts +5 -3
  67. package/lib/chain/chain.d.ts.map +1 -1
  68. package/lib/chain/chain.js +42 -12
  69. package/lib/chain/chain.js.map +1 -1
  70. package/lib/chain/emitter.d.ts +0 -11
  71. package/lib/chain/emitter.d.ts.map +1 -1
  72. package/lib/chain/emitter.js +0 -4
  73. package/lib/chain/emitter.js.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/index.d.ts +1 -0
  83. package/lib/chain/errors/index.d.ts.map +1 -1
  84. package/lib/chain/errors/index.js +1 -0
  85. package/lib/chain/errors/index.js.map +1 -1
  86. package/lib/chain/errors/proposerPreferences.d.ts +40 -0
  87. package/lib/chain/errors/proposerPreferences.d.ts.map +1 -0
  88. package/lib/chain/errors/proposerPreferences.js +14 -0
  89. package/lib/chain/errors/proposerPreferences.js.map +1 -0
  90. package/lib/chain/initState.d.ts.map +1 -1
  91. package/lib/chain/initState.js +6 -1
  92. package/lib/chain/initState.js.map +1 -1
  93. package/lib/chain/interface.d.ts +5 -3
  94. package/lib/chain/interface.d.ts.map +1 -1
  95. package/lib/chain/interface.js.map +1 -1
  96. package/lib/chain/opPools/payloadAttestationPool.d.ts +3 -2
  97. package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -1
  98. package/lib/chain/opPools/payloadAttestationPool.js +26 -4
  99. package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
  100. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  101. package/lib/chain/prepareNextSlot.js +31 -13
  102. package/lib/chain/prepareNextSlot.js.map +1 -1
  103. package/lib/chain/produceBlock/produceBlockBody.d.ts +11 -1
  104. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  105. package/lib/chain/produceBlock/produceBlockBody.js +47 -15
  106. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  107. package/lib/chain/regen/interface.d.ts +1 -0
  108. package/lib/chain/regen/interface.d.ts.map +1 -1
  109. package/lib/chain/regen/interface.js +1 -0
  110. package/lib/chain/regen/interface.js.map +1 -1
  111. package/lib/chain/regen/queued.d.ts.map +1 -1
  112. package/lib/chain/regen/queued.js +1 -4
  113. package/lib/chain/regen/queued.js.map +1 -1
  114. package/lib/chain/regen/regen.d.ts.map +1 -1
  115. package/lib/chain/regen/regen.js +1 -4
  116. package/lib/chain/regen/regen.js.map +1 -1
  117. package/lib/chain/seenCache/index.d.ts +1 -0
  118. package/lib/chain/seenCache/index.d.ts.map +1 -1
  119. package/lib/chain/seenCache/index.js +1 -0
  120. package/lib/chain/seenCache/index.js.map +1 -1
  121. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +24 -7
  122. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
  123. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +69 -17
  124. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
  125. package/lib/chain/seenCache/seenProposerPreferences.d.ts +16 -0
  126. package/lib/chain/seenCache/seenProposerPreferences.d.ts.map +1 -0
  127. package/lib/chain/seenCache/seenProposerPreferences.js +26 -0
  128. package/lib/chain/seenCache/seenProposerPreferences.js.map +1 -0
  129. package/lib/chain/validation/block.d.ts.map +1 -1
  130. package/lib/chain/validation/block.js +1 -0
  131. package/lib/chain/validation/block.js.map +1 -1
  132. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  133. package/lib/chain/validation/executionPayloadBid.js +24 -9
  134. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  135. package/lib/chain/validation/proposerPreferences.d.ts +8 -0
  136. package/lib/chain/validation/proposerPreferences.d.ts.map +1 -0
  137. package/lib/chain/validation/proposerPreferences.js +91 -0
  138. package/lib/chain/validation/proposerPreferences.js.map +1 -0
  139. package/lib/metrics/metrics/lodestar.d.ts +1 -0
  140. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  141. package/lib/metrics/metrics/lodestar.js +4 -0
  142. package/lib/metrics/metrics/lodestar.js.map +1 -1
  143. package/lib/network/gossip/interface.d.ts +7 -1
  144. package/lib/network/gossip/interface.d.ts.map +1 -1
  145. package/lib/network/gossip/interface.js +1 -0
  146. package/lib/network/gossip/interface.js.map +1 -1
  147. package/lib/network/gossip/scoringParameters.d.ts.map +1 -1
  148. package/lib/network/gossip/scoringParameters.js +12 -1
  149. package/lib/network/gossip/scoringParameters.js.map +1 -1
  150. package/lib/network/gossip/topic.d.ts +10 -0
  151. package/lib/network/gossip/topic.d.ts.map +1 -1
  152. package/lib/network/gossip/topic.js +6 -0
  153. package/lib/network/gossip/topic.js.map +1 -1
  154. package/lib/network/interface.d.ts +1 -0
  155. package/lib/network/interface.d.ts.map +1 -1
  156. package/lib/network/network.d.ts +1 -0
  157. package/lib/network/network.d.ts.map +1 -1
  158. package/lib/network/network.js +5 -0
  159. package/lib/network/network.js.map +1 -1
  160. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  161. package/lib/network/processor/gossipHandlers.js +38 -16
  162. package/lib/network/processor/gossipHandlers.js.map +1 -1
  163. package/lib/network/processor/gossipQueues/index.d.ts.map +1 -1
  164. package/lib/network/processor/gossipQueues/index.js +5 -0
  165. package/lib/network/processor/gossipQueues/index.js.map +1 -1
  166. package/lib/network/processor/index.d.ts.map +1 -1
  167. package/lib/network/processor/index.js +6 -5
  168. package/lib/network/processor/index.js.map +1 -1
  169. package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
  170. package/lib/network/reqresp/handlers/beaconBlocksByRange.js +14 -6
  171. package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
  172. package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts.map +1 -1
  173. package/lib/network/reqresp/handlers/blobSidecarsByRange.js +11 -5
  174. package/lib/network/reqresp/handlers/blobSidecarsByRange.js.map +1 -1
  175. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
  176. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +17 -5
  177. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
  178. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -1
  179. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +7 -4
  180. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
  181. package/lib/node/nodejs.js +2 -2
  182. package/lib/node/nodejs.js.map +1 -1
  183. package/lib/sync/constants.d.ts +3 -1
  184. package/lib/sync/constants.d.ts.map +1 -1
  185. package/lib/sync/constants.js +3 -4
  186. package/lib/sync/constants.js.map +1 -1
  187. package/lib/sync/range/batch.d.ts +35 -5
  188. package/lib/sync/range/batch.d.ts.map +1 -1
  189. package/lib/sync/range/batch.js +240 -59
  190. package/lib/sync/range/batch.js.map +1 -1
  191. package/lib/sync/range/chain.d.ts +19 -4
  192. package/lib/sync/range/chain.d.ts.map +1 -1
  193. package/lib/sync/range/chain.js +64 -11
  194. package/lib/sync/range/chain.js.map +1 -1
  195. package/lib/sync/range/range.d.ts.map +1 -1
  196. package/lib/sync/range/range.js +31 -9
  197. package/lib/sync/range/range.js.map +1 -1
  198. package/lib/sync/sync.d.ts.map +1 -1
  199. package/lib/sync/sync.js +13 -0
  200. package/lib/sync/sync.js.map +1 -1
  201. package/lib/sync/types.d.ts +34 -0
  202. package/lib/sync/types.d.ts.map +1 -1
  203. package/lib/sync/types.js +34 -0
  204. package/lib/sync/types.js.map +1 -1
  205. package/lib/sync/unknownBlock.d.ts +29 -1
  206. package/lib/sync/unknownBlock.d.ts.map +1 -1
  207. package/lib/sync/unknownBlock.js +738 -61
  208. package/lib/sync/unknownBlock.js.map +1 -1
  209. package/lib/sync/utils/downloadByRange.d.ts +67 -10
  210. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  211. package/lib/sync/utils/downloadByRange.js +211 -26
  212. package/lib/sync/utils/downloadByRange.js.map +1 -1
  213. package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
  214. package/lib/sync/utils/downloadByRoot.js +16 -2
  215. package/lib/sync/utils/downloadByRoot.js.map +1 -1
  216. package/lib/sync/utils/pendingBlocksTree.d.ts +0 -1
  217. package/lib/sync/utils/pendingBlocksTree.d.ts.map +1 -1
  218. package/lib/sync/utils/pendingBlocksTree.js +0 -9
  219. package/lib/sync/utils/pendingBlocksTree.js.map +1 -1
  220. package/lib/util/sszBytes.d.ts.map +1 -1
  221. package/lib/util/sszBytes.js +8 -6
  222. package/lib/util/sszBytes.js.map +1 -1
  223. package/package.json +16 -15
  224. package/src/api/impl/beacon/blocks/index.ts +21 -5
  225. package/src/api/impl/beacon/pool/index.ts +83 -1
  226. package/src/api/impl/debug/index.ts +0 -1
  227. package/src/api/impl/lodestar/index.ts +1 -1
  228. package/src/api/impl/validator/index.ts +82 -1
  229. package/src/chain/blocks/blockInput/blockInput.ts +4 -1
  230. package/src/chain/blocks/importBlock.ts +16 -48
  231. package/src/chain/blocks/importExecutionPayload.ts +76 -30
  232. package/src/chain/blocks/index.ts +71 -22
  233. package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +37 -3
  234. package/src/chain/blocks/payloadEnvelopeInput/types.ts +18 -0
  235. package/src/chain/blocks/payloadEnvelopeProcessor.ts +2 -2
  236. package/src/chain/blocks/types.ts +4 -3
  237. package/src/chain/blocks/utils/chainSegment.ts +114 -17
  238. package/src/chain/blocks/verifyBlock.ts +70 -9
  239. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +6 -4
  240. package/src/chain/blocks/verifyBlocksSanityChecks.ts +26 -7
  241. package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +16 -8
  242. package/src/chain/blocks/verifyPayloadsDataAvailability.ts +7 -4
  243. package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +8 -17
  244. package/src/chain/chain.ts +55 -10
  245. package/src/chain/emitter.ts +0 -11
  246. package/src/chain/errors/blockError.ts +4 -1
  247. package/src/chain/errors/executionPayloadBid.ts +6 -0
  248. package/src/chain/errors/index.ts +1 -0
  249. package/src/chain/errors/proposerPreferences.ts +47 -0
  250. package/src/chain/initState.ts +9 -1
  251. package/src/chain/interface.ts +9 -1
  252. package/src/chain/opPools/payloadAttestationPool.ts +29 -8
  253. package/src/chain/prepareNextSlot.ts +36 -14
  254. package/src/chain/produceBlock/produceBlockBody.ts +57 -14
  255. package/src/chain/regen/interface.ts +1 -0
  256. package/src/chain/regen/queued.ts +2 -7
  257. package/src/chain/regen/regen.ts +2 -7
  258. package/src/chain/seenCache/index.ts +1 -0
  259. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +89 -21
  260. package/src/chain/seenCache/seenProposerPreferences.ts +32 -0
  261. package/src/chain/validation/block.ts +1 -0
  262. package/src/chain/validation/executionPayloadBid.ts +25 -8
  263. package/src/chain/validation/proposerPreferences.ts +110 -0
  264. package/src/metrics/metrics/lodestar.ts +4 -0
  265. package/src/network/gossip/interface.ts +6 -0
  266. package/src/network/gossip/scoringParameters.ts +14 -1
  267. package/src/network/gossip/topic.ts +6 -0
  268. package/src/network/interface.ts +1 -0
  269. package/src/network/network.ts +11 -0
  270. package/src/network/processor/gossipHandlers.ts +53 -17
  271. package/src/network/processor/gossipQueues/index.ts +5 -0
  272. package/src/network/processor/index.ts +6 -5
  273. package/src/network/reqresp/handlers/beaconBlocksByRange.ts +14 -6
  274. package/src/network/reqresp/handlers/blobSidecarsByRange.ts +11 -5
  275. package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +17 -5
  276. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +7 -4
  277. package/src/node/nodejs.ts +2 -2
  278. package/src/sync/constants.ts +4 -4
  279. package/src/sync/range/batch.ts +320 -67
  280. package/src/sync/range/chain.ts +89 -14
  281. package/src/sync/range/range.ts +34 -9
  282. package/src/sync/sync.ts +13 -1
  283. package/src/sync/types.ts +72 -0
  284. package/src/sync/unknownBlock.ts +928 -65
  285. package/src/sync/utils/downloadByRange.ts +378 -39
  286. package/src/sync/utils/downloadByRoot.ts +24 -2
  287. package/src/sync/utils/pendingBlocksTree.ts +0 -15
  288. package/src/util/sszBytes.ts +8 -6
@@ -4,7 +4,6 @@ import {routes} from "@lodestar/api";
4
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
- import {SignedExecutionPayloadEnvelope} from "@lodestar/types/gloas";
8
7
  import {PeerIdStr} from "../util/peerId.js";
9
8
  import {BlockInputSource, IBlockInput} from "./blocks/blockInput/types.js";
10
9
  import {PayloadEnvelopeInput} from "./blocks/payloadEnvelopeInput/payloadEnvelopeInput.js";
@@ -60,10 +59,6 @@ export enum ChainEvent {
60
59
  * Post-gloas, missing parent could be a SignedBeaconBlock and/or a SignedExecutionPayloadEnvelope
61
60
  */
62
61
  blockUnknownParent = "blockUnknownParent",
63
- /**
64
- * Trigger BlockInputSync to find a SignedBeaconBlock given a SignedExecutionPayloadEnvelop received
65
- */
66
- envelopeUnknownBlock = "envelopeUnknownBlock",
67
62
  /**
68
63
  * Trigger BlockInputSync to find a SignedBeaconBlock with specified block root.
69
64
  */
@@ -92,11 +87,6 @@ type ApiEvents = {[K in routes.events.EventType]: (data: routes.events.EventData
92
87
 
93
88
  export type ChainEventData = {
94
89
  [ChainEvent.blockUnknownParent]: {blockInput: IBlockInput; peer: PeerIdStr; source: BlockInputSource};
95
- [ChainEvent.envelopeUnknownBlock]: {
96
- envelope: SignedExecutionPayloadEnvelope;
97
- peer?: PeerIdStr;
98
- source: BlockInputSource;
99
- };
100
90
  [ChainEvent.unknownBlockRoot]: {rootHex: RootHex; peer?: PeerIdStr; source: BlockInputSource};
101
91
  [ChainEvent.incompleteBlockInput]: {blockInput: IBlockInput; peer: PeerIdStr; source: BlockInputSource};
102
92
  [ChainEvent.incompletePayloadEnvelope]: {
@@ -124,7 +114,6 @@ export type IChainEvents = ApiEvents & {
124
114
  // Sync events that are chain->chain. Initiated from network requests but do not cross the network
125
115
  // barrier so are considered ChainEvent(s).
126
116
  [ChainEvent.blockUnknownParent]: (data: ChainEventData[ChainEvent.blockUnknownParent]) => void;
127
- [ChainEvent.envelopeUnknownBlock]: (data: ChainEventData[ChainEvent.envelopeUnknownBlock]) => void;
128
117
  [ChainEvent.unknownBlockRoot]: (data: ChainEventData[ChainEvent.unknownBlockRoot]) => void;
129
118
  [ChainEvent.incompleteBlockInput]: (data: ChainEventData[ChainEvent.incompleteBlockInput]) => void;
130
119
  [ChainEvent.incompletePayloadEnvelope]: (data: ChainEventData[ChainEvent.incompletePayloadEnvelope]) => void;
@@ -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};
@@ -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,47 @@
1
+ import {RootHex, 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
+ UNKNOWN_DEPENDENT_ROOT = "PROPOSER_PREFERENCES_ERROR_UNKNOWN_DEPENDENT_ROOT",
8
+ INVALID_PROPOSER = "PROPOSER_PREFERENCES_ERROR_INVALID_PROPOSER",
9
+ ALREADY_KNOWN = "PROPOSER_PREFERENCES_ERROR_ALREADY_KNOWN",
10
+ INVALID_SIGNATURE = "PROPOSER_PREFERENCES_ERROR_INVALID_SIGNATURE",
11
+ }
12
+
13
+ export type ProposerPreferencesErrorType =
14
+ | {
15
+ code: ProposerPreferencesErrorCode.INVALID_EPOCH;
16
+ proposalSlot: Slot;
17
+ currentEpoch: number;
18
+ }
19
+ | {
20
+ code: ProposerPreferencesErrorCode.PROPOSAL_SLOT_PASSED;
21
+ proposalSlot: Slot;
22
+ currentSlot: Slot;
23
+ }
24
+ | {
25
+ code: ProposerPreferencesErrorCode.UNKNOWN_DEPENDENT_ROOT;
26
+ proposalSlot: Slot;
27
+ dependentRoot: RootHex;
28
+ }
29
+ | {
30
+ code: ProposerPreferencesErrorCode.INVALID_PROPOSER;
31
+ proposalSlot: Slot;
32
+ validatorIndex: ValidatorIndex;
33
+ dependentRoot: RootHex;
34
+ }
35
+ | {
36
+ code: ProposerPreferencesErrorCode.ALREADY_KNOWN;
37
+ proposalSlot: Slot;
38
+ validatorIndex: ValidatorIndex;
39
+ dependentRoot: RootHex;
40
+ }
41
+ | {
42
+ code: ProposerPreferencesErrorCode.INVALID_SIGNATURE;
43
+ proposalSlot: Slot;
44
+ validatorIndex: ValidatorIndex;
45
+ };
46
+
47
+ export class ProposerPreferencesError extends GossipActionError<ProposerPreferencesErrorType> {}
@@ -1,7 +1,8 @@
1
1
  import {ChainForkConfig} from "@lodestar/config";
2
- import {ZERO_HASH} from "@lodestar/params";
2
+ import {ForkPostGloas, ForkSeq, ZERO_HASH} from "@lodestar/params";
3
3
  import {
4
4
  BeaconStateAllForks,
5
+ BeaconStateGloas,
5
6
  IBeaconStateView,
6
7
  computeEpochAtSlot,
7
8
  computeStartSlotAtEpoch,
@@ -52,6 +53,13 @@ export function createGenesisBlock(config: ChainForkConfig, genesisState: Beacon
52
53
  const genesisBlock = types.SignedBeaconBlock.defaultValue();
53
54
  const stateRoot = genesisState.hashTreeRoot();
54
55
  genesisBlock.message.stateRoot = stateRoot;
56
+
57
+ if (config.getForkSeq(GENESIS_SLOT) >= ForkSeq.gloas) {
58
+ const gloasBlock = genesisBlock as SignedBeaconBlock<ForkPostGloas>;
59
+ const gloasState = genesisState as BeaconStateGloas;
60
+ gloasBlock.message.body.signedExecutionPayloadBid.message = gloasState.latestExecutionPayloadBid.toValue();
61
+ }
62
+
55
63
  return genesisBlock;
56
64
  }
57
65
 
@@ -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;
@@ -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
 
@@ -4,6 +4,7 @@ import {getSafeExecutionBlockHash} from "@lodestar/fork-choice";
4
4
  import {ForkPostBellatrix, ForkSeq, SLOTS_PER_EPOCH, isForkPostBellatrix} from "@lodestar/params";
5
5
  import {
6
6
  IBeaconStateView,
7
+ IBeaconStateViewBellatrix,
7
8
  StateHashTreeRootSource,
8
9
  computeEpochAtSlot,
9
10
  computeTimeAtSlot,
@@ -83,7 +84,7 @@ export class PrepareNextSlotScheduler {
83
84
  const headBlock = this.chain.recomputeForkChoiceHead(ForkchoiceCaller.prepareNextSlot);
84
85
  const {slot: headSlot, blockRoot: headRoot} = headBlock;
85
86
  // may be updated below if we predict a proposer-boost-reorg
86
- let updatedHeadRoot = headRoot;
87
+ let updatedHead = headBlock;
87
88
 
88
89
  // PS: previously this was comparing slots, but that gave no leway on the skipped
89
90
  // slots on epoch bounday. Making it more fluid.
@@ -148,7 +149,7 @@ export class PrepareNextSlotScheduler {
148
149
  {dontTransferCache: !isEpochTransition},
149
150
  RegenCaller.predictProposerHead
150
151
  );
151
- updatedHeadRoot = proposerHeadRoot;
152
+ updatedHead = proposerHead;
152
153
  }
153
154
 
154
155
  // Update the builder status, if enabled shoot an api call to check status
@@ -165,10 +166,22 @@ export class PrepareNextSlotScheduler {
165
166
  }
166
167
 
167
168
  let parentBlockHash: Bytes32;
169
+ // Apply parent payload once here as it's reused by EL prep and SSE emit below
170
+ let stateAfterParentPayload: IBeaconStateViewBellatrix = updatedPrepareState;
168
171
  if (isStatePostGloas(updatedPrepareState)) {
169
- parentBlockHash = this.chain.forkChoice.shouldExtendPayload(updatedHeadRoot)
170
- ? updatedPrepareState.latestExecutionPayloadBid.blockHash
171
- : updatedPrepareState.latestExecutionPayloadBid.parentBlockHash;
172
+ if (this.chain.forkChoice.shouldExtendPayload(updatedHead.blockRoot)) {
173
+ parentBlockHash = updatedPrepareState.latestExecutionPayloadBid.blockHash;
174
+ // Skip applying parent payload unless we're proposing the next slot or have to emit payload_attributes events
175
+ if (feeRecipient !== undefined || this.chain.opts.emitPayloadAttributes === true) {
176
+ const parentExecutionRequests = await this.chain.getParentExecutionRequests(
177
+ updatedHead.slot,
178
+ updatedHead.blockRoot
179
+ );
180
+ stateAfterParentPayload = updatedPrepareState.withParentPayloadApplied(parentExecutionRequests);
181
+ }
182
+ } else {
183
+ parentBlockHash = updatedPrepareState.latestExecutionPayloadBid.parentBlockHash;
184
+ }
172
185
  } else {
173
186
  parentBlockHash = updatedPrepareState.latestExecutionPayloadHeader.blockHash;
174
187
  }
@@ -189,11 +202,11 @@ export class PrepareNextSlotScheduler {
189
202
  this.chain,
190
203
  this.logger,
191
204
  fork as ForkPostBellatrix, // State is of execution type
192
- fromHex(updatedHeadRoot),
205
+ fromHex(updatedHead.blockRoot),
193
206
  parentBlockHash,
194
207
  safeBlockHash,
195
208
  finalizedBlockHash,
196
- updatedPrepareState,
209
+ stateAfterParentPayload,
197
210
  feeRecipient
198
211
  );
199
212
  this.logger.verbose("PrepareNextSlotScheduler prepared new payload", {
@@ -203,21 +216,30 @@ 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.pruneBelowParent(updatedHeadParent);
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
  ) {
213
237
  const data = getPayloadAttributesForSSE(fork as ForkPostBellatrix, this.chain, {
214
- prepareState: updatedPrepareState,
238
+ prepareState: stateAfterParentPayload,
215
239
  prepareSlot,
216
- parentBlockRoot: fromHex(headRoot),
240
+ parentBlockRoot: fromHex(updatedHead.blockRoot),
217
241
  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",
242
+ feeRecipient: feeRecipient ?? "0x0000000000000000000000000000000000000000",
221
243
  });
222
244
  this.chain.emitter.emit(routes.events.EventType.payloadAttributes, {data, version: fork});
223
245
  }
@@ -111,6 +111,7 @@ export type ProduceFullGloas = {
111
111
  executionRequests: electra.ExecutionRequests;
112
112
  blobsBundle: BlobsBundle<ForkPostGloas>;
113
113
  cells: fulu.Cell[][];
114
+ parentBlockRoot: Root;
114
115
  };
115
116
  export type ProduceFullFulu = {
116
117
  type: BlockType.Full;
@@ -214,9 +215,19 @@ export async function produceBlockBody<T extends BlockType>(
214
215
  });
215
216
 
216
217
  // Get execution payload from EL
217
- const parentBlockHash = this.forkChoice.shouldExtendPayload(toRootHex(parentBlockRoot))
218
- ? currentState.latestExecutionPayloadBid.blockHash
219
- : currentState.latestExecutionPayloadBid.parentBlockHash;
218
+ let parentBlockHash: Bytes32;
219
+ let parentExecutionRequests: electra.ExecutionRequests;
220
+ // Apply parent payload once here as it's reused by EL prep and voluntary exit filtering below
221
+ let stateAfterParentPayload: IBeaconStateViewBellatrix = currentState;
222
+ const isExtendingPayload = this.forkChoice.shouldExtendPayload(toRootHex(parentBlockRoot));
223
+ if (isExtendingPayload) {
224
+ parentBlockHash = currentState.latestExecutionPayloadBid.blockHash;
225
+ parentExecutionRequests = await this.getParentExecutionRequests(parentBlock.slot, parentBlock.blockRoot);
226
+ stateAfterParentPayload = currentState.withParentPayloadApplied(parentExecutionRequests);
227
+ } else {
228
+ parentBlockHash = currentState.latestExecutionPayloadBid.parentBlockHash;
229
+ parentExecutionRequests = ssz.electra.ExecutionRequests.defaultValue();
230
+ }
220
231
  const prepareRes = await prepareExecutionPayload(
221
232
  this,
222
233
  this.logger,
@@ -225,7 +236,7 @@ export async function produceBlockBody<T extends BlockType>(
225
236
  parentBlockHash,
226
237
  safeBlockHash,
227
238
  finalizedBlockHash ?? ZERO_HASH_HEX,
228
- currentState,
239
+ stateAfterParentPayload,
229
240
  feeRecipient
230
241
  );
231
242
 
@@ -280,9 +291,19 @@ export async function produceBlockBody<T extends BlockType>(
280
291
  const commonBlockBody = await commonBlockBodyPromise;
281
292
  const gloasBody = Object.assign({}, commonBlockBody) as gloas.BeaconBlockBody;
282
293
  gloasBody.signedExecutionPayloadBid = signedBid;
283
- // TODO GLOAS: Get payload attestations from pool for previous slot
284
- gloasBody.payloadAttestations = [];
285
- // TODO GLOAS: set parentExecutionRequests in the block body
294
+ gloasBody.payloadAttestations = this.payloadAttestationPool.getPayloadAttestationsForBlock(
295
+ parentBlock.blockRoot,
296
+ blockSlot - 1
297
+ );
298
+ gloasBody.parentExecutionRequests = parentExecutionRequests;
299
+ // Drop voluntary exits that parent_execution_requests have invalidated (e.g. a withdrawal
300
+ // request initiating an exit on the same validator). Op pool selected against the unapplied
301
+ // state, so re-validate against the post-apply state to avoid producing an invalid block.
302
+ if (isExtendingPayload && commonBlockBody.voluntaryExits.length > 0) {
303
+ gloasBody.voluntaryExits = commonBlockBody.voluntaryExits.filter((signedVoluntaryExit) =>
304
+ stateAfterParentPayload.isValidVoluntaryExit(signedVoluntaryExit, false)
305
+ );
306
+ }
286
307
  blockBody = gloasBody as AssembledBodyType<T>;
287
308
 
288
309
  // Store execution payload data required to construct execution payload envelope later
@@ -291,6 +312,7 @@ export async function produceBlockBody<T extends BlockType>(
291
312
  gloasResult.executionRequests = executionRequests;
292
313
  gloasResult.blobsBundle = blobsBundle;
293
314
  gloasResult.cells = cells;
315
+ gloasResult.parentBlockRoot = fromHex(parentBlock.blockRoot);
294
316
 
295
317
  const fetchedTime = Date.now() / 1000 - computeTimeAtSlot(this.config, blockSlot, this.genesisTime);
296
318
  this.metrics?.blockPayload.payloadFetchedTime.observe({prepType}, fetchedTime);
@@ -618,6 +640,10 @@ export async function prepareExecutionPayload(
618
640
  parentBlockHash: Bytes32,
619
641
  safeBlockHash: RootHex,
620
642
  finalizedBlockHash: RootHex,
643
+ /**
644
+ * Post-gloas, when extending a full parent, callers must apply
645
+ * parent execution payload first (see `withParentPayloadApplied`).
646
+ */
621
647
  state: IBeaconStateViewBellatrix,
622
648
  suggestedFeeRecipient: string
623
649
  ): Promise<{prepType: PayloadPreparationType; payloadId: PayloadId}> {
@@ -715,6 +741,10 @@ export function getPayloadAttributesForSSE(
715
741
  parentBlockHash,
716
742
  feeRecipient,
717
743
  }: {
744
+ /**
745
+ * Post-gloas, when extending a full parent, callers must apply
746
+ * parent execution payload first (see `withParentPayloadApplied`).
747
+ */
718
748
  prepareState: IBeaconStateViewBellatrix;
719
749
  prepareSlot: Slot;
720
750
  parentBlockRoot: Root;
@@ -767,6 +797,10 @@ function preparePayloadAttributes(
767
797
  parentBlockHash,
768
798
  feeRecipient,
769
799
  }: {
800
+ /**
801
+ * Post-gloas, when extending a full parent, callers must apply
802
+ * parent execution payload first (see `withParentPayloadApplied`).
803
+ */
770
804
  prepareState: IBeaconStateViewBellatrix;
771
805
  prepareSlot: Slot;
772
806
  parentBlockRoot: Root;
@@ -789,13 +823,22 @@ function preparePayloadAttributes(
789
823
 
790
824
  if (isStatePostGloas(prepareState)) {
791
825
  const isExtendingPayload = byteArrayEquals(parentBlockHash, prepareState.latestExecutionPayloadBid.blockHash);
792
- // When the parent block is empty, state.payloadExpectedWithdrawals holds a batch
793
- // already deducted from CL balances but never credited on the EL (the envelope
794
- // was not delivered). The next payload must carry those same withdrawals to
795
- // restore CL/EL consistency, otherwise validators permanently lose that balance.
796
- (payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals = isExtendingPayload
797
- ? prepareState.getExpectedWithdrawals().expectedWithdrawals
798
- : prepareState.payloadExpectedWithdrawals;
826
+ if (isExtendingPayload) {
827
+ // applyParentExecutionPayload sets latestBlockHash = parentBid.blockHash, so a mismatch
828
+ // here means the caller did not apply parent payload to prepareState
829
+ if (!byteArrayEquals(prepareState.latestBlockHash, prepareState.latestExecutionPayloadBid.blockHash)) {
830
+ throw new Error("Expected state with parent execution payload applied for withdrawals");
831
+ }
832
+ (payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
833
+ prepareState.getExpectedWithdrawals().expectedWithdrawals;
834
+ } else {
835
+ // When the parent block is empty, state.payloadExpectedWithdrawals holds a batch
836
+ // already deducted from CL balances but never credited on the EL (the envelope
837
+ // was not delivered). The next payload must carry those same withdrawals to
838
+ // restore CL/EL consistency, otherwise validators permanently lose that balance.
839
+ (payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
840
+ prepareState.payloadExpectedWithdrawals;
841
+ }
799
842
  } else {
800
843
  // withdrawals logic is now fork aware as it changes on electra fork post capella
801
844
  (payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
@@ -21,6 +21,7 @@ export enum RegenCaller {
21
21
  validateGossipAttestation = "validateGossipAttestation",
22
22
  validateGossipVoluntaryExit = "validateGossipVoluntaryExit",
23
23
  validateGossipExecutionPayloadBid = "validateGossipExecutionPayloadBid",
24
+ validateGossipProposerPreferences = "validateGossipProposerPreferences",
24
25
  onForkChoiceFinalized = "onForkChoiceFinalized",
25
26
  restApi = "restApi",
26
27
  }
@@ -1,7 +1,7 @@
1
1
  import {routes} from "@lodestar/api";
2
2
  import {IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
3
3
  import {IBeaconStateView, computeEpochAtSlot} from "@lodestar/state-transition";
4
- import {BeaconBlock, Epoch, RootHex, Slot, isGloasBeaconBlock, phase0} from "@lodestar/types";
4
+ import {BeaconBlock, Epoch, RootHex, Slot, phase0} from "@lodestar/types";
5
5
  import {Logger, toRootHex} from "@lodestar/utils";
6
6
  import {Metrics} from "../../metrics/index.js";
7
7
  import {JobItemQueue} from "../../util/queue/index.js";
@@ -88,12 +88,7 @@ export class QueuedStateRegenerator implements IStateRegenerator {
88
88
  */
89
89
  getPreStateSync(block: BeaconBlock): IBeaconStateView | null {
90
90
  const parentRoot = toRootHex(block.parentRoot);
91
- const parentBlock = isGloasBeaconBlock(block)
92
- ? this.forkChoice.getBlockHexAndBlockHash(
93
- parentRoot,
94
- toRootHex(block.body.signedExecutionPayloadBid.message.parentBlockHash)
95
- )
96
- : this.forkChoice.getBlockHexDefaultStatus(parentRoot);
91
+ const parentBlock = this.forkChoice.getBlockHexDefaultStatus(parentRoot);
97
92
  if (!parentBlock) {
98
93
  throw new RegenError({
99
94
  code: RegenErrorCode.BLOCK_NOT_IN_FORKCHOICE,
@@ -9,7 +9,7 @@ import {
9
9
  computeEpochAtSlot,
10
10
  computeStartSlotAtEpoch,
11
11
  } from "@lodestar/state-transition";
12
- import {BeaconBlock, RootHex, SignedBeaconBlock, Slot, isGloasBeaconBlock} from "@lodestar/types";
12
+ import {BeaconBlock, RootHex, SignedBeaconBlock, Slot} from "@lodestar/types";
13
13
  import {Logger, fromHex, toRootHex} from "@lodestar/utils";
14
14
  import {IBeaconDb} from "../../db/index.js";
15
15
  import {Metrics} from "../../metrics/index.js";
@@ -57,12 +57,7 @@ export class StateRegenerator implements IStateRegeneratorInternal {
57
57
  regenCaller: RegenCaller
58
58
  ): Promise<IBeaconStateView> {
59
59
  const parentRoot = toRootHex(block.parentRoot);
60
- const parentBlock = isGloasBeaconBlock(block)
61
- ? this.modules.forkChoice.getBlockHexAndBlockHash(
62
- parentRoot,
63
- toRootHex(block.body.signedExecutionPayloadBid.message.parentBlockHash)
64
- )
65
- : this.modules.forkChoice.getBlockHexDefaultStatus(parentRoot);
60
+ const parentBlock = this.modules.forkChoice.getBlockHexDefaultStatus(parentRoot);
66
61
  if (!parentBlock) {
67
62
  throw new RegenError({
68
63
  code: RegenErrorCode.BLOCK_NOT_IN_FORKCHOICE,
@@ -5,3 +5,4 @@ export {SeenContributionAndProof} from "./seenCommitteeContribution.js";
5
5
  export {SeenExecutionPayloadBids} from "./seenExecutionPayloadBids.js";
6
6
  export {SeenBlockInput} from "./seenGossipBlockInput.js";
7
7
  export {PayloadEnvelopeInput, SeenPayloadEnvelopeInput} from "./seenPayloadEnvelopeInput.js";
8
+ export {SeenProposerPreferences} from "./seenProposerPreferences.js";