@lodestar/beacon-node 1.43.0-dev.78c66bac71 → 1.43.0-dev.87cbe69c66

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 (260) 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/importBlock.d.ts.map +1 -1
  16. package/lib/chain/blocks/importBlock.js +24 -20
  17. package/lib/chain/blocks/importBlock.js.map +1 -1
  18. package/lib/chain/blocks/importExecutionPayload.d.ts +19 -6
  19. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  20. package/lib/chain/blocks/importExecutionPayload.js +45 -23
  21. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  22. package/lib/chain/blocks/index.d.ts +5 -3
  23. package/lib/chain/blocks/index.d.ts.map +1 -1
  24. package/lib/chain/blocks/index.js +59 -25
  25. package/lib/chain/blocks/index.js.map +1 -1
  26. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +1 -0
  27. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
  28. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +5 -1
  29. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
  30. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +1 -0
  31. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
  32. package/lib/chain/blocks/payloadEnvelopeProcessor.js +2 -2
  33. package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
  34. package/lib/chain/blocks/types.d.ts +4 -3
  35. package/lib/chain/blocks/types.d.ts.map +1 -1
  36. package/lib/chain/blocks/utils/chainSegment.d.ts +23 -2
  37. package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
  38. package/lib/chain/blocks/utils/chainSegment.js +89 -12
  39. package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
  40. package/lib/chain/blocks/verifyBlock.d.ts +5 -3
  41. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  42. package/lib/chain/blocks/verifyBlock.js +50 -7
  43. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  44. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +0 -4
  45. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  46. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +5 -2
  47. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  48. package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts +2 -1
  49. package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
  50. package/lib/chain/blocks/verifyBlocksSanityChecks.js +25 -5
  51. package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
  52. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +2 -2
  53. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -1
  54. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +7 -4
  55. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -1
  56. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -1
  57. package/lib/chain/blocks/verifyPayloadsDataAvailability.js +8 -3
  58. package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -1
  59. package/lib/chain/chain.d.ts +3 -2
  60. package/lib/chain/chain.d.ts.map +1 -1
  61. package/lib/chain/chain.js +12 -4
  62. package/lib/chain/chain.js.map +1 -1
  63. package/lib/chain/emitter.d.ts +0 -11
  64. package/lib/chain/emitter.d.ts.map +1 -1
  65. package/lib/chain/emitter.js +0 -4
  66. package/lib/chain/emitter.js.map +1 -1
  67. package/lib/chain/errors/blockError.d.ts +8 -1
  68. package/lib/chain/errors/blockError.d.ts.map +1 -1
  69. package/lib/chain/errors/blockError.js +2 -0
  70. package/lib/chain/errors/blockError.js.map +1 -1
  71. package/lib/chain/errors/index.d.ts +1 -0
  72. package/lib/chain/errors/index.d.ts.map +1 -1
  73. package/lib/chain/errors/index.js +1 -0
  74. package/lib/chain/errors/index.js.map +1 -1
  75. package/lib/chain/errors/proposerPreferences.d.ts +40 -0
  76. package/lib/chain/errors/proposerPreferences.d.ts.map +1 -0
  77. package/lib/chain/errors/proposerPreferences.js +14 -0
  78. package/lib/chain/errors/proposerPreferences.js.map +1 -0
  79. package/lib/chain/interface.d.ts +3 -2
  80. package/lib/chain/interface.d.ts.map +1 -1
  81. package/lib/chain/interface.js.map +1 -1
  82. package/lib/chain/opPools/payloadAttestationPool.d.ts +3 -2
  83. package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -1
  84. package/lib/chain/opPools/payloadAttestationPool.js +26 -4
  85. package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
  86. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  87. package/lib/chain/prepareNextSlot.js +15 -17
  88. package/lib/chain/prepareNextSlot.js.map +1 -1
  89. package/lib/chain/produceBlock/produceBlockBody.d.ts +12 -3
  90. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  91. package/lib/chain/produceBlock/produceBlockBody.js +35 -17
  92. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  93. package/lib/chain/regen/interface.d.ts +1 -0
  94. package/lib/chain/regen/interface.d.ts.map +1 -1
  95. package/lib/chain/regen/interface.js +1 -0
  96. package/lib/chain/regen/interface.js.map +1 -1
  97. package/lib/chain/regen/queued.d.ts.map +1 -1
  98. package/lib/chain/regen/queued.js +1 -4
  99. package/lib/chain/regen/queued.js.map +1 -1
  100. package/lib/chain/regen/regen.d.ts.map +1 -1
  101. package/lib/chain/regen/regen.js +1 -4
  102. package/lib/chain/regen/regen.js.map +1 -1
  103. package/lib/chain/seenCache/index.d.ts +1 -0
  104. package/lib/chain/seenCache/index.d.ts.map +1 -1
  105. package/lib/chain/seenCache/index.js +1 -0
  106. package/lib/chain/seenCache/index.js.map +1 -1
  107. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +8 -2
  108. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
  109. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +20 -4
  110. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
  111. package/lib/chain/seenCache/seenProposerPreferences.d.ts +16 -0
  112. package/lib/chain/seenCache/seenProposerPreferences.d.ts.map +1 -0
  113. package/lib/chain/seenCache/seenProposerPreferences.js +31 -0
  114. package/lib/chain/seenCache/seenProposerPreferences.js.map +1 -0
  115. package/lib/chain/validation/block.d.ts.map +1 -1
  116. package/lib/chain/validation/block.js +1 -0
  117. package/lib/chain/validation/block.js.map +1 -1
  118. package/lib/chain/validation/executionPayloadBid.js +11 -8
  119. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  120. package/lib/chain/validation/proposerPreferences.d.ts +8 -0
  121. package/lib/chain/validation/proposerPreferences.d.ts.map +1 -0
  122. package/lib/chain/validation/proposerPreferences.js +91 -0
  123. package/lib/chain/validation/proposerPreferences.js.map +1 -0
  124. package/lib/metrics/metrics/lodestar.d.ts +1 -0
  125. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  126. package/lib/metrics/metrics/lodestar.js +4 -0
  127. package/lib/metrics/metrics/lodestar.js.map +1 -1
  128. package/lib/network/gossip/interface.d.ts +7 -1
  129. package/lib/network/gossip/interface.d.ts.map +1 -1
  130. package/lib/network/gossip/interface.js +1 -0
  131. package/lib/network/gossip/interface.js.map +1 -1
  132. package/lib/network/gossip/scoringParameters.d.ts.map +1 -1
  133. package/lib/network/gossip/scoringParameters.js +12 -1
  134. package/lib/network/gossip/scoringParameters.js.map +1 -1
  135. package/lib/network/gossip/topic.d.ts +10 -0
  136. package/lib/network/gossip/topic.d.ts.map +1 -1
  137. package/lib/network/gossip/topic.js +6 -0
  138. package/lib/network/gossip/topic.js.map +1 -1
  139. package/lib/network/interface.d.ts +1 -0
  140. package/lib/network/interface.d.ts.map +1 -1
  141. package/lib/network/network.d.ts +1 -0
  142. package/lib/network/network.d.ts.map +1 -1
  143. package/lib/network/network.js +5 -0
  144. package/lib/network/network.js.map +1 -1
  145. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  146. package/lib/network/processor/gossipHandlers.js +24 -16
  147. package/lib/network/processor/gossipHandlers.js.map +1 -1
  148. package/lib/network/processor/gossipQueues/index.d.ts.map +1 -1
  149. package/lib/network/processor/gossipQueues/index.js +5 -0
  150. package/lib/network/processor/gossipQueues/index.js.map +1 -1
  151. package/lib/network/processor/index.d.ts.map +1 -1
  152. package/lib/network/processor/index.js +6 -5
  153. package/lib/network/processor/index.js.map +1 -1
  154. package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
  155. package/lib/network/reqresp/handlers/beaconBlocksByRange.js +14 -6
  156. package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
  157. package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts.map +1 -1
  158. package/lib/network/reqresp/handlers/blobSidecarsByRange.js +11 -5
  159. package/lib/network/reqresp/handlers/blobSidecarsByRange.js.map +1 -1
  160. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
  161. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +17 -5
  162. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
  163. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -1
  164. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +7 -4
  165. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
  166. package/lib/node/nodejs.js +2 -2
  167. package/lib/node/nodejs.js.map +1 -1
  168. package/lib/sync/range/batch.d.ts +23 -2
  169. package/lib/sync/range/batch.d.ts.map +1 -1
  170. package/lib/sync/range/batch.js +84 -33
  171. package/lib/sync/range/batch.js.map +1 -1
  172. package/lib/sync/range/chain.d.ts +6 -2
  173. package/lib/sync/range/chain.d.ts.map +1 -1
  174. package/lib/sync/range/chain.js +26 -7
  175. package/lib/sync/range/chain.js.map +1 -1
  176. package/lib/sync/range/range.d.ts.map +1 -1
  177. package/lib/sync/range/range.js +17 -6
  178. package/lib/sync/range/range.js.map +1 -1
  179. package/lib/sync/types.d.ts +34 -0
  180. package/lib/sync/types.d.ts.map +1 -1
  181. package/lib/sync/types.js +34 -0
  182. package/lib/sync/types.js.map +1 -1
  183. package/lib/sync/unknownBlock.d.ts +22 -1
  184. package/lib/sync/unknownBlock.d.ts.map +1 -1
  185. package/lib/sync/unknownBlock.js +602 -53
  186. package/lib/sync/unknownBlock.js.map +1 -1
  187. package/lib/sync/utils/downloadByRange.d.ts +46 -10
  188. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  189. package/lib/sync/utils/downloadByRange.js +164 -24
  190. package/lib/sync/utils/downloadByRange.js.map +1 -1
  191. package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
  192. package/lib/sync/utils/downloadByRoot.js +16 -2
  193. package/lib/sync/utils/downloadByRoot.js.map +1 -1
  194. package/lib/sync/utils/pendingBlocksTree.d.ts +0 -1
  195. package/lib/sync/utils/pendingBlocksTree.d.ts.map +1 -1
  196. package/lib/sync/utils/pendingBlocksTree.js +0 -9
  197. package/lib/sync/utils/pendingBlocksTree.js.map +1 -1
  198. package/lib/util/sszBytes.d.ts.map +1 -1
  199. package/lib/util/sszBytes.js +8 -6
  200. package/lib/util/sszBytes.js.map +1 -1
  201. package/package.json +16 -15
  202. package/src/api/impl/beacon/blocks/index.ts +21 -5
  203. package/src/api/impl/beacon/pool/index.ts +83 -1
  204. package/src/api/impl/debug/index.ts +0 -1
  205. package/src/api/impl/lodestar/index.ts +1 -1
  206. package/src/api/impl/validator/index.ts +82 -1
  207. package/src/chain/blocks/importBlock.ts +24 -38
  208. package/src/chain/blocks/importExecutionPayload.ts +59 -25
  209. package/src/chain/blocks/index.ts +73 -22
  210. package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +6 -1
  211. package/src/chain/blocks/payloadEnvelopeInput/types.ts +1 -0
  212. package/src/chain/blocks/payloadEnvelopeProcessor.ts +2 -2
  213. package/src/chain/blocks/types.ts +4 -3
  214. package/src/chain/blocks/utils/chainSegment.ts +114 -17
  215. package/src/chain/blocks/verifyBlock.ts +70 -9
  216. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +6 -4
  217. package/src/chain/blocks/verifyBlocksSanityChecks.ts +26 -7
  218. package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +9 -4
  219. package/src/chain/blocks/verifyPayloadsDataAvailability.ts +7 -4
  220. package/src/chain/chain.ts +16 -3
  221. package/src/chain/emitter.ts +0 -11
  222. package/src/chain/errors/blockError.ts +4 -1
  223. package/src/chain/errors/index.ts +1 -0
  224. package/src/chain/errors/proposerPreferences.ts +47 -0
  225. package/src/chain/interface.ts +7 -1
  226. package/src/chain/opPools/payloadAttestationPool.ts +29 -8
  227. package/src/chain/prepareNextSlot.ts +20 -28
  228. package/src/chain/produceBlock/produceBlockBody.ts +46 -22
  229. package/src/chain/regen/interface.ts +1 -0
  230. package/src/chain/regen/queued.ts +2 -7
  231. package/src/chain/regen/regen.ts +2 -7
  232. package/src/chain/seenCache/index.ts +1 -0
  233. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +25 -5
  234. package/src/chain/seenCache/seenProposerPreferences.ts +37 -0
  235. package/src/chain/validation/block.ts +1 -0
  236. package/src/chain/validation/executionPayloadBid.ts +11 -8
  237. package/src/chain/validation/proposerPreferences.ts +110 -0
  238. package/src/metrics/metrics/lodestar.ts +4 -0
  239. package/src/network/gossip/interface.ts +6 -0
  240. package/src/network/gossip/scoringParameters.ts +14 -1
  241. package/src/network/gossip/topic.ts +6 -0
  242. package/src/network/interface.ts +1 -0
  243. package/src/network/network.ts +11 -0
  244. package/src/network/processor/gossipHandlers.ts +35 -17
  245. package/src/network/processor/gossipQueues/index.ts +5 -0
  246. package/src/network/processor/index.ts +6 -5
  247. package/src/network/reqresp/handlers/beaconBlocksByRange.ts +14 -6
  248. package/src/network/reqresp/handlers/blobSidecarsByRange.ts +11 -5
  249. package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +17 -5
  250. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +7 -4
  251. package/src/node/nodejs.ts +2 -2
  252. package/src/sync/range/batch.ts +142 -38
  253. package/src/sync/range/chain.ts +37 -9
  254. package/src/sync/range/range.ts +18 -6
  255. package/src/sync/types.ts +72 -0
  256. package/src/sync/unknownBlock.ts +760 -57
  257. package/src/sync/utils/downloadByRange.ts +274 -39
  258. package/src/sync/utils/downloadByRoot.ts +24 -2
  259. package/src/sync/utils/pendingBlocksTree.ts +0 -15
  260. package/src/util/sszBytes.ts +8 -6
