@lodestar/beacon-node 1.42.0-dev.7df0e2c8fa → 1.42.0-dev.8300b502a6

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 (295) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +24 -12
  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 +9 -3
  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/archiveStore/archiveStore.d.ts.map +1 -1
  26. package/lib/chain/archiveStore/archiveStore.js +1 -0
  27. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  28. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts +3 -3
  29. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
  30. package/lib/chain/archiveStore/historicalState/getHistoricalState.js +6 -4
  31. package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
  32. package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts +2 -2
  33. package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts.map +1 -1
  34. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -0
  35. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
  36. package/lib/chain/archiveStore/historicalState/types.d.ts +2 -0
  37. package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
  38. package/lib/chain/archiveStore/historicalState/types.js.map +1 -1
  39. package/lib/chain/archiveStore/historicalState/worker.js +1 -4
  40. package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
  41. package/lib/chain/archiveStore/interface.d.ts +1 -0
  42. package/lib/chain/archiveStore/interface.d.ts.map +1 -1
  43. package/lib/chain/blocks/blockInput/blockInput.d.ts +5 -5
  44. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  45. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  46. package/lib/chain/blocks/blockInput/types.d.ts +4 -4
  47. package/lib/chain/blocks/blockInput/types.d.ts.map +1 -1
  48. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  49. package/lib/chain/blocks/importBlock.js +34 -20
  50. package/lib/chain/blocks/importBlock.js.map +1 -1
  51. package/lib/chain/blocks/importExecutionPayload.d.ts +10 -8
  52. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  53. package/lib/chain/blocks/importExecutionPayload.js +86 -49
  54. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  55. package/lib/chain/blocks/index.d.ts.map +1 -1
  56. package/lib/chain/blocks/index.js +2 -1
  57. package/lib/chain/blocks/index.js.map +1 -1
  58. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +14 -6
  59. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
  60. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +33 -2
  61. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
  62. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +2 -1
  63. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
  64. package/lib/chain/blocks/types.d.ts +20 -14
  65. package/lib/chain/blocks/types.d.ts.map +1 -1
  66. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +2 -2
  67. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  68. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +4 -3
  69. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  70. package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
  71. package/lib/chain/blocks/verifyBlocksSignatures.js +4 -2
  72. package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
  73. package/lib/chain/chain.d.ts +3 -2
  74. package/lib/chain/chain.d.ts.map +1 -1
  75. package/lib/chain/chain.js +68 -28
  76. package/lib/chain/chain.js.map +1 -1
  77. package/lib/chain/emitter.d.ts +29 -7
  78. package/lib/chain/emitter.d.ts.map +1 -1
  79. package/lib/chain/emitter.js +12 -3
  80. package/lib/chain/emitter.js.map +1 -1
  81. package/lib/chain/errors/blockError.d.ts +6 -1
  82. package/lib/chain/errors/blockError.d.ts.map +1 -1
  83. package/lib/chain/errors/blockError.js +2 -0
  84. package/lib/chain/errors/blockError.js.map +1 -1
  85. package/lib/chain/errors/dataColumnSidecarError.d.ts +31 -1
  86. package/lib/chain/errors/dataColumnSidecarError.d.ts.map +1 -1
  87. package/lib/chain/errors/dataColumnSidecarError.js +7 -0
  88. package/lib/chain/errors/dataColumnSidecarError.js.map +1 -1
  89. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  90. package/lib/chain/forkChoice/index.js +10 -8
  91. package/lib/chain/forkChoice/index.js.map +1 -1
  92. package/lib/chain/interface.d.ts +4 -2
  93. package/lib/chain/interface.d.ts.map +1 -1
  94. package/lib/chain/lightClient/index.d.ts +2 -2
  95. package/lib/chain/lightClient/index.d.ts.map +1 -1
  96. package/lib/chain/lightClient/index.js +7 -0
  97. package/lib/chain/lightClient/index.js.map +1 -1
  98. package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
  99. package/lib/chain/opPools/aggregatedAttestationPool.js +5 -2
  100. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  101. package/lib/chain/opPools/executionPayloadBidPool.d.ts +2 -2
  102. package/lib/chain/opPools/executionPayloadBidPool.d.ts.map +1 -1
  103. package/lib/chain/opPools/executionPayloadBidPool.js +2 -2
  104. package/lib/chain/opPools/executionPayloadBidPool.js.map +1 -1
  105. package/lib/chain/options.d.ts +1 -0
  106. package/lib/chain/options.d.ts.map +1 -1
  107. package/lib/chain/options.js +1 -0
  108. package/lib/chain/options.js.map +1 -1
  109. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  110. package/lib/chain/prepareNextSlot.js +7 -1
  111. package/lib/chain/prepareNextSlot.js.map +1 -1
  112. package/lib/chain/produceBlock/computeNewStateRoot.d.ts +3 -3
  113. package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
  114. package/lib/chain/produceBlock/computeNewStateRoot.js +8 -8
  115. package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
  116. package/lib/chain/produceBlock/produceBlockBody.d.ts +5 -5
  117. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  118. package/lib/chain/produceBlock/produceBlockBody.js +23 -4
  119. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  120. package/lib/chain/seenCache/seenGossipBlockInput.d.ts +1 -1
  121. package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
  122. package/lib/chain/seenCache/seenGossipBlockInput.js +2 -2
  123. package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
  124. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +1 -1
  125. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
  126. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +2 -2
  127. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
  128. package/lib/chain/validation/block.d.ts.map +1 -1
  129. package/lib/chain/validation/block.js +14 -5
  130. package/lib/chain/validation/block.js.map +1 -1
  131. package/lib/chain/validation/dataColumnSidecar.d.ts +11 -4
  132. package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
  133. package/lib/chain/validation/dataColumnSidecar.js +184 -5
  134. package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
  135. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  136. package/lib/chain/validation/executionPayloadBid.js +7 -4
  137. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  138. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  139. package/lib/chain/validation/executionPayloadEnvelope.js +6 -1
  140. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  141. package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
  142. package/lib/chain/validation/payloadAttestationMessage.js +4 -1
  143. package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
  144. package/lib/chain/validation/syncCommittee.d.ts.map +1 -1
  145. package/lib/chain/validation/syncCommittee.js +4 -0
  146. package/lib/chain/validation/syncCommittee.js.map +1 -1
  147. package/lib/chain/validation/syncCommitteeContributionAndProof.js +4 -1
  148. package/lib/chain/validation/syncCommitteeContributionAndProof.js.map +1 -1
  149. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  150. package/lib/chain/validatorMonitor.js +3 -3
  151. package/lib/chain/validatorMonitor.js.map +1 -1
  152. package/lib/db/buckets.d.ts +2 -2
  153. package/lib/db/buckets.d.ts.map +1 -1
  154. package/lib/db/buckets.js +2 -2
  155. package/lib/db/buckets.js.map +1 -1
  156. package/lib/db/repositories/blockArchiveIndex.d.ts +2 -2
  157. package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
  158. package/lib/db/repositories/dataColumnSidecar.d.ts.map +1 -1
  159. package/lib/db/repositories/dataColumnSidecar.js +4 -2
  160. package/lib/db/repositories/dataColumnSidecar.js.map +1 -1
  161. package/lib/db/repositories/dataColumnSidecarArchive.d.ts.map +1 -1
  162. package/lib/db/repositories/dataColumnSidecarArchive.js +4 -2
  163. package/lib/db/repositories/dataColumnSidecarArchive.js.map +1 -1
  164. package/lib/metrics/metrics/lodestar.d.ts +20 -0
  165. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  166. package/lib/metrics/metrics/lodestar.js +33 -0
  167. package/lib/metrics/metrics/lodestar.js.map +1 -1
  168. package/lib/network/interface.d.ts +3 -2
  169. package/lib/network/interface.d.ts.map +1 -1
  170. package/lib/network/libp2p/index.d.ts.map +1 -1
  171. package/lib/network/libp2p/index.js +19 -13
  172. package/lib/network/libp2p/index.js.map +1 -1
  173. package/lib/network/network.d.ts +3 -2
  174. package/lib/network/network.d.ts.map +1 -1
  175. package/lib/network/network.js +3 -0
  176. package/lib/network/network.js.map +1 -1
  177. package/lib/network/options.d.ts.map +1 -1
  178. package/lib/network/options.js +7 -2
  179. package/lib/network/options.js.map +1 -1
  180. package/lib/network/processor/extractSlotRootFns.d.ts +1 -1
  181. package/lib/network/processor/extractSlotRootFns.d.ts.map +1 -1
  182. package/lib/network/processor/extractSlotRootFns.js +25 -5
  183. package/lib/network/processor/extractSlotRootFns.js.map +1 -1
  184. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  185. package/lib/network/processor/gossipHandlers.js +260 -73
  186. package/lib/network/processor/gossipHandlers.js.map +1 -1
  187. package/lib/network/processor/index.d.ts +11 -1
  188. package/lib/network/processor/index.d.ts.map +1 -1
  189. package/lib/network/processor/index.js +234 -22
  190. package/lib/network/processor/index.js.map +1 -1
  191. package/lib/network/reqresp/types.d.ts +3 -3
  192. package/lib/network/reqresp/types.d.ts.map +1 -1
  193. package/lib/network/reqresp/types.js +9 -3
  194. package/lib/network/reqresp/types.js.map +1 -1
  195. package/lib/node/nodejs.d.ts.map +1 -1
  196. package/lib/node/nodejs.js +4 -1
  197. package/lib/node/nodejs.js.map +1 -1
  198. package/lib/node/notifier.d.ts.map +1 -1
  199. package/lib/node/notifier.js +2 -2
  200. package/lib/node/notifier.js.map +1 -1
  201. package/lib/sync/unknownBlock.js +2 -2
  202. package/lib/sync/unknownBlock.js.map +1 -1
  203. package/lib/sync/utils/downloadByRange.d.ts +3 -3
  204. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  205. package/lib/sync/utils/downloadByRange.js +4 -2
  206. package/lib/sync/utils/downloadByRange.js.map +1 -1
  207. package/lib/sync/utils/downloadByRoot.d.ts +3 -3
  208. package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
  209. package/lib/sync/utils/downloadByRoot.js +10 -5
  210. package/lib/sync/utils/downloadByRoot.js.map +1 -1
  211. package/lib/util/blobs.d.ts +3 -3
  212. package/lib/util/blobs.d.ts.map +1 -1
  213. package/lib/util/blobs.js +21 -10
  214. package/lib/util/blobs.js.map +1 -1
  215. package/lib/util/dataColumns.d.ts +18 -11
  216. package/lib/util/dataColumns.d.ts.map +1 -1
  217. package/lib/util/dataColumns.js +51 -17
  218. package/lib/util/dataColumns.js.map +1 -1
  219. package/lib/util/execution.d.ts +6 -2
  220. package/lib/util/execution.d.ts.map +1 -1
  221. package/lib/util/execution.js +49 -25
  222. package/lib/util/execution.js.map +1 -1
  223. package/lib/util/sszBytes.d.ts +25 -1
  224. package/lib/util/sszBytes.d.ts.map +1 -1
  225. package/lib/util/sszBytes.js +189 -2
  226. package/lib/util/sszBytes.js.map +1 -1
  227. package/package.json +15 -15
  228. package/src/api/impl/beacon/blocks/index.ts +32 -15
  229. package/src/api/impl/beacon/pool/index.ts +4 -0
  230. package/src/api/impl/beacon/state/index.ts +15 -15
  231. package/src/api/impl/debug/index.ts +2 -2
  232. package/src/api/impl/lodestar/index.ts +4 -0
  233. package/src/api/impl/validator/index.ts +9 -2
  234. package/src/chain/ColumnReconstructionTracker.ts +6 -5
  235. package/src/chain/GetBlobsTracker.ts +14 -12
  236. package/src/chain/archiveStore/archiveStore.ts +1 -0
  237. package/src/chain/archiveStore/historicalState/getHistoricalState.ts +6 -5
  238. package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +2 -1
  239. package/src/chain/archiveStore/historicalState/types.ts +2 -0
  240. package/src/chain/archiveStore/historicalState/worker.ts +1 -5
  241. package/src/chain/archiveStore/interface.ts +1 -0
  242. package/src/chain/blocks/blockInput/blockInput.ts +8 -8
  243. package/src/chain/blocks/blockInput/types.ts +4 -4
  244. package/src/chain/blocks/importBlock.ts +45 -23
  245. package/src/chain/blocks/importExecutionPayload.ts +94 -53
  246. package/src/chain/blocks/index.ts +2 -1
  247. package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +53 -12
  248. package/src/chain/blocks/payloadEnvelopeInput/types.ts +2 -1
  249. package/src/chain/blocks/types.ts +25 -14
  250. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +6 -5
  251. package/src/chain/blocks/verifyBlocksSignatures.ts +9 -2
  252. package/src/chain/chain.ts +77 -32
  253. package/src/chain/emitter.ts +25 -7
  254. package/src/chain/errors/blockError.ts +4 -1
  255. package/src/chain/errors/dataColumnSidecarError.ts +32 -1
  256. package/src/chain/forkChoice/index.ts +11 -8
  257. package/src/chain/interface.ts +4 -2
  258. package/src/chain/lightClient/index.ts +15 -3
  259. package/src/chain/opPools/aggregatedAttestationPool.ts +6 -1
  260. package/src/chain/opPools/executionPayloadBidPool.ts +3 -3
  261. package/src/chain/options.ts +2 -0
  262. package/src/chain/prepareNextSlot.ts +8 -0
  263. package/src/chain/produceBlock/computeNewStateRoot.ts +11 -10
  264. package/src/chain/produceBlock/produceBlockBody.ts +40 -10
  265. package/src/chain/seenCache/seenGossipBlockInput.ts +2 -2
  266. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +2 -2
  267. package/src/chain/validation/block.ts +15 -7
  268. package/src/chain/validation/dataColumnSidecar.ts +230 -7
  269. package/src/chain/validation/executionPayloadBid.ts +7 -3
  270. package/src/chain/validation/executionPayloadEnvelope.ts +10 -1
  271. package/src/chain/validation/payloadAttestationMessage.ts +4 -0
  272. package/src/chain/validation/syncCommittee.ts +5 -1
  273. package/src/chain/validation/syncCommitteeContributionAndProof.ts +5 -1
  274. package/src/chain/validatorMonitor.ts +3 -2
  275. package/src/db/buckets.ts +2 -2
  276. package/src/db/repositories/dataColumnSidecar.ts +4 -2
  277. package/src/db/repositories/dataColumnSidecarArchive.ts +4 -2
  278. package/src/metrics/metrics/lodestar.ts +34 -0
  279. package/src/network/interface.ts +3 -2
  280. package/src/network/libp2p/index.ts +21 -15
  281. package/src/network/network.ts +7 -4
  282. package/src/network/options.ts +7 -2
  283. package/src/network/processor/extractSlotRootFns.ts +32 -6
  284. package/src/network/processor/gossipHandlers.ts +325 -86
  285. package/src/network/processor/index.ts +304 -22
  286. package/src/network/reqresp/types.ts +13 -5
  287. package/src/node/nodejs.ts +5 -2
  288. package/src/node/notifier.ts +7 -2
  289. package/src/sync/unknownBlock.ts +3 -3
  290. package/src/sync/utils/downloadByRange.ts +9 -7
  291. package/src/sync/utils/downloadByRoot.ts +16 -12
  292. package/src/util/blobs.ts +35 -15
  293. package/src/util/dataColumns.ts +69 -25
  294. package/src/util/execution.ts +49 -30
  295. package/src/util/sszBytes.ts +245 -3
