@lodestar/beacon-node 1.42.0-dev.efc1ab8e31 → 1.42.0-dev.f866249fa3

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 (247) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +11 -11
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
  5. package/lib/api/impl/beacon/pool/index.js +4 -0
  6. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  7. package/lib/api/impl/beacon/state/index.d.ts.map +1 -1
  8. package/lib/api/impl/beacon/state/index.js +13 -10
  9. package/lib/api/impl/beacon/state/index.js.map +1 -1
  10. package/lib/api/impl/debug/index.js.map +1 -1
  11. package/lib/api/impl/lodestar/index.d.ts.map +1 -1
  12. package/lib/api/impl/lodestar/index.js +4 -0
  13. package/lib/api/impl/lodestar/index.js.map +1 -1
  14. package/lib/api/impl/validator/index.d.ts.map +1 -1
  15. package/lib/api/impl/validator/index.js +7 -1
  16. package/lib/api/impl/validator/index.js.map +1 -1
  17. package/lib/chain/ColumnReconstructionTracker.d.ts +2 -1
  18. package/lib/chain/ColumnReconstructionTracker.d.ts.map +1 -1
  19. package/lib/chain/ColumnReconstructionTracker.js +5 -5
  20. package/lib/chain/ColumnReconstructionTracker.js.map +1 -1
  21. package/lib/chain/GetBlobsTracker.d.ts +2 -1
  22. package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
  23. package/lib/chain/GetBlobsTracker.js +14 -12
  24. package/lib/chain/GetBlobsTracker.js.map +1 -1
  25. package/lib/chain/blocks/blockInput/blockInput.d.ts +5 -5
  26. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  27. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  28. package/lib/chain/blocks/blockInput/types.d.ts +4 -4
  29. package/lib/chain/blocks/blockInput/types.d.ts.map +1 -1
  30. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  31. package/lib/chain/blocks/importBlock.js +19 -5
  32. package/lib/chain/blocks/importBlock.js.map +1 -1
  33. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  34. package/lib/chain/blocks/importExecutionPayload.js +7 -1
  35. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  36. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +14 -6
  37. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
  38. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +33 -2
  39. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
  40. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +2 -1
  41. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
  42. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  43. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +3 -2
  44. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  45. package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
  46. package/lib/chain/blocks/verifyBlocksSignatures.js +4 -2
  47. package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
  48. package/lib/chain/chain.d.ts +3 -2
  49. package/lib/chain/chain.d.ts.map +1 -1
  50. package/lib/chain/chain.js +64 -24
  51. package/lib/chain/chain.js.map +1 -1
  52. package/lib/chain/emitter.d.ts +29 -7
  53. package/lib/chain/emitter.d.ts.map +1 -1
  54. package/lib/chain/emitter.js +12 -3
  55. package/lib/chain/emitter.js.map +1 -1
  56. package/lib/chain/errors/dataColumnSidecarError.d.ts +31 -1
  57. package/lib/chain/errors/dataColumnSidecarError.d.ts.map +1 -1
  58. package/lib/chain/errors/dataColumnSidecarError.js +7 -0
  59. package/lib/chain/errors/dataColumnSidecarError.js.map +1 -1
  60. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  61. package/lib/chain/forkChoice/index.js +10 -8
  62. package/lib/chain/forkChoice/index.js.map +1 -1
  63. package/lib/chain/interface.d.ts +4 -2
  64. package/lib/chain/interface.d.ts.map +1 -1
  65. package/lib/chain/lightClient/index.d.ts +2 -2
  66. package/lib/chain/lightClient/index.d.ts.map +1 -1
  67. package/lib/chain/lightClient/index.js.map +1 -1
  68. package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
  69. package/lib/chain/opPools/aggregatedAttestationPool.js +5 -2
  70. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  71. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  72. package/lib/chain/prepareNextSlot.js +7 -1
  73. package/lib/chain/prepareNextSlot.js.map +1 -1
  74. package/lib/chain/produceBlock/computeNewStateRoot.d.ts +2 -2
  75. package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
  76. package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
  77. package/lib/chain/produceBlock/produceBlockBody.d.ts +3 -3
  78. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  79. package/lib/chain/produceBlock/produceBlockBody.js +10 -1
  80. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  81. package/lib/chain/seenCache/seenGossipBlockInput.d.ts +1 -1
  82. package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
  83. package/lib/chain/seenCache/seenGossipBlockInput.js +2 -2
  84. package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
  85. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +1 -1
  86. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
  87. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +2 -2
  88. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
  89. package/lib/chain/validation/block.d.ts.map +1 -1
  90. package/lib/chain/validation/block.js +2 -2
  91. package/lib/chain/validation/block.js.map +1 -1
  92. package/lib/chain/validation/dataColumnSidecar.d.ts +11 -4
  93. package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
  94. package/lib/chain/validation/dataColumnSidecar.js +184 -5
  95. package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
  96. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  97. package/lib/chain/validation/executionPayloadBid.js +4 -1
  98. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  99. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  100. package/lib/chain/validation/executionPayloadEnvelope.js +4 -1
  101. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  102. package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
  103. package/lib/chain/validation/payloadAttestationMessage.js +4 -1
  104. package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
  105. package/lib/chain/validation/syncCommittee.d.ts.map +1 -1
  106. package/lib/chain/validation/syncCommittee.js +4 -0
  107. package/lib/chain/validation/syncCommittee.js.map +1 -1
  108. package/lib/chain/validation/syncCommitteeContributionAndProof.js +4 -1
  109. package/lib/chain/validation/syncCommitteeContributionAndProof.js.map +1 -1
  110. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  111. package/lib/chain/validatorMonitor.js +3 -3
  112. package/lib/chain/validatorMonitor.js.map +1 -1
  113. package/lib/db/buckets.d.ts +2 -2
  114. package/lib/db/buckets.d.ts.map +1 -1
  115. package/lib/db/buckets.js +2 -2
  116. package/lib/db/buckets.js.map +1 -1
  117. package/lib/db/repositories/blockArchiveIndex.d.ts +2 -2
  118. package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
  119. package/lib/db/repositories/dataColumnSidecar.d.ts.map +1 -1
  120. package/lib/db/repositories/dataColumnSidecar.js +4 -2
  121. package/lib/db/repositories/dataColumnSidecar.js.map +1 -1
  122. package/lib/db/repositories/dataColumnSidecarArchive.d.ts.map +1 -1
  123. package/lib/db/repositories/dataColumnSidecarArchive.js +4 -2
  124. package/lib/db/repositories/dataColumnSidecarArchive.js.map +1 -1
  125. package/lib/metrics/metrics/lodestar.d.ts +20 -0
  126. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  127. package/lib/metrics/metrics/lodestar.js +33 -0
  128. package/lib/metrics/metrics/lodestar.js.map +1 -1
  129. package/lib/network/gossip/topic.d.ts +727 -0
  130. package/lib/network/gossip/topic.d.ts.map +1 -1
  131. package/lib/network/interface.d.ts +3 -2
  132. package/lib/network/interface.d.ts.map +1 -1
  133. package/lib/network/libp2p/index.d.ts.map +1 -1
  134. package/lib/network/libp2p/index.js +19 -13
  135. package/lib/network/libp2p/index.js.map +1 -1
  136. package/lib/network/network.d.ts +3 -2
  137. package/lib/network/network.d.ts.map +1 -1
  138. package/lib/network/network.js +3 -0
  139. package/lib/network/network.js.map +1 -1
  140. package/lib/network/options.d.ts.map +1 -1
  141. package/lib/network/options.js +7 -2
  142. package/lib/network/options.js.map +1 -1
  143. package/lib/network/processor/extractSlotRootFns.d.ts +1 -1
  144. package/lib/network/processor/extractSlotRootFns.d.ts.map +1 -1
  145. package/lib/network/processor/extractSlotRootFns.js +25 -5
  146. package/lib/network/processor/extractSlotRootFns.js.map +1 -1
  147. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  148. package/lib/network/processor/gossipHandlers.js +242 -66
  149. package/lib/network/processor/gossipHandlers.js.map +1 -1
  150. package/lib/network/processor/index.d.ts +11 -1
  151. package/lib/network/processor/index.d.ts.map +1 -1
  152. package/lib/network/processor/index.js +234 -22
  153. package/lib/network/processor/index.js.map +1 -1
  154. package/lib/network/reqresp/types.d.ts +3 -3
  155. package/lib/network/reqresp/types.d.ts.map +1 -1
  156. package/lib/network/reqresp/types.js +9 -3
  157. package/lib/network/reqresp/types.js.map +1 -1
  158. package/lib/node/nodejs.d.ts.map +1 -1
  159. package/lib/node/nodejs.js +4 -1
  160. package/lib/node/nodejs.js.map +1 -1
  161. package/lib/node/notifier.d.ts.map +1 -1
  162. package/lib/node/notifier.js +2 -2
  163. package/lib/node/notifier.js.map +1 -1
  164. package/lib/sync/unknownBlock.js +2 -2
  165. package/lib/sync/unknownBlock.js.map +1 -1
  166. package/lib/sync/utils/downloadByRange.d.ts +3 -3
  167. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  168. package/lib/sync/utils/downloadByRange.js +4 -2
  169. package/lib/sync/utils/downloadByRange.js.map +1 -1
  170. package/lib/sync/utils/downloadByRoot.d.ts +3 -3
  171. package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
  172. package/lib/sync/utils/downloadByRoot.js +10 -5
  173. package/lib/sync/utils/downloadByRoot.js.map +1 -1
  174. package/lib/util/blobs.d.ts +3 -3
  175. package/lib/util/blobs.d.ts.map +1 -1
  176. package/lib/util/blobs.js +21 -10
  177. package/lib/util/blobs.js.map +1 -1
  178. package/lib/util/dataColumns.d.ts +18 -11
  179. package/lib/util/dataColumns.d.ts.map +1 -1
  180. package/lib/util/dataColumns.js +51 -17
  181. package/lib/util/dataColumns.js.map +1 -1
  182. package/lib/util/execution.d.ts +6 -2
  183. package/lib/util/execution.d.ts.map +1 -1
  184. package/lib/util/execution.js +49 -25
  185. package/lib/util/execution.js.map +1 -1
  186. package/lib/util/sszBytes.d.ts +25 -1
  187. package/lib/util/sszBytes.d.ts.map +1 -1
  188. package/lib/util/sszBytes.js +189 -2
  189. package/lib/util/sszBytes.js.map +1 -1
  190. package/package.json +15 -15
  191. package/src/api/impl/beacon/blocks/index.ts +17 -14
  192. package/src/api/impl/beacon/pool/index.ts +4 -0
  193. package/src/api/impl/beacon/state/index.ts +15 -15
  194. package/src/api/impl/debug/index.ts +2 -2
  195. package/src/api/impl/lodestar/index.ts +4 -0
  196. package/src/api/impl/validator/index.ts +7 -0
  197. package/src/chain/ColumnReconstructionTracker.ts +6 -5
  198. package/src/chain/GetBlobsTracker.ts +14 -12
  199. package/src/chain/blocks/blockInput/blockInput.ts +8 -8
  200. package/src/chain/blocks/blockInput/types.ts +4 -4
  201. package/src/chain/blocks/importBlock.ts +29 -8
  202. package/src/chain/blocks/importExecutionPayload.ts +7 -1
  203. package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +53 -12
  204. package/src/chain/blocks/payloadEnvelopeInput/types.ts +2 -1
  205. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +2 -1
  206. package/src/chain/blocks/verifyBlocksSignatures.ts +9 -2
  207. package/src/chain/chain.ts +73 -28
  208. package/src/chain/emitter.ts +25 -7
  209. package/src/chain/errors/dataColumnSidecarError.ts +32 -1
  210. package/src/chain/forkChoice/index.ts +11 -8
  211. package/src/chain/interface.ts +4 -2
  212. package/src/chain/lightClient/index.ts +7 -3
  213. package/src/chain/opPools/aggregatedAttestationPool.ts +6 -1
  214. package/src/chain/prepareNextSlot.ts +8 -0
  215. package/src/chain/produceBlock/computeNewStateRoot.ts +2 -1
  216. package/src/chain/produceBlock/produceBlockBody.ts +25 -5
  217. package/src/chain/seenCache/seenGossipBlockInput.ts +2 -2
  218. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +2 -2
  219. package/src/chain/validation/block.ts +2 -1
  220. package/src/chain/validation/dataColumnSidecar.ts +230 -7
  221. package/src/chain/validation/executionPayloadBid.ts +4 -0
  222. package/src/chain/validation/executionPayloadEnvelope.ts +8 -1
  223. package/src/chain/validation/payloadAttestationMessage.ts +4 -0
  224. package/src/chain/validation/syncCommittee.ts +5 -1
  225. package/src/chain/validation/syncCommitteeContributionAndProof.ts +5 -1
  226. package/src/chain/validatorMonitor.ts +3 -2
  227. package/src/db/buckets.ts +2 -2
  228. package/src/db/repositories/dataColumnSidecar.ts +4 -2
  229. package/src/db/repositories/dataColumnSidecarArchive.ts +4 -2
  230. package/src/metrics/metrics/lodestar.ts +34 -0
  231. package/src/network/interface.ts +3 -2
  232. package/src/network/libp2p/index.ts +21 -15
  233. package/src/network/network.ts +7 -4
  234. package/src/network/options.ts +7 -2
  235. package/src/network/processor/extractSlotRootFns.ts +32 -6
  236. package/src/network/processor/gossipHandlers.ts +305 -79
  237. package/src/network/processor/index.ts +304 -22
  238. package/src/network/reqresp/types.ts +13 -5
  239. package/src/node/nodejs.ts +5 -2
  240. package/src/node/notifier.ts +7 -2
  241. package/src/sync/unknownBlock.ts +3 -3
  242. package/src/sync/utils/downloadByRange.ts +9 -7
  243. package/src/sync/utils/downloadByRoot.ts +16 -12
  244. package/src/util/blobs.ts +35 -15
  245. package/src/util/dataColumns.ts +69 -25
  246. package/src/util/execution.ts +49 -30
  247. package/src/util/sszBytes.ts +245 -3