@@ -1,12 +1,14 @@
1
1
  import {ExecutionStatus, ProtoBlock} from "@lodestar/fork-choice";
2
- import {ForkName, isForkPostFulu} from "@lodestar/params";
2
+ import {ForkName, ForkSeq, isForkPostFulu} from "@lodestar/params";
3
3
  import {DataAvailabilityStatus, IBeaconStateView, computeEpochAtSlot} from "@lodestar/state-transition";
4
- import {IndexedAttestation, deneb} from "@lodestar/types";
4
+ import {IndexedAttestation, Slot, deneb} from "@lodestar/types";
5
+ import {getBlobKzgCommitments} from "../../util/dataColumns.js";
5
6
  import type {BeaconChain} from "../chain.js";
6
7
  import {BlockError, BlockErrorCode} from "../errors/index.js";
7
8
  import {BlockProcessOpts} from "../options.js";
8
9
  import {RegenCaller} from "../regen/index.js";
9
10
  import {DAType, IBlockInput} from "./blockInput/index.js";
11
+ import {PayloadEnvelopeInput} from "./payloadEnvelopeInput/payloadEnvelopeInput.js";
10
12
  import {ImportBlockOpts} from "./types.js";
11
13
  import {DENEB_BLOWFISH_BANNER} from "./utils/blowfishBanner.js";