@@ -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.
@@ -268,6 +272,14 @@ export class LightClientServer {
268
272
  return;
269
273
  }
270
274
 
275
+ // TODO GLOAS: Light client updates for gloas are not yet updated in the spec.
276
+ // The block body no longer contains execution payload, so `blockToLightClientHeader`
277
+ // cannot construct a header from a gloas block. Skip all light client processing
278
+ // for post-gloas blocks, revisit once there is a spec for it.
279
+ if (this.config.getForkSeq(block.slot) >= ForkSeq.gloas) {
280
+ return;
281
+ }
282
+
271
283
  // What is the syncAggregate signing?
272
284
  // From the state-transition
273
285
  // ```
@@ -396,7 +408,7 @@ export class LightClientServer {
396
408
 
397
409
  private async persistPostBlockImportData(
398
410
  block: BeaconBlock<ForkPostAltair>,
399
- postState: IBeaconStateView,
411
+ postState: IBeaconStateViewAltair,
400
412
  parentBlockSlot: Slot
401
413
  ): Promise<void> {
402
414
  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.
@@ -59,13 +59,13 @@ export class ExecutionPayloadBidPool {
59
59
  }
60
60
 
61
61
  /**
62
- * Return the highest-value bid matching slot, parent block root, and parent block hash.
62
+ * Return the highest-value bid matching slot, parent block hash, and parent block root.
63
63
  * Used for gossip validation and block production.
64
64
  */
65
65
  getBestBid(
66
- parentBlockRoot: BlockRootHex,
66
+ slot: Slot,
67
67
  parentBlockHash: BlockHashHex,
68
- slot: Slot
68
+ parentBlockRoot: BlockRootHex
69
69
  ): gloas.ExecutionPayloadBid | null {
70
70
  const bidByParentHash = this.bidByParentHashByParentRootBySlot.get(slot)?.get(parentBlockRoot);
71
71
  return bidByParentHash?.get(parentBlockHash) ?? null;
@@ -47,6 +47,7 @@ export type IChainOptions = BlockProcessOpts &
47
47
  minSameMessageSignatureSetsToBatch: number;
48
48
  archiveDateEpochs?: number;
49
49
  nHistoricalStatesFileDataStore?: boolean;
50
+ nativeStateView?: boolean;
50
51
  };
51
52
 
52
53
  export type BlockProcessOpts = {
@@ -124,6 +125,7 @@ export const defaultChainOptions: IChainOptions = {
124
125
  // - users can prune the persisted checkpoint state files manually to save disc space
125
126
  // - it helps debug easier when network is unfinalized
126
127
  nHistoricalStatesFileDataStore: true,
128
+ nativeStateView: false,
127
129
  maxBlockStates: DEFAULT_MAX_BLOCK_STATES,
128
130
  maxCPStateEpochsInMemory: DEFAULT_MAX_CP_STATE_EPOCHS_IN_MEMORY,
129
131
  maxCPStateEpochsOnDisk: DEFAULT_MAX_CP_STATE_ON_DISK,
@@ -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";
@@ -18,11 +19,11 @@ export function computeNewStateRoot(
18
19
  metrics: Metrics | null,
19
20
  state: IBeaconStateView,
20
21
  block: BeaconBlock | BlindedBeaconBlock
21
- ): {newStateRoot: Root; proposerReward: Gwei; postState: IBeaconStateView} {
22
+ ): {newStateRoot: Root; proposerReward: Gwei; postBlockState: IBeaconStateView} {
22
23
  // Set signature to zero to re-use stateTransition() function which requires the SignedBeaconBlock type
23
24
  const blockEmptySig = {message: block, signature: ZERO_HASH};
24
25
 
25
- const postState = state.stateTransition(
26
+ const postBlockState = state.stateTransition(
26
27
  blockEmptySig,
27
28
  {
28
29
  // ExecutionPayloadStatus.valid: Assume payload valid, it has been produced by a trusted EL
@@ -41,16 +42,16 @@ export function computeNewStateRoot(
41
42
  {metrics}
42
43
  );
43
44
 
44
- const {attestations, syncAggregate, slashing} = postState.proposerRewards;
45
+ const {attestations, syncAggregate, slashing} = postBlockState.proposerRewards;
45
46
  const proposerReward = BigInt(attestations + syncAggregate + slashing);
46
47
 
47
48
  const hashTreeRootTimer = metrics?.stateHashTreeRootTime.startTimer({
48
49
  source: StateHashTreeRootSource.computeNewStateRoot,
49
50
  });
50
- const newStateRoot = postState.hashTreeRoot();
51
+ const newStateRoot = postBlockState.hashTreeRoot();
51
52
  hashTreeRootTimer?.();
52
53
 
53
- return {newStateRoot, proposerReward, postState};
54
+ return {newStateRoot, proposerReward, postBlockState};
54
55
  }
55
56
 
56
57
  /**
@@ -58,9 +59,9 @@ export function computeNewStateRoot(
58
59
  * Similar to `computeNewStateRoot` but for payload envelope processing.
59
60
  *
60
61
  */
61
- export function computeEnvelopeStateRoot(
62
+ export function computePayloadEnvelopeStateRoot(
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 = {
@@ -69,7 +70,7 @@ export function computeEnvelopeStateRoot(
69
70
  };
70
71
 
71
72
  const processEnvelopeTimer = metrics?.blockPayload.executionPayloadEnvelopeProcessingTime.startTimer();
72
- const postEnvelopeState = postBlockState.processExecutionPayloadEnvelope(signedEnvelope, {
73
+ const postPayloadState = postBlockState.processExecutionPayloadEnvelope(signedEnvelope, {
73
74
  // Signature is zero-ed (G2_POINT_AT_INFINITY), skip verification
74
75
  verifySignature: false,
75
76
  // State root is being computed here, the envelope doesn't have it yet
@@ -80,9 +81,9 @@ export function computeEnvelopeStateRoot(
80
81
  processEnvelopeTimer?.();
81
82
 
82
83
  const hashTreeRootTimer = metrics?.stateHashTreeRootTime.startTimer({
83
- source: StateHashTreeRootSource.computeEnvelopeStateRoot,
84
+ source: StateHashTreeRootSource.computePayloadEnvelopeStateRoot,
84
85
  });
85
- const stateRoot = postEnvelopeState.hashTreeRoot();
86
+ const stateRoot = postPayloadState.hashTreeRoot();
86
87
  hashTreeRootTimer?.();
87
88
 
88
89
  return stateRoot;
@@ -14,7 +14,16 @@ 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
+ isParentBlockFull,
23
+ isStatePostBellatrix,
24
+ isStatePostCapella,
25
+ isStatePostGloas,
26
+ } from "@lodestar/state-transition";
18
27
  import {
19
28
  BLSPubkey,
20
29
  BLSSignature,
@@ -103,11 +112,11 @@ export type ProduceFullGloas = {
103
112
  blobsBundle: BlobsBundle<ForkPostGloas>;
104
113
  cells: fulu.Cell[][];
105
114
  /**
106
- * Cached envelope state root computed during block production.
115
+ * Cached payload envelope state root computed during block production.
107
116
  * This is the state root after running `processExecutionPayloadEnvelope` on the
108
117
  * post-block state, and later used to construct the `ExecutionPayloadEnvelope`.
109
118
  */
110
- envelopeStateRoot: Root;
119
+ payloadEnvelopeStateRoot: Root;
111
120
  };
112
121
  export type ProduceFullFulu = {
113
122
  type: BlockType.Full;
@@ -191,6 +200,10 @@ export async function produceBlockBody<T extends BlockType>(
191
200
  this.logger.verbose("Producing beacon block body", logMeta);
192
201
 
193
202
  if (isForkPostGloas(fork)) {
203
+ if (!isStatePostGloas(currentState)) {
204
+ throw new Error("Expected Gloas state for Gloas block production");
205
+ }
206
+
194
207
  // TODO GLOAS: support non self-building here, the block type differentiation between
195
208
  // full and blinded no longer makes sense in gloas, it might be a good idea to move
196
209
  // this into a completely separate function and have pre/post gloas more separated
@@ -297,6 +310,10 @@ export async function produceBlockBody<T extends BlockType>(
297
310
  shouldOverrideBuilder,
298
311
  });
299
312
  } else if (isForkPostBellatrix(fork)) {
313
+ if (!isStatePostBellatrix(currentState)) {
314
+ throw new Error("Expected Bellatrix state for execution block production");
315
+ }
316
+
300
317
  const safeBlockHash = getSafeExecutionBlockHash(this.forkChoice);
301
318
  const finalizedBlockHash = this.forkChoice.getFinalizedBlock().executionPayloadBlockHash ?? ZERO_HASH_HEX;
302
319
  const feeRecipient = requestedFeeRecipient ?? this.beaconProposerCache.getOrDefault(proposerIndex);
@@ -598,7 +615,7 @@ export async function prepareExecutionPayload(
598
615
  parentBlockRoot: Root,
599
616
  safeBlockHash: RootHex,
600
617
  finalizedBlockHash: RootHex,
601
- state: IBeaconStateView,
618
+ state: IBeaconStateViewBellatrix,
602
619
  suggestedFeeRecipient: string
603
620
  ): Promise<{prepType: PayloadPreparationType; payloadId: PayloadId}> {
604
621
  const parentHash = state.latestBlockHash;
@@ -666,7 +683,7 @@ async function prepareExecutionPayloadHeader(
666
683
  config: ChainForkConfig;
667
684
  },
668
685
  fork: ForkPostBellatrix,
669
- state: IBeaconStateView,
686
+ state: IBeaconStateViewBellatrix,
670
687
  proposerPubKey: BLSPubkey
671
688
  ): Promise<{
672
689
  header: ExecutionPayloadHeader;
@@ -693,7 +710,7 @@ export function getPayloadAttributesForSSE(
693
710
  prepareSlot,
694
711
  parentBlockRoot,
695
712
  feeRecipient,
696
- }: {prepareState: IBeaconStateView; prepareSlot: Slot; parentBlockRoot: Root; feeRecipient: string}
713
+ }: {prepareState: IBeaconStateViewBellatrix; prepareSlot: Slot; parentBlockRoot: Root; feeRecipient: string}
697
714
  ): SSEPayloadAttributes {
698
715
  const parentHash = prepareState.latestBlockHash;
699
716
  const payloadAttributes = preparePayloadAttributes(fork, chain, {
@@ -736,7 +753,7 @@ function preparePayloadAttributes(
736
753
  parentBlockRoot,
737
754
  feeRecipient,
738
755
  }: {
739
- prepareState: IBeaconStateView;
756
+ prepareState: IBeaconStateViewBellatrix;
740
757
  prepareSlot: Slot;
741
758
  parentBlockRoot: Root;
742
759
  feeRecipient: string;
@@ -751,9 +768,22 @@ function preparePayloadAttributes(
751
768
  };
752
769
 
753
770
  if (ForkSeq[fork] >= ForkSeq.capella) {
754
- // withdrawals logic is now fork aware as it changes on electra fork post capella
755
- (payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
756
- prepareState.getExpectedWithdrawals().expectedWithdrawals;
771
+ if (!isStatePostCapella(prepareState)) {
772
+ throw new Error("Expected Capella state for withdrawals");
773
+ }
774
+
775
+ if (isStatePostGloas(prepareState) && !isParentBlockFull(prepareState)) {
776
+ // When the parent block is empty, state.payloadExpectedWithdrawals holds a batch
777
+ // already deducted from CL balances but never credited on the EL (the envelope
778
+ // was not delivered). The next payload must carry those same withdrawals to
779
+ // restore CL/EL consistency, otherwise validators permanently lose that balance.
780
+ (payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
781
+ prepareState.payloadExpectedWithdrawals;
782
+ } else {
783
+ // withdrawals logic is now fork aware as it changes on electra fork post capella
784
+ (payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
785
+ prepareState.getExpectedWithdrawals().expectedWithdrawals;
786
+ }
757
787
  }
758
788
 
759
789
  if (ForkSeq[fork] >= ForkSeq.deneb) {
@@ -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";
@@ -70,12 +71,7 @@ export async function validateGossipBlock(
70
71
  // [REJECT] The current finalized_checkpoint is an ancestor of block -- i.e.
71
72
  // get_ancestor(store, block.parent_root, compute_start_slot_at_epoch(store.finalized_checkpoint.epoch)) == store.finalized_checkpoint.root
72
73
  const parentRoot = toRootHex(block.parentRoot);
73
- const parentBlock = isGloasBeaconBlock(block)
74
- ? chain.forkChoice.getBlockHexAndBlockHash(
75
- parentRoot,
76
- toRootHex(block.body.signedExecutionPayloadBid.message.parentBlockHash)
77
- )
78
- : chain.forkChoice.getBlockHexDefaultStatus(parentRoot);
74
+ const parentBlock = chain.forkChoice.getBlockHexDefaultStatus(parentRoot);
79
75
  if (parentBlock === null) {
80
76
  // If fork choice does *not* consider the parent to be a descendant of the finalized block,
81
77
  // then there are two more cases:
@@ -90,6 +86,18 @@ export async function validateGossipBlock(
90
86
  throw new BlockGossipError(GossipAction.IGNORE, {code: BlockErrorCode.PARENT_UNKNOWN, parentRoot});
91
87
  }
92
88
 
89
+ // [IGNORE] The block's parent execution payload (defined by bid.parent_block_hash) has been seen
90
+ // (via gossip or non-gossip sources) (a client MAY queue blocks for processing once the parent payload is retrieved).
91
+ if (isGloasBeaconBlock(block)) {
92
+ const parentBlockHashHex = toRootHex(block.body.signedExecutionPayloadBid.message.parentBlockHash);
93
+ if (chain.forkChoice.getBlockHexAndBlockHash(parentRoot, parentBlockHashHex) === null) {
94
+ throw new BlockGossipError(GossipAction.IGNORE, {
95
+ code: BlockErrorCode.PARENT_PAYLOAD_UNKNOWN,
96
+ parentBlockHash: parentBlockHashHex,
97
+ });
98
+ }
99
+ }
100
+
93
101
  // [IGNORE] The attestation head block is too far behind the attestation slot, causing many skip slots.
94
102
  // This is deemed a DoS risk because we need to get the proposerShuffling. To get the shuffling we have
95
103
  // to do a bunch of epoch transitions, the longer the distance between the parent and block,
@@ -174,7 +182,7 @@ export async function validateGossipBlock(
174
182
  if (isForkPostBellatrix(fork) && !isForkPostGloas(fork)) {
175
183
  if (!isExecutionBlockBodyType(block.body)) throw Error("Not execution block body type");
176
184
  const executionPayload = block.body.executionPayload;
177
- if (blockState.isExecutionStateType && blockState.isExecutionEnabled(block)) {
185
+ if (isStatePostBellatrix(blockState) && blockState.isExecutionStateType && blockState.isExecutionEnabled(block)) {
178
186
  const expectedTimestamp = computeTimeAtSlot(config, blockSlot, chain.genesisTime);
179
187
  if (executionPayload.timestamp !== computeTimeAtSlot(config, blockSlot, chain.genesisTime)) {
180
188
  throw new BlockGossipError(GossipAction.REJECT, {