@@ -15,9 +15,9 @@ import {
15
15
  BUILDER_INDEX_SELF_BUILD,
16
16
  EFFECTIVE_BALANCE_INCREMENT,
17
17
  type ForkPostFulu,
18
+ type ForkPostGloas,
18
19
  GENESIS_SLOT,
19
20
  SLOTS_PER_EPOCH,
20
- isForkPostElectra,
21
21
  isForkPostGloas,
22
22
  } from "@lodestar/params";
23
23
  import {
@@ -29,12 +29,15 @@ import {
29
29
  computeEpochAtSlot,
30
30
  computeStartSlotAtEpoch,
31
31
  getEffectiveBalancesFromStateBytes,
32
+ isStatePostAltair,
33
+ isStatePostElectra,
34
+ isStatePostGloas,
32
35
  } from "@lodestar/state-transition";
33
36
  import {
34
37
  BeaconBlock,
35
38
  BlindedBeaconBlock,
36
39
  BlindedBeaconBlockBody,
37
- DataColumnSidecars,
40
+ DataColumnSidecar,
38
41
  Epoch,
39
42
  Root,
40
43
  RootHex,
@@ -504,7 +507,11 @@ export class BeaconChain implements IBeaconChain {
504
507
  }
505
508
 
506
509
  seenBlock(blockRoot: RootHex): boolean {
507
- return this.seenBlockInputCache.has(blockRoot) || this.forkChoice.hasBlockHex(blockRoot);
510
+ return this.seenBlockInputCache.hasBlock(blockRoot) || this.forkChoice.hasBlockHexUnsafe(blockRoot);
511
+ }
512
+
513
+ seenPayloadEnvelope(blockRoot: RootHex): boolean {
514
+ return this.seenPayloadEnvelopeInputCache.hasPayload(blockRoot) || this.forkChoice.hasPayloadHexUnsafe(blockRoot);
508
515
  }
509
516
 
510
517
  regenCanAcceptWork(): boolean {
@@ -873,20 +880,32 @@ export class BeaconChain implements IBeaconChain {
873
880
  );
874
881
  }
875
882
 
876
- async getDataColumnSidecars(blockSlot: Slot, blockRootHex: string): Promise<DataColumnSidecars> {
877
- const blockInput = this.seenBlockInputCache.get(blockRootHex);
878
- if (blockInput) {
879
- if (!isBlockInputColumns(blockInput)) {
880
- throw new Error(`Expected block input to have columns: slot=${blockSlot} root=${blockRootHex}`);
883
+ async getDataColumnSidecars(blockSlot: Slot, blockRootHex: string): Promise<DataColumnSidecar[]> {
884
+ const fork = this.config.getForkName(blockSlot);
885
+
886
+ if (isForkPostGloas(fork)) {
887
+ // After gloas, columns are tracked in PayloadEnvelopeInput
888
+ const payloadInput = this.seenPayloadEnvelopeInputCache.get(blockRootHex);
889
+ if (payloadInput) {
890
+ return payloadInput.getAllColumns();
891
+ }
892
+ } else {
893
+ // Before gloas, columns are tracked in BlockInput
894
+ const blockInput = this.seenBlockInputCache.get(blockRootHex);
895
+ if (blockInput) {
896
+ if (!isBlockInputColumns(blockInput)) {
897
+ throw new Error(`Expected block input to have columns: slot=${blockSlot} root=${blockRootHex}`);
898
+ }
899
+ return blockInput.getAllColumns();
881
900
  }
882
- return blockInput.getAllColumns();
883
901
  }
902
+
884
903
  const sidecarsUnfinalized = await this.db.dataColumnSidecar.values(fromHex(blockRootHex));
885
904
  if (sidecarsUnfinalized.length > 0) {
886
- return sidecarsUnfinalized as DataColumnSidecars;
905
+ return sidecarsUnfinalized;
887
906
  }
888
907
  const sidecarsFinalized = await this.db.dataColumnSidecarArchive.values(blockSlot);
889
- return sidecarsFinalized as DataColumnSidecars;
908
+ return sidecarsFinalized;
890
909
  }
891
910
 
892
911
  async getSerializedDataColumnSidecars(
@@ -894,23 +913,45 @@ export class BeaconChain implements IBeaconChain {
894
913
  blockRootHex: string,
895
914
  indices: number[]
896
915
  ): Promise<(Uint8Array | undefined)[]> {
897
- const blockInput = this.seenBlockInputCache.get(blockRootHex);
898
- if (blockInput) {
899
- if (!isBlockInputColumns(blockInput)) {
900
- throw new Error(`Expected block input to have columns: slot=${blockSlot} root=${blockRootHex}`);
916
+ const fork = this.config.getForkName(blockSlot);
917
+
918
+ if (isForkPostGloas(fork)) {
919
+ // After gloas, columns are tracked in PayloadEnvelopeInput
920
+ const payloadInput = this.seenPayloadEnvelopeInputCache.get(blockRootHex);
921
+ if (payloadInput) {
922
+ return indices.map((index) => {
923
+ const sidecar = payloadInput.getColumn(index);
924
+ if (!sidecar) {
925
+ return undefined;
926
+ }
927
+ const serialized = this.serializedCache.get(sidecar);
928
+ if (serialized) {
929
+ return serialized;
930
+ }
931
+ return sszTypesFor(fork as ForkPostGloas).DataColumnSidecar.serialize(sidecar);
932
+ });
901
933
  }
902
- return indices.map((index) => {
903
- const sidecar = blockInput.getColumn(index);
904
- if (!sidecar) {
905
- return undefined;
906
- }
907
- const serialized = this.serializedCache.get(sidecar);
908
- if (serialized) {
909
- return serialized;
934
+ } else {
935
+ // Before gloas, columns are tracked in BlockInput
936
+ const blockInput = this.seenBlockInputCache.get(blockRootHex);
937
+ if (blockInput) {
938
+ if (!isBlockInputColumns(blockInput)) {
939
+ throw new Error(`Expected block input to have columns: slot=${blockSlot} root=${blockRootHex}`);
910
940
  }
911
- return sszTypesFor(blockInput.forkName as ForkPostFulu).DataColumnSidecar.serialize(sidecar);
912
- });
941
+ return indices.map((index) => {
942
+ const sidecar = blockInput.getColumn(index);
943
+ if (!sidecar) {
944
+ return undefined;
945
+ }
946
+ const serialized = this.serializedCache.get(sidecar);
947
+ if (serialized) {
948
+ return serialized;
949
+ }
950
+ return sszTypesFor(blockInput.forkName as ForkPostFulu).DataColumnSidecar.serialize(sidecar);
951
+ });
952
+ }
913
953
  }
954
+
914
955
  const sidecarsUnfinalized = await this.db.dataColumnSidecar.getManyBinary(fromHex(blockRootHex), indices);
915
956
  if (sidecarsUnfinalized.some((sidecar) => sidecar != null)) {
916
957
  return sidecarsUnfinalized;
@@ -1037,6 +1078,9 @@ export class BeaconChain implements IBeaconChain {
1037
1078
  slot,
1038
1079
  stateRoot: ZERO_HASH,
1039
1080
  };
1081
+ if (!isStatePostGloas(postState)) {
1082
+ throw Error(`Expected gloas+ post-state for execution payload envelope, got fork=${postState.forkName}`);
1083
+ }
1040
1084
  const envelopeStateRoot = computeEnvelopeStateRoot(this.metrics, postState, envelope);
1041
1085
  gloasResult.envelopeStateRoot = envelopeStateRoot;
1042
1086
  }
@@ -1365,9 +1409,7 @@ export class BeaconChain implements IBeaconChain {
1365
1409
  metrics.chain.blacklistedBlocks.set(this.blacklistedBlocks.size);
1366
1410
 
1367
1411
  const headState = this.getHeadState();
1368
- const fork = this.config.getForkName(headState.slot);
1369
-
1370
- if (isForkPostElectra(fork)) {
1412
+ if (isStatePostElectra(headState)) {
1371
1413
  metrics.pendingDeposits.set(headState.pendingDepositsCount);
1372
1414
  metrics.pendingPartialWithdrawals.set(headState.pendingPartialWithdrawalsCount);
1373
1415
  metrics.pendingConsolidations.set(headState.pendingConsolidationsCount);
@@ -1614,6 +1656,9 @@ export class BeaconChain implements IBeaconChain {
1614
1656
  }
1615
1657
 
1616
1658
  preState = preState.processSlots(block.slot); // Dial preState's slot to block.slot
1659
+ if (!isStatePostAltair(preState)) {
1660
+ throw new Error("Sync committee rewards are not supported before Altair");
1661
+ }
1617
1662
 
1618
1663
  return preState.computeSyncCommitteeRewards(block, validatorIds ?? []);
1619
1664
  }
@@ -3,7 +3,8 @@ import {StrictEventEmitter} from "strict-event-emitter-types";
3
3
  import {routes} from "@lodestar/api";
4
4
  import {CheckpointWithPayloadStatus} from "@lodestar/fork-choice";
5
5
  import {IBeaconStateView} from "@lodestar/state-transition";
6
- import {DataColumnSidecars, RootHex, deneb, phase0} from "@lodestar/types";
6
+ import {DataColumnSidecar, RootHex, deneb, phase0} from "@lodestar/types";
7
+ import {SignedExecutionPayloadEnvelope} from "@lodestar/types/gloas";
7
8
  import {PeerIdStr} from "../util/peerId.js";
8
9
  import {BlockInputSource, IBlockInput} from "./blocks/blockInput/types.js";
9
10
 
@@ -54,13 +55,22 @@ export enum ChainEvent {
54
55
  */
55
56
  updateStatus = "updateStatus",
56
57
  /**
57
- * Trigger a BlockInputSync for blocks where the parentRoot is not known to fork choice
58
+ * Trigger BlockInputSync to find parent of a SignedBeaconBlock received
59
+ * Post-gloas, missing parent could be a SignedBeaconBlock and/or a SignedExecutionPayloadEnvelope
58
60
  */
59
- unknownParent = "unknownParent",
61
+ blockUnknownParent = "blockUnknownParent",
60
62
  /**
61
- * Trigger BlockInputSync for objects that correspond to a block that is not known to fork choice
63
+ * Trigger BlockInputSync to find a SignedBeaconBlock given a SignedExecutionPayloadEnvelop received
64
+ */
65
+ envelopeUnknownBlock = "envelopeUnknownBlock",
66
+ /**
67
+ * Trigger BlockInputSync to find a SignedBeaconBlock with specified block root.
62
68
  */
63
69
  unknownBlockRoot = "unknownBlockRoot",
70
+ /**
71
+ * Trigger BlockInputSync to find a SignedExecutionPayloadEnvelope with specified block root.
72
+ */
73
+ unknownEnvelopeBlockRoot = "unknownEnvelopeBlockRoot",
64
74
  /**
65
75
  * Trigger BlockInputSync for blocks that are partially received via gossip but are not complete by time the
66
76
  * cut-off window passes for waiting on gossip
@@ -75,9 +85,15 @@ export type ReorgEventData = routes.events.EventData[routes.events.EventType.cha
75
85
  type ApiEvents = {[K in routes.events.EventType]: (data: routes.events.EventData[K]) => void};
76
86
 
77
87
  export type ChainEventData = {
78
- [ChainEvent.unknownParent]: {blockInput: IBlockInput; peer: PeerIdStr; source: BlockInputSource};
88
+ [ChainEvent.blockUnknownParent]: {blockInput: IBlockInput; peer: PeerIdStr; source: BlockInputSource};
89
+ [ChainEvent.envelopeUnknownBlock]: {
90
+ envelope: SignedExecutionPayloadEnvelope;
91
+ peer?: PeerIdStr;
92
+ source: BlockInputSource;
93
+ };
79
94
  [ChainEvent.unknownBlockRoot]: {rootHex: RootHex; peer?: PeerIdStr; source: BlockInputSource};
80
95
  [ChainEvent.incompleteBlockInput]: {blockInput: IBlockInput; peer: PeerIdStr; source: BlockInputSource};
96
+ [ChainEvent.unknownEnvelopeBlockRoot]: {rootHex: RootHex; peer?: PeerIdStr; source: BlockInputSource};
81
97
  };
82
98
 
83
99
  export type IChainEvents = ApiEvents & {
@@ -88,7 +104,7 @@ export type IChainEvents = ApiEvents & {
88
104
 
89
105
  [ChainEvent.updateTargetCustodyGroupCount]: (targetGroupCount: number) => void;
90
106
 
91
- [ChainEvent.publishDataColumns]: (sidecars: DataColumnSidecars) => void;
107
+ [ChainEvent.publishDataColumns]: (sidecars: DataColumnSidecar[]) => void;
92
108
 
93
109
  [ChainEvent.publishBlobSidecars]: (sidecars: deneb.BlobSidecar[]) => void;
94
110
 
@@ -96,9 +112,11 @@ export type IChainEvents = ApiEvents & {
96
112
 
97
113
  // Sync events that are chain->chain. Initiated from network requests but do not cross the network
98
114
  // barrier so are considered ChainEvent(s).
99
- [ChainEvent.unknownParent]: (data: ChainEventData[ChainEvent.unknownParent]) => void;
115
+ [ChainEvent.blockUnknownParent]: (data: ChainEventData[ChainEvent.blockUnknownParent]) => void;
116
+ [ChainEvent.envelopeUnknownBlock]: (data: ChainEventData[ChainEvent.envelopeUnknownBlock]) => void;
100
117
  [ChainEvent.unknownBlockRoot]: (data: ChainEventData[ChainEvent.unknownBlockRoot]) => void;
101
118
  [ChainEvent.incompleteBlockInput]: (data: ChainEventData[ChainEvent.incompleteBlockInput]) => void;
119
+ [ChainEvent.unknownEnvelopeBlockRoot]: (data: ChainEventData[ChainEvent.unknownEnvelopeBlockRoot]) => void;
102
120
  };
103
121
 
104
122
  /**
@@ -1,3 +1,4 @@
1
+ import {ForkName} from "@lodestar/params";
1
2
  import {RootHex, Slot, SubnetID} from "@lodestar/types";
2
3
  import {LodestarError} from "@lodestar/utils";
3
4
  import {GossipActionError} from "./gossipValidation.js";
@@ -6,6 +7,7 @@ export enum DataColumnSidecarErrorCode {
6
7
  INVALID_INDEX = "DATA_COLUMN_SIDECAR_ERROR_INVALID_INDEX",
7
8
  NO_COMMITMENTS = "DATA_COLUMN_SIDECAR_ERROR_NO_COMMITMENTS",
8
9
  MISMATCHED_LENGTHS = "DATA_COLUMN_SIDECAR_ERROR_MISMATCHED_LENGTHS",
10
+ INCORRECT_TYPE = "DATA_COLUMN_SIDECAR_ERROR_INCORRECT_TYPE",
9
11
  INVALID_SUBNET = "DATA_COLUMN_SIDECAR_ERROR_INVALID_SUBNET",
10
12
  INVALID_KZG_PROOF = "DATA_COLUMN_SIDECAR_ERROR_INVALID_KZG_PROOF",
11
13
  TOO_MANY_KZG_COMMITMENTS = "DATA_COLUMN_SIDECAR_ERROR_TOO_MANY_KZG_COMMITMENTS",
@@ -18,6 +20,10 @@ export enum DataColumnSidecarErrorCode {
18
20
  INCORRECT_SIDECAR_COUNT = "DATA_COLUMN_SIDECAR_ERROR_INCORRECT_SIDECAR_COUNT",
19
21
  /** Sidecar doesn't match block */
20
22
  INCORRECT_BLOCK = "DATA_COLUMN_SIDECAR_ERROR_INCORRECT_BLOCK",
23
+ /** Sidecar slot doesn't match block slot */
24
+ INCORRECT_SIDECAR_SLOT = "DATA_COLUMN_SIDECAR_ERROR_INCORRECT_SIDECAR_SLOT",
25
+ /** Sidecar referenced block is not the expected block type */
26
+ INCORRECT_BLOCK_TYPE = "DATA_COLUMN_SIDECAR_ERROR_INCORRECT_BLOCK_TYPE",
21
27
  /** Sidecar cell count not as expected */
22
28
  INCORRECT_CELL_COUNT = "DATA_COLUMN_SIDECAR_ERROR_INCORRECT_CELL_COUNT",
23
29
  /** Sidecar kzg proof count not as expected */
@@ -32,10 +38,12 @@ export enum DataColumnSidecarErrorCode {
32
38
  FUTURE_SLOT = "DATA_COLUMN_SIDECAR_ERROR_FUTURE_SLOT",
33
39
  WOULD_REVERT_FINALIZED_SLOT = "DATA_COLUMN_SIDECAR_ERROR_WOULD_REVERT_FINALIZED_SLOT",
34
40
  PARENT_UNKNOWN = "DATA_COLUMN_SIDECAR_ERROR_PARENT_UNKNOWN",
41
+ BLOCK_UNKNOWN = "DATA_COLUMN_SIDECAR_ERROR_BLOCK_UNKNOWN",
35
42
  NOT_LATER_THAN_PARENT = "DATA_COLUMN_SIDECAR_ERROR_NOT_LATER_THAN_PARENT",
36
43
  PROPOSAL_SIGNATURE_INVALID = "DATA_COLUMN_SIDECAR_ERROR_PROPOSAL_SIGNATURE_INVALID",
37
44
  INCLUSION_PROOF_INVALID = "DATA_COLUMN_SIDECAR_ERROR_INCLUSION_PROOF_INVALID",
38
45
  INCORRECT_PROPOSER = "DATA_COLUMN_SIDECAR_ERROR_INCORRECT_PROPOSER",
46
+ PAYLOAD_ENVELOPE_INPUT_MISSING = "DATA_COLUMN_SIDECAR_ERROR_PAYLOAD_ENVELOPE_INPUT_MISSING",
39
47
  }
40
48
 
41
49
  export type DataColumnSidecarErrorType =
@@ -47,6 +55,12 @@ export type DataColumnSidecarErrorType =
47
55
  commitmentsLength: number;
48
56
  proofsLength: number;
49
57
  }
58
+ | {
59
+ code: DataColumnSidecarErrorCode.INCORRECT_TYPE;
60
+ slot: Slot;
61
+ columnIndex: number;
62
+ fork: ForkName;
63
+ }
50
64
  | {code: DataColumnSidecarErrorCode.INVALID_SUBNET; columnIndex: number; gossipSubnet: SubnetID}
51
65
  | {
52
66
  code: DataColumnSidecarErrorCode.TOO_MANY_KZG_COMMITMENTS;
@@ -63,6 +77,11 @@ export type DataColumnSidecarErrorType =
63
77
  parentRoot: RootHex;
64
78
  slot: Slot;
65
79
  }
80
+ | {
81
+ code: DataColumnSidecarErrorCode.BLOCK_UNKNOWN;
82
+ blockRoot: RootHex;
83
+ slot: Slot;
84
+ }
66
85
  | {
67
86
  code: DataColumnSidecarErrorCode.PROPOSAL_SIGNATURE_INVALID;
68
87
  slot: Slot;
@@ -80,6 +99,17 @@ export type DataColumnSidecarErrorType =
80
99
  expected: string;
81
100
  actual: string;
82
101
  }
102
+ | {
103
+ code: DataColumnSidecarErrorCode.INCORRECT_BLOCK_TYPE;
104
+ slot: Slot;
105
+ columnIndex: number;
106
+ }
107
+ | {
108
+ code: DataColumnSidecarErrorCode.INCORRECT_SIDECAR_SLOT;
109
+ columnIndex: number;
110
+ expected: Slot;
111
+ actual: Slot;
112
+ }
83
113
  | {
84
114
  code: DataColumnSidecarErrorCode.INCORRECT_HEADER_ROOT;
85
115
  slot: number;
@@ -97,7 +127,8 @@ export type DataColumnSidecarErrorType =
97
127
  actual: number;
98
128
  }
99
129
  | {code: DataColumnSidecarErrorCode.INVALID_KZG_PROOF_BATCH; slot: number; reason: string}
100
- | {code: DataColumnSidecarErrorCode.INCORRECT_PROPOSER; actualProposerIndex: number; expectedProposerIndex: number};
130
+ | {code: DataColumnSidecarErrorCode.INCORRECT_PROPOSER; actualProposerIndex: number; expectedProposerIndex: number}
131
+ | {code: DataColumnSidecarErrorCode.PAYLOAD_ENVELOPE_INPUT_MISSING; slot: Slot; blockRoot: RootHex};
101
132
 
102
133
  export class DataColumnSidecarGossipError extends GossipActionError<DataColumnSidecarErrorType> {}
103
134
  export class DataColumnSidecarValidationError extends LodestarError<DataColumnSidecarErrorType> {}
@@ -10,12 +10,14 @@ import {
10
10
  ForkChoiceOpts as RawForkChoiceOpts,
11
11
  getCheckpointPayloadStatus,
12
12
  } from "@lodestar/fork-choice";
13
- import {ForkSeq, ZERO_HASH_HEX} from "@lodestar/params";
13
+ import {ZERO_HASH_HEX} from "@lodestar/params";
14
14
  import {
15
15
  DataAvailabilityStatus,
16
16
  IBeaconStateView,
17
17
  computeEpochAtSlot,
18
18
  computeStartSlotAtEpoch,
19
+ isStatePostBellatrix,
20
+ isStatePostGloas,
19
21
  } from "@lodestar/state-transition";
20
22
  import {Slot, ssz} from "@lodestar/types";
21
23
  import {Logger, toRootHex} from "@lodestar/utils";
@@ -142,19 +144,19 @@ export function initializeForkChoiceFromFinalizedState(
142
144
  unrealizedFinalizedEpoch: finalizedCheckpoint.epoch,
143
145
  unrealizedFinalizedRoot: toRootHex(finalizedCheckpoint.root),
144
146
 
145
- ...(state.isExecutionStateType && state.isMergeTransitionComplete
147
+ ...(isStatePostBellatrix(state) && state.isExecutionStateType && state.isMergeTransitionComplete
146
148
  ? {
147
149
  executionPayloadBlockHash: toRootHex(state.latestBlockHash),
148
150
  // TODO GLOAS: executionPayloadNumber is not tracked in BeaconState post-gloas (EIP-7732 removed
149
151
  // latestExecutionPayloadHeader). Using 0 as unavailable fallback until a solution is found.
150
- executionPayloadNumber: config.getForkSeq(state.slot) >= ForkSeq.gloas ? 0 : state.payloadBlockNumber,
152
+ executionPayloadNumber: isStatePostGloas(state) ? 0 : state.payloadBlockNumber,
151
153
  executionStatus: blockHeader.slot === GENESIS_SLOT ? ExecutionStatus.Valid : ExecutionStatus.Syncing,
152
154
  }
153
155
  : {executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}),
154
156
 
155
157
  dataAvailabilityStatus: DataAvailabilityStatus.PreData,
156
158
  payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL, // TODO GLOAS: Post-gloas how do we know if the checkpoint payload is FULL or EMPTY?
157
- parentBlockHash: isForkPostGloas ? toRootHex(state.latestBlockHash) : null,
159
+ parentBlockHash: isStatePostGloas(state) ? toRootHex(state.latestBlockHash) : null,
158
160
  },
159
161
  currentSlot
160
162
  ),
@@ -237,20 +239,21 @@ export function initializeForkChoiceFromUnfinalizedState(
237
239
  unrealizedFinalizedEpoch: finalizedCheckpoint.epoch,
238
240
  unrealizedFinalizedRoot: toRootHex(finalizedCheckpoint.root),
239
241
 
240
- ...(unfinalizedState.isExecutionStateType && unfinalizedState.isMergeTransitionComplete
242
+ ...(isStatePostBellatrix(unfinalizedState) &&
243
+ unfinalizedState.isExecutionStateType &&
244
+ unfinalizedState.isMergeTransitionComplete
241
245
  ? {
242
246
  executionPayloadBlockHash: toRootHex(unfinalizedState.latestBlockHash),
243
247
  // TODO GLOAS: executionPayloadNumber is not tracked in BeaconState post-gloas (EIP-7732 removed
244
248
  // latestExecutionPayloadHeader). Using 0 as unavailable fallback until a solution is found.
245
- executionPayloadNumber:
246
- config.getForkSeq(unfinalizedState.slot) >= ForkSeq.gloas ? 0 : unfinalizedState.payloadBlockNumber,
249
+ executionPayloadNumber: isStatePostGloas(unfinalizedState) ? 0 : unfinalizedState.payloadBlockNumber,
247
250
  executionStatus: blockHeader.slot === GENESIS_SLOT ? ExecutionStatus.Valid : ExecutionStatus.Syncing,
248
251
  }
249
252
  : {executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}),
250
253
 
251
254
  dataAvailabilityStatus: DataAvailabilityStatus.PreData,
252
255
  payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL, // TODO GLOAS: Post-gloas how do we know if the checkpoint payload is FULL or EMPTY?
253
- parentBlockHash: isForkPostGloas ? toRootHex(unfinalizedState.latestBlockHash) : null,
256
+ parentBlockHash: isStatePostGloas(unfinalizedState) ? toRootHex(unfinalizedState.latestBlockHash) : null,
254
257
  };
255
258
 
256
259
  const parentSlot = blockHeader.slot - 1;
@@ -5,7 +5,7 @@ import {EpochShuffling, IBeaconStateView, PubkeyCache} from "@lodestar/state-tra
5
5
  import {
6
6
  BeaconBlock,
7
7
  BlindedBeaconBlock,
8
- DataColumnSidecars,
8
+ DataColumnSidecar,
9
9
  Epoch,
10
10
  Root,
11
11
  RootHex,
@@ -159,6 +159,8 @@ export interface IBeaconChain {
159
159
  close(): Promise<void>;
160
160
  /** Chain has seen the specified block root or not. The block may not be processed yet, use forkchoice.hasBlock to check it */
161
161
  seenBlock(blockRoot: RootHex): boolean;
162
+ /** Chain has seen a SignedExecutionPayloadEnvelope for this block root (via seenCache or fork choice FULL variant) */
163
+ seenPayloadEnvelope(blockRoot: RootHex): boolean;
162
164
  /** Populate in-memory caches with persisted data. Call at least once on startup */
163
165
  loadFromDisk(): Promise<void>;
164
166
  /** Persist in-memory data to the DB. Call at least once before stopping the process */
@@ -217,7 +219,7 @@ export interface IBeaconChain {
217
219
  ): Promise<{block: SignedBeaconBlock; executionOptimistic: boolean; finalized: boolean} | null>;
218
220
  getBlobSidecars(blockSlot: Slot, blockRootHex: string): Promise<deneb.BlobSidecars | null>;
219
221
  getSerializedBlobSidecars(blockSlot: Slot, blockRootHex: string): Promise<Uint8Array | null>;
220
- getDataColumnSidecars(blockSlot: Slot, blockRootHex: string): Promise<DataColumnSidecars>;
222
+ getDataColumnSidecars(blockSlot: Slot, blockRootHex: string): Promise<DataColumnSidecar[]>;
221
223
  getSerializedDataColumnSidecars(
222
224
  blockSlot: Slot,
223
225
  blockRootHex: string,
@@ -21,7 +21,7 @@ import {
21
21
  isForkPostElectra,
22
22
  } from "@lodestar/params";
23
23
  import {
24
- IBeaconStateView,
24
+ type IBeaconStateViewAltair,
25
25
  computeStartSlotAtEpoch,
26
26
  computeSyncPeriodAtEpoch,
27
27
  computeSyncPeriodAtSlot,
@@ -260,7 +260,11 @@ export class LightClientServer {
260
260
  * - Persist state witness
261
261
  * - Use block's syncAggregate
262
262
  */
263
- onImportBlockHead(block: BeaconBlock<ForkPostAltair>, postState: IBeaconStateView, parentBlockSlot: Slot): void {
263
+ onImportBlockHead(
264
+ block: BeaconBlock<ForkPostAltair>,
265
+ postState: IBeaconStateViewAltair,
266
+ parentBlockSlot: Slot
267
+ ): void {
264
268
  // TEMP: To disable this functionality for fork_choice spec tests.
265
269
  // Since the tests have deep-reorgs attested data is not available often printing lots of error logs.
266
270
  // While this function is only called for head blocks, best to disable.
@@ -396,7 +400,7 @@ export class LightClientServer {
396
400
 
397
401
  private async persistPostBlockImportData(
398
402
  block: BeaconBlock<ForkPostAltair>,
399
- postState: IBeaconStateView,
403
+ postState: IBeaconStateViewAltair,
400
404
  parentBlockSlot: Slot
401
405
  ): Promise<void> {
402
406
  const blockSlot = block.slot;
@@ -26,6 +26,8 @@ import {
26
26
  computeSlotsSinceEpochStart,
27
27
  computeStartSlotAtEpoch,
28
28
  getAttestationParticipationStatus,
29
+ isStatePostAltair,
30
+ isStatePostGloas,
29
31
  } from "@lodestar/state-transition";
30
32
  import {Attestation, Epoch, RootHex, Slot, electra, isElectraAttestation, phase0, ssz} from "@lodestar/types";
31
33
  import {MapDef, assert, toRootHex} from "@lodestar/utils";
@@ -359,7 +361,7 @@ export class AggregatedAttestationPool {
359
361
  inclusionDistance,
360
362
  stateEpoch,
361
363
  rootCache,
362
- ForkSeq[fork] >= ForkSeq.gloas ? state.executionPayloadAvailability : null
364
+ isStatePostGloas(state) ? state.executionPayloadAvailability : null
363
365
  );
364
366
 
365
367
  const weight =
@@ -742,6 +744,9 @@ export function getNotSeenValidatorsFn(
742
744
  if (config.getForkName(stateSlot) === ForkName.phase0) {
743
745
  throw new Error("getNotSeenValidatorsFn is not supported phase0 state");
744
746
  }
747
+ if (!isStatePostAltair(state)) {
748
+ throw new Error("Expected Altair state for participation tracking");
749
+ }
745
750
 
746
751
  // altair and future forks
747
752
  // Get attestations to be included in an altair block.
@@ -7,6 +7,7 @@ import {
7
7
  StateHashTreeRootSource,
8
8
  computeEpochAtSlot,
9
9
  computeTimeAtSlot,
10
+ isStatePostBellatrix,
10
11
  } from "@lodestar/state-transition";
11
12
  import {Slot} from "@lodestar/types";
12
13
  import {Logger, fromHex, isErrorAborted, sleep} from "@lodestar/utils";
@@ -159,6 +160,9 @@ export class PrepareNextSlotScheduler {
159
160
  const preparationTime =
160
161
  computeTimeAtSlot(this.config, prepareSlot, this.chain.genesisTime) - Date.now() / 1000;
161
162
  this.metrics?.blockPayload.payloadAdvancePrepTime.observe(preparationTime);
163
+ if (!isStatePostBellatrix(updatedPrepareState)) {
164
+ throw new Error("Expected Bellatrix state for payload preparation");
165
+ }
162
166
 
163
167
  const safeBlockHash = getSafeExecutionBlockHash(this.chain.forkChoice);
164
168
  const finalizedBlockHash =
@@ -183,6 +187,10 @@ export class PrepareNextSlotScheduler {
183
187
  });
184
188
  }
185
189
 
190
+ if (!isStatePostBellatrix(updatedPrepareState)) {
191
+ throw new Error("Expected Bellatrix state for payload attributes");
192
+ }
193
+
186
194
  this.computeStateHashTreeRoot(updatedPrepareState, isEpochTransition);
187
195
 
188
196
  // If emitPayloadAttributes is true emit a SSE payloadAttributes event
@@ -3,6 +3,7 @@ import {
3
3
  ExecutionPayloadStatus,
4
4
  G2_POINT_AT_INFINITY,
5
5
  IBeaconStateView,
6
+ IBeaconStateViewGloas,
6
7
  StateHashTreeRootSource,
7
8
  } from "@lodestar/state-transition";
8
9
  import {BeaconBlock, BlindedBeaconBlock, Gwei, Root, gloas} from "@lodestar/types";
@@ -60,7 +61,7 @@ export function computeNewStateRoot(
60
61
  */
61
62
  export function computeEnvelopeStateRoot(
62
63
  metrics: Metrics | null,
63
- postBlockState: IBeaconStateView,
64
+ postBlockState: IBeaconStateViewGloas,
64
65
  envelope: gloas.ExecutionPayloadEnvelope
65
66
  ): Root {
66
67
  const signedEnvelope: gloas.SignedExecutionPayloadEnvelope = {
@@ -14,7 +14,15 @@ import {
14
14
  isForkPostBellatrix,
15
15
  isForkPostGloas,
16
16
  } from "@lodestar/params";
17
- import {G2_POINT_AT_INFINITY, IBeaconStateView, computeTimeAtSlot} from "@lodestar/state-transition";
17
+ import {
18
+ G2_POINT_AT_INFINITY,
19
+ IBeaconStateView,
20
+ type IBeaconStateViewBellatrix,
21
+ computeTimeAtSlot,
22
+ isStatePostBellatrix,
23
+ isStatePostCapella,
24
+ isStatePostGloas,
25
+ } from "@lodestar/state-transition";
18
26
  import {
19
27
  BLSPubkey,
20
28
  BLSSignature,
@@ -191,6 +199,10 @@ export async function produceBlockBody<T extends BlockType>(
191
199
  this.logger.verbose("Producing beacon block body", logMeta);
192
200
 
193
201
  if (isForkPostGloas(fork)) {
202
+ if (!isStatePostGloas(currentState)) {
203
+ throw new Error("Expected Gloas state for Gloas block production");
204
+ }
205
+
194
206
  // TODO GLOAS: support non self-building here, the block type differentiation between
195
207
  // full and blinded no longer makes sense in gloas, it might be a good idea to move
196
208
  // this into a completely separate function and have pre/post gloas more separated
@@ -297,6 +309,10 @@ export async function produceBlockBody<T extends BlockType>(
297
309
  shouldOverrideBuilder,
298
310
  });
299
311
  } else if (isForkPostBellatrix(fork)) {
312
+ if (!isStatePostBellatrix(currentState)) {
313
+ throw new Error("Expected Bellatrix state for execution block production");
314
+ }
315
+
300
316
  const safeBlockHash = getSafeExecutionBlockHash(this.forkChoice);
301
317
  const finalizedBlockHash = this.forkChoice.getFinalizedBlock().executionPayloadBlockHash ?? ZERO_HASH_HEX;
302
318
  const feeRecipient = requestedFeeRecipient ?? this.beaconProposerCache.getOrDefault(proposerIndex);
@@ -598,7 +614,7 @@ export async function prepareExecutionPayload(
598
614
  parentBlockRoot: Root,
599
615
  safeBlockHash: RootHex,
600
616
  finalizedBlockHash: RootHex,
601
- state: IBeaconStateView,
617
+ state: IBeaconStateViewBellatrix,
602
618
  suggestedFeeRecipient: string
603
619
  ): Promise<{prepType: PayloadPreparationType; payloadId: PayloadId}> {
604
620
  const parentHash = state.latestBlockHash;
@@ -666,7 +682,7 @@ async function prepareExecutionPayloadHeader(
666
682
  config: ChainForkConfig;
667
683
  },
668
684
  fork: ForkPostBellatrix,
669
- state: IBeaconStateView,
685
+ state: IBeaconStateViewBellatrix,
670
686
  proposerPubKey: BLSPubkey
671
687
  ): Promise<{
672
688
  header: ExecutionPayloadHeader;
@@ -693,7 +709,7 @@ export function getPayloadAttributesForSSE(
693
709
  prepareSlot,
694
710
  parentBlockRoot,
695
711
  feeRecipient,
696
- }: {prepareState: IBeaconStateView; prepareSlot: Slot; parentBlockRoot: Root; feeRecipient: string}
712
+ }: {prepareState: IBeaconStateViewBellatrix; prepareSlot: Slot; parentBlockRoot: Root; feeRecipient: string}
697
713
  ): SSEPayloadAttributes {
698
714
  const parentHash = prepareState.latestBlockHash;
699
715
  const payloadAttributes = preparePayloadAttributes(fork, chain, {
@@ -736,7 +752,7 @@ function preparePayloadAttributes(
736
752
  parentBlockRoot,
737
753
  feeRecipient,
738
754
  }: {
739
- prepareState: IBeaconStateView;
755
+ prepareState: IBeaconStateViewBellatrix;
740
756
  prepareSlot: Slot;
741
757
  parentBlockRoot: Root;
742
758
  feeRecipient: string;
@@ -751,6 +767,10 @@ function preparePayloadAttributes(
751
767
  };
752
768
 
753
769
  if (ForkSeq[fork] >= ForkSeq.capella) {
770
+ if (!isStatePostCapella(prepareState)) {
771
+ throw new Error("Expected Capella state for withdrawals");
772
+ }
773
+
754
774
  // withdrawals logic is now fork aware as it changes on electra fork post capella
755
775
  (payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
756
776
  prepareState.getExpectedWithdrawals().expectedWithdrawals;
@@ -149,8 +149,8 @@ export class SeenBlockInput {
149
149
  });
150
150
  }
151
151
 
152
- has(rootHex: RootHex): boolean {
153
- return this.blockInputs.has(rootHex);
152
+ hasBlock(rootHex: RootHex): boolean {
153
+ return this.blockInputs.get(rootHex)?.hasBlock() ?? false;
154
154
  }
155
155
 
156
156
  get(rootHex: RootHex): IBlockInput | undefined {
@@ -84,8 +84,8 @@ export class SeenPayloadEnvelopeInput {
84
84
  return this.payloadInputs.get(blockRootHex);
85
85
  }
86
86
 
87
- has(blockRootHex: RootHex): boolean {
88
- return this.payloadInputs.has(blockRootHex);
87
+ hasPayload(blockRootHex: RootHex): boolean {
88
+ return this.payloadInputs.get(blockRootHex)?.hasPayloadEnvelope() ?? false;
89
89
  }
90
90
 
91
91
  prune(blockRootHex: RootHex): void {
@@ -6,6 +6,7 @@ import {
6
6
  computeTimeAtSlot,
7
7
  getBlockProposerSignatureSet,
8
8
  isExecutionBlockBodyType,
9
+ isStatePostBellatrix,
9
10
  } from "@lodestar/state-transition";
10
11
  import {SignedBeaconBlock, deneb, gloas, isGloasBeaconBlock} from "@lodestar/types";
11
12
  import {byteArrayEquals, sleep, toRootHex} from "@lodestar/utils";
@@ -174,7 +175,7 @@ export async function validateGossipBlock(
174
175
  if (isForkPostBellatrix(fork) && !isForkPostGloas(fork)) {
175
176
  if (!isExecutionBlockBodyType(block.body)) throw Error("Not execution block body type");
176
177
  const executionPayload = block.body.executionPayload;
177
- if (blockState.isExecutionStateType && blockState.isExecutionEnabled(block)) {
178
+ if (isStatePostBellatrix(blockState) && blockState.isExecutionStateType && blockState.isExecutionEnabled(block)) {
178
179
  const expectedTimestamp = computeTimeAtSlot(config, blockSlot, chain.genesisTime);
179
180
  if (executionPayload.timestamp !== computeTimeAtSlot(config, blockSlot, chain.genesisTime)) {
180
181
  throw new BlockGossipError(GossipAction.REJECT, {