12
14
  import {ELECTRA_GIRAFFE_BANNER} from "./utils/giraffeBanner.js";
@@ -16,6 +18,7 @@ import {verifyBlocksDataAvailability} from "./verifyBlocksDataAvailability.js";
16
18
  import {SegmentExecStatus, verifyBlocksExecutionPayload} from "./verifyBlocksExecutionPayloads.js";
17
19
  import {verifyBlocksSignatures} from "./verifyBlocksSignatures.js";
18
20
  import {verifyBlocksStateTransitionOnly} from "./verifyBlocksStateTransitionOnly.js";
21
+ import {verifyPayloadsDataAvailability} from "./verifyPayloadsDataAvailability.js";
19
22
 
20
23
  /**
21
24
  * Verifies 1 or more blocks are fully valid; from a linear sequence of blocks.
@@ -32,12 +35,14 @@ export async function verifyBlocksInEpoch(
32
35
  this: BeaconChain,
33
36
  parentBlock: ProtoBlock,
34
37
  blockInputs: IBlockInput[],
38
+ payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
35
39
  opts: BlockProcessOpts & ImportBlockOpts
36
40
  ): Promise<{
37
41
  postStates: IBeaconStateView[];
38
42
  proposerBalanceDeltas: number[];
39
43
  segmentExecStatus: SegmentExecStatus;
40
- dataAvailabilityStatuses: DataAvailabilityStatus[];
44
+ blockDAStatuses: DataAvailabilityStatus[];
45
+ payloadDAStatuses: Map<Slot, DataAvailabilityStatus>;
41
46
  indexedAttestationsByBlock: IndexedAttestation[][];
42
47
  }> {
43
48
  const blocks = blockInputs.map((blockInput) => blockInput.getBlock());
@@ -110,17 +115,61 @@ export async function verifyBlocksInEpoch(
110
115
  });
111
116
  }
112
117
 
118
+ // Pick the data-availability source by fork:
119
+ // - Pre-Gloas: blob/Fulu-column data lives in IBlockInput → verifyBlocksDataAvailability.
120
+ // - Post-Gloas: verifyPayloadsDataAvailability (payload-level DA, keyed by slot).
121
+ const daAvailabilityPromise: Promise<{
122
+ blockDAStatuses: DataAvailabilityStatus[];
123
+ payloadDAStatuses: Map<Slot, DataAvailabilityStatus>;
124
+ availableTime: number;
125
+ }> =
126
+ fork >= ForkSeq.gloas
127
+ ? (async () => {
128
+ // Validate DA for ALL payloads in the Map, not just those paired with blockInputs.
129
+ // A checkpoint-sync batch may include a payload for a slot whose block was filtered
130
+ // out of relevantBlocks (e.g., the anchor at the finalized slot); that payload still
131
+ // needs DA validation so it can be imported in processBlocks.
132
+ const payloadInputsForDa: PayloadEnvelopeInput[] =
133
+ payloadEnvelopes !== null ? Array.from(payloadEnvelopes.values()) : [];
134
+ const {dataAvailabilityStatuses, availableTime} = await verifyPayloadsDataAvailability(
135
+ payloadInputsForDa,
136
+ abortController.signal
137
+ );
138
+
139
+ const payloadDAStatuses = new Map<Slot, DataAvailabilityStatus>();
140
+ for (let i = 0; i < payloadInputsForDa.length; i++) {
141
+ payloadDAStatuses.set(payloadInputsForDa[i].slot, dataAvailabilityStatuses[i]);
142
+ }
143
+ return {
144
+ // post-gloas, DataAvailabilityStatus is NotRequired for forkChoice.onBlock() ProtoBlock
145
+ blockDAStatuses: blockInputs.map(() => DataAvailabilityStatus.NotRequired),
146
+ payloadDAStatuses,
147
+ availableTime,
148
+ };
149
+ })()
150
+ : (async () => {
151
+ const {dataAvailabilityStatuses, availableTime} = await verifyBlocksDataAvailability(
152
+ blockInputs,
153
+ abortController.signal
154
+ );
155
+ return {
156
+ blockDAStatuses: dataAvailabilityStatuses,
157
+ payloadDAStatuses: new Map<Slot, DataAvailabilityStatus>(),
158
+ availableTime,
159
+ };
160
+ })();
161
+
113
162
  // batch all I/O operations to reduce overhead
114
163
  const [
115
164
  segmentExecStatus,
116
- {dataAvailabilityStatuses, availableTime},
165
+ {blockDAStatuses, payloadDAStatuses, availableTime},
117
166
  {postStates, proposerBalanceDeltas, verifyStateTime},
118
167
  {verifySignaturesTime},
119
168
  ] = await Promise.all([
120
169
  verifyExecutionPayloadsPromise,
121
170
 
122
- // data availability for the blobs
123
- verifyBlocksDataAvailability(blockInputs, abortController.signal),
171
+ // data availability (fork-specific; see daAvailabilityPromise above)
172
+ daAvailabilityPromise,
124
173
 
125
174
  // Run state transition only
126
175
  // TODO: Ensure it yields to allow flushing to workers and engine API
@@ -149,6 +198,9 @@ export async function verifyBlocksInEpoch(
149
198
  opts
150
199
  )
151
200
  : Promise.resolve({verifySignaturesTime: Date.now()}),
201
+
202
+ // TODO GLOAS: can verify payload signatures in batch too
203
+ // maybe chain with the above verifyBlocksSignatures()
152
204
  ]);
153
205
 
154
206
  if (opts.verifyOnly !== true) {
@@ -200,7 +252,9 @@ export async function verifyBlocksInEpoch(
200
252
  blockInputs.length === 1 &&
201
253
  // gossip blocks have seenTimestampSec
202
254
  opts.seenTimestampSec !== undefined &&
255
+ // PreData (pre-deneb) and NoData (gloas) carry no blob data on the block — skip metric
203
256
  blockInputs[0].type !== DAType.PreData &&
257
+ blockInputs[0].type !== DAType.NoData &&
204
258
  executionStatuses[0] === ExecutionStatus.Valid
205
259
  ) {
206
260
  // Find the max time when the block was actually verified
@@ -209,8 +263,8 @@ export async function verifyBlocksInEpoch(
209
263
  this.metrics?.gossipBlock.receivedToFullyVerifiedTime.observe(recvTofullyVerifedTime);
210
264
 
211
265
  const verifiedToBlobsAvailabiltyTime = Math.max(availableTime - fullyVerifiedTime, 0) / 1000;
212
- const block = blockInputs[0].getBlock() as deneb.SignedBeaconBlock;
213
- const numBlobs = block.message.body.blobKzgCommitments.length;
266
+ const block = blockInputs[0].getBlock();
267
+ const numBlobs = getBlobKzgCommitments(blockInputs[0].forkName, block as deneb.SignedBeaconBlock).length;
214
268
 
215
269
  this.metrics?.gossipBlock.verifiedToBlobsAvailabiltyTime.observe({numBlobs}, verifiedToBlobsAvailabiltyTime);
216
270
  this.logger.verbose("Verified blockInput fully with blobs availability", {
@@ -229,7 +283,14 @@ export async function verifyBlocksInEpoch(
229
283
  );
230
284
  }
231
285
 
232
- return {postStates, dataAvailabilityStatuses, proposerBalanceDeltas, segmentExecStatus, indexedAttestationsByBlock};
286
+ return {
287
+ postStates,
288
+ blockDAStatuses,
289
+ payloadDAStatuses,
290
+ proposerBalanceDeltas,
291
+ segmentExecStatus,
292
+ indexedAttestationsByBlock,
293
+ };
233
294
  } finally {
234
295
  abortController.abort();
235
296
  }
@@ -46,8 +46,7 @@ type VerifyBlockExecutionResponse =
46
46
  | VerifyExecutionErrorResponse
47
47
  | {executionStatus: ExecutionStatus.Valid; lvhResponse: LVHValidResponse; execError: null}
48
48
  | {executionStatus: ExecutionStatus.Syncing; lvhResponse?: LVHValidResponse; execError: null}
49
- | {executionStatus: ExecutionStatus.PreMerge; lvhResponse: undefined; execError: null}
50
- | {executionStatus: ExecutionStatus.PayloadSeparated; lvhResponse: undefined; execError: null};
49
+ | {executionStatus: ExecutionStatus.PreMerge; lvhResponse: undefined; execError: null};
51
50
 
52
51
  /**
53
52
  * Verifies 1 or more execution payloads from a linear sequence of blocks.
@@ -145,9 +144,10 @@ export async function verifyBlockExecutionPayload(
145
144
  ): Promise<VerifyBlockExecutionResponse> {
146
145
  const block = blockInput.getBlock();
147
146
 
148
- // Gloas block doesn't have execution payload. Return right away
147
+ // Gloas block doesn't have execution payload. Return Syncing as a placeholder; the actual
148
+ // status for gloas PENDING/EMPTY is derived from parent's chain in importBlock.
149
149
  if (isBlockInputNoData(blockInput)) {
150
- return {executionStatus: ExecutionStatus.PayloadSeparated, lvhResponse: undefined, execError: null};
150
+ return {executionStatus: ExecutionStatus.Syncing, lvhResponse: undefined, execError: null};
151
151
  }
152
152
 
153
153
  /** Not null if execution is enabled */
@@ -198,6 +198,7 @@ export async function verifyBlockExecutionPayload(
198
198
  executionStatus,
199
199
  latestValidExecHash: execResult.latestValidHash,
200
200
  invalidateFromParentBlockRoot: blockInput.parentRootHex,
201
+ invalidateFromParentBlockHash: toRootHex(executionPayloadEnabled.parentHash),
201
202
  };
202
203
  const execError = new BlockError(block, {
203
204
  code: BlockErrorCode.EXECUTION_ENGINE_ERROR,
@@ -281,6 +282,7 @@ function getSegmentErrorResponse(
281
282
  executionStatus: ExecutionStatus.Invalid,
282
283
  latestValidExecHash: lvhResponse.latestValidExecHash,
283
284
  invalidateFromParentBlockRoot: parentBlock.blockRoot,
285
+ invalidateFromParentBlockHash: parentBlock.executionPayloadBlockHash,
284
286
  };
285
287
  }
286
288
  }
@@ -7,6 +7,7 @@ import {IClock} from "../../util/clock.js";
7
7
  import {BlockError, BlockErrorCode} from "../errors/index.js";
8
8
  import {IChainOptions} from "../options.js";
9
9
  import {IBlockInput} from "./blockInput/types.js";
10
+ import {PayloadEnvelopeInput} from "./payloadEnvelopeInput/payloadEnvelopeInput.js";
10
11
  import {ImportBlockOpts} from "./types.js";
11
12
 
12
13
  /**
@@ -30,6 +31,7 @@ export function verifyBlocksSanityChecks(
30
31
  blacklistedBlocks: Map<RootHex, Slot | null>;
31
32
  },
32
33
  blocks: IBlockInput[],
34
+ payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
33
35
  opts: ImportBlockOpts
34
36
  ): {
35
37
  relevantBlocks: IBlockInput[];
@@ -90,15 +92,32 @@ export function verifyBlocksSanityChecks(
90
92
  } else {
91
93
  // When importing a block segment, only the first NON-IGNORED block must be known to the fork-choice.
92
94
  const parentRoot = toRootHex(block.message.parentRoot);
93
- parentBlock = isGloasBeaconBlock(block.message)
94
- ? chain.forkChoice.getBlockHexAndBlockHash(
95
- parentRoot,
96
- toRootHex(block.message.body.signedExecutionPayloadBid.message.parentBlockHash)
97
- )
98
- : chain.forkChoice.getBlockHexDefaultStatus(parentRoot);
99
- if (!parentBlock) {
95
+ const parentBlockDefaultStatus = chain.forkChoice.getBlockHexDefaultStatus(parentRoot);
96
+ if (!parentBlockDefaultStatus) {
100
97
  throw new BlockError(block, {code: BlockErrorCode.PARENT_UNKNOWN, parentRoot});
101
98
  }
99
+
100
+ parentBlock = parentBlockDefaultStatus;
101
+ if (isGloasBeaconBlock(block.message)) {
102
+ const parentBlockHash = toRootHex(block.message.body.signedExecutionPayloadBid.message.parentBlockHash);
103
+ const parentBlockWithPayload = chain.forkChoice.getBlockHexAndBlockHash(parentRoot, parentBlockHash);
104
+ if (!parentBlockWithPayload) {
105
+ // Checkpoint sync: parent's FULL variant may not be in fork-choice yet because the
106
+ // anchor block is initialized with PENDING+EMPTY only. The parent's payload arrives
107
+ // in the same batch via payloadEnvelopes and will be imported by processBlocks. If
108
+ // a matching payload is in the Map, accept the parent as known.
109
+ const parentPayloadInput = payloadEnvelopes?.get(parentBlockDefaultStatus.slot);
110
+ if (parentPayloadInput?.getBlockHashHex() !== parentBlockHash) {
111
+ throw new BlockError(block, {
112
+ code: BlockErrorCode.PARENT_PAYLOAD_UNKNOWN,
113
+ parentRoot,
114
+ parentBlockHash,
115
+ });
116
+ }
117
+ } else {
118
+ parentBlock = parentBlockWithPayload;
119
+ }
120
+ }
102
121
  // Parent is known to the fork-choice
103
122
  parentBlockSlot = parentBlock.slot;
104
123
  }
@@ -20,7 +20,7 @@ export type VerifyExecutionPayloadEnvelopeOpts = {
20
20
  * performed outside this function, see `verifyExecutionPayloadEnvelopeSignature` and
21
21
  * `importExecutionPayload` which run both in parallel with this check.
22
22
  *
23
- * Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.5/specs/gloas/fork-choice.md#new-verify_execution_payload_envelope
23
+ * Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/fork-choice.md#new-verify_execution_payload_envelope
24
24
  */
25
25
  export function verifyExecutionPayloadEnvelope(
26
26
  config: BeaconConfig,
@@ -32,8 +32,8 @@ export function verifyExecutionPayloadEnvelope(
32
32
  const payload = envelope.payload;
33
33
 
34
34
  // Verify consistency with the beacon block.
35
- // Compute header root on a copy of latestBlockHeader to avoid mutating state.
36
- const headerValue = {...state.latestBlockHeader};
35
+ // Compute header root on a clone of latestBlockHeader to avoid mutating state.
36
+ const headerValue = ssz.phase0.BeaconBlockHeader.clone(state.latestBlockHeader);
37
37
  if (byteArrayEquals(headerValue.stateRoot, ssz.Root.defaultValue())) {
38
38
  headerValue.stateRoot = state.hashTreeRoot();
39
39
  }
@@ -43,6 +43,11 @@ export function verifyExecutionPayloadEnvelope(
43
43
  `Envelope's block is not the latest block header envelope=${toRootHex(envelope.beaconBlockRoot)} latestBlockHeader=${toRootHex(headerRoot)}`
44
44
  );
45
45
  }
46
+ if (!byteArrayEquals(envelope.parentBeaconBlockRoot, state.latestBlockHeader.parentRoot)) {
47
+ throw new Error(
48
+ `Envelope's parent_beacon_block_root mismatch envelope=${toRootHex(envelope.parentBeaconBlockRoot)} state=${toRootHex(state.latestBlockHeader.parentRoot)}`
49
+ );
50
+ }
46
51
 
47
52
  // Verify consistency with the committed bid
48
53
  const bid = state.latestExecutionPayloadBid;
@@ -108,7 +113,7 @@ export function verifyExecutionPayloadEnvelope(
108
113
  /**
109
114
  * Verify the BLS signature of an execution payload envelope.
110
115
  *
111
- * Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.5/specs/gloas/fork-choice.md#new-verify_execution_payload_envelope_signature
116
+ * Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/fork-choice.md#new-verify_execution_payload_envelope_signature
112
117
  */
113
118
  export async function verifyExecutionPayloadEnvelopeSignature(
114
119
  config: BeaconConfig,
@@ -28,11 +28,14 @@ export async function verifyPayloadsDataAvailability(
28
28
  await Promise.all(promises);
29
29
 
30
30
  const availableTime = Math.max(0, Math.max(...payloadInputs.map((payloadInput) => payloadInput.getTimeComplete())));
31
- const dataAvailabilityStatuses: DataAvailabilityStatus[] = payloadInputs.map((payloadInput) =>
32
- payloadInput.getBlobKzgCommitments().length === 0
31
+ const dataAvailabilityStatuses: DataAvailabilityStatus[] = payloadInputs.map((payloadInput) => {
32
+ if (payloadInput.daOutOfRange) {
33
+ return DataAvailabilityStatus.OutOfRange;
34
+ }
35
+ return payloadInput.getBlobKzgCommitments().length === 0
33
36
  ? DataAvailabilityStatus.NotRequired
34
- : DataAvailabilityStatus.Available
35
- );
37
+ : DataAvailabilityStatus.Available;
38
+ });
36
39
 
37
40
  return {dataAvailabilityStatuses, availableTime};
38
41
  }
@@ -106,6 +106,7 @@ import {
106
106
  SeenExecutionPayloadBids,
107
107
  SeenPayloadAttesters,
108
108
  SeenPayloadEnvelopeInput,
109
+ SeenProposerPreferences,
109
110
  SeenSyncCommitteeMessages,
110
111
  } from "./seenCache/index.js";
111
112
  import {SeenAggregatedAttestations} from "./seenCache/seenAggregateAndProof.js";
@@ -186,6 +187,7 @@ export class BeaconChain implements IBeaconChain {
186
187
  readonly seenPayloadAttesters = new SeenPayloadAttesters();
187
188
  readonly seenAggregatedAttestations: SeenAggregatedAttestations;
188
189
  readonly seenExecutionPayloadBids = new SeenExecutionPayloadBids();
190
+ readonly seenProposerPreferences = new SeenProposerPreferences();
189
191
  readonly seenBlockProposers = new SeenBlockProposers();
190
192
  readonly seenSyncCommitteeMessages = new SeenSyncCommitteeMessages();
191
193
  readonly seenContributionAndProof: SeenContributionAndProof;
@@ -334,6 +336,8 @@ export class BeaconChain implements IBeaconChain {
334
336
  logger,
335
337
  });
336
338
  this.seenPayloadEnvelopeInputCache = new SeenPayloadEnvelopeInput({
339
+ config,
340
+ clock,
337
341
  chainEvents: emitter,
338
342
  signal,
339
343
  serializedCache: this.serializedCache,
@@ -891,6 +895,10 @@ export class BeaconChain implements IBeaconChain {
891
895
  parentBlockSlot: Slot,
892
896
  parentBlockRootHex: RootHex
893
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
+ }
894
902
  const envelope = await this.getExecutionPayloadEnvelope(parentBlockSlot, parentBlockRootHex);
895
903
  if (envelope === null) {
896
904
  throw Error(`Parent execution payload envelope not found slot=${parentBlockSlot}, root=${parentBlockRootHex}`);
@@ -1094,11 +1102,15 @@ export class BeaconChain implements IBeaconChain {
1094
1102
  }
1095
1103
 
1096
1104
  async processBlock(block: IBlockInput, opts?: ImportBlockOpts): Promise<void> {
1097
- return this.blockProcessor.processBlocksJob([block], opts);
1105
+ return this.blockProcessor.processBlocksJob([block], null, opts);
1098
1106
  }
1099
1107
 
1100
- async processChainSegment(blocks: IBlockInput[], opts?: ImportBlockOpts): Promise<void> {
1101
- 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);
1102
1114
  }
1103
1115
 
1104
1116
  async processExecutionPayload(payloadInput: PayloadEnvelopeInput, opts?: ImportPayloadOpts): Promise<void> {
@@ -1429,6 +1441,7 @@ export class BeaconChain implements IBeaconChain {
1429
1441
  this.payloadAttestationPool.prune(slot);
1430
1442
  this.executionPayloadBidPool.prune(slot);
1431
1443
  this.seenExecutionPayloadBids.prune(slot);
1444
+ this.seenProposerPreferences.prune(slot);
1432
1445
  this.seenAttestationDatas.onSlot(slot);
1433
1446
  this.reprocessController.onSlot(slot);
1434
1447
 
@@ -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
 
@@ -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> {}
@@ -61,6 +61,7 @@ import {
61
61
  SeenContributionAndProof,
62
62
  SeenExecutionPayloadBids,
63
63
  SeenPayloadAttesters,
64
+ SeenProposerPreferences,
64
65
  SeenSyncCommitteeMessages,
65
66
  } from "./seenCache/index.js";
66
67
  import {SeenAggregatedAttestations} from "./seenCache/seenAggregateAndProof.js";
@@ -131,6 +132,7 @@ export interface IBeaconChain {
131
132
  readonly seenPayloadAttesters: SeenPayloadAttesters;
132
133
  readonly seenAggregatedAttestations: SeenAggregatedAttestations;
133
134
  readonly seenExecutionPayloadBids: SeenExecutionPayloadBids;
135
+ readonly seenProposerPreferences: SeenProposerPreferences;
134
136
  readonly seenBlockProposers: SeenBlockProposers;
135
137
  readonly seenSyncCommitteeMessages: SeenSyncCommitteeMessages;
136
138
  readonly seenContributionAndProof: SeenContributionAndProof;
@@ -250,7 +252,11 @@ export interface IBeaconChain {
250
252
  /** Process a block until complete */
251
253
  processBlock(block: IBlockInput, opts?: ImportBlockOpts): Promise<void>;
252
254
  /** Process a chain of blocks until complete */
253
- processChainSegment(blocks: IBlockInput[], opts?: ImportBlockOpts): Promise<void>;
255
+ processChainSegment(
256
+ blocks: IBlockInput[],
257
+ payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
258
+ opts?: ImportBlockOpts
259
+ ): Promise<void>;
254
260
 
255
261
  /** Process execution payload envelope: verify, import to fork choice, and persist to DB */
256
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