@lodestar/beacon-node 1.48.0-dev.f22c5ce63e → 1.48.0-dev.f63ac74039

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 (303) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +4 -11
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  5. package/lib/api/impl/beacon/state/utils.js +14 -0
  6. package/lib/api/impl/beacon/state/utils.js.map +1 -1
  7. package/lib/api/impl/config/index.d.ts.map +1 -1
  8. package/lib/api/impl/config/index.js +4 -1
  9. package/lib/api/impl/config/index.js.map +1 -1
  10. package/lib/api/impl/validator/index.d.ts.map +1 -1
  11. package/lib/api/impl/validator/index.js +39 -39
  12. package/lib/api/impl/validator/index.js.map +1 -1
  13. package/lib/chain/archiveStore/archiveStore.d.ts +1 -0
  14. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  15. package/lib/chain/archiveStore/archiveStore.js +5 -1
  16. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  17. package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts.map +1 -1
  18. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -0
  19. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
  20. package/lib/chain/archiveStore/historicalState/metrics.d.ts.map +1 -1
  21. package/lib/chain/archiveStore/historicalState/metrics.js +12 -1
  22. package/lib/chain/archiveStore/historicalState/metrics.js.map +1 -1
  23. package/lib/chain/archiveStore/historicalState/types.d.ts +2 -0
  24. package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
  25. package/lib/chain/archiveStore/historicalState/types.js.map +1 -1
  26. package/lib/chain/archiveStore/historicalState/worker.js +4 -1
  27. package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
  28. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +9 -1
  29. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
  30. package/lib/chain/archiveStore/utils/archiveBlocks.js +68 -38
  31. package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
  32. package/lib/chain/blocks/importBlock.d.ts +5 -1
  33. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  34. package/lib/chain/blocks/importBlock.js +12 -18
  35. package/lib/chain/blocks/importBlock.js.map +1 -1
  36. package/lib/chain/blocks/index.d.ts +8 -4
  37. package/lib/chain/blocks/index.d.ts.map +1 -1
  38. package/lib/chain/blocks/index.js +83 -17
  39. package/lib/chain/blocks/index.js.map +1 -1
  40. package/lib/chain/blocks/types.d.ts +8 -0
  41. package/lib/chain/blocks/types.d.ts.map +1 -1
  42. package/lib/chain/blocks/types.js.map +1 -1
  43. package/lib/chain/blocks/utils/chainSegment.d.ts +1 -1
  44. package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
  45. package/lib/chain/blocks/utils/chainSegment.js +26 -11
  46. package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
  47. package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
  48. package/lib/chain/blocks/writeBlockInputToDb.js +9 -16
  49. package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
  50. package/lib/chain/chain.d.ts +11 -5
  51. package/lib/chain/chain.d.ts.map +1 -1
  52. package/lib/chain/chain.js +129 -75
  53. package/lib/chain/chain.js.map +1 -1
  54. package/lib/chain/emitter.d.ts +1 -1
  55. package/lib/chain/emitter.js +1 -1
  56. package/lib/chain/errors/blockError.d.ts +14 -9
  57. package/lib/chain/errors/blockError.d.ts.map +1 -1
  58. package/lib/chain/errors/blockError.js +0 -2
  59. package/lib/chain/errors/blockError.js.map +1 -1
  60. package/lib/chain/errors/dataColumnSidecarError.d.ts +15 -2
  61. package/lib/chain/errors/dataColumnSidecarError.d.ts.map +1 -1
  62. package/lib/chain/errors/dataColumnSidecarError.js.map +1 -1
  63. package/lib/chain/errors/executionPayloadBid.d.ts +4 -0
  64. package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
  65. package/lib/chain/errors/executionPayloadBid.js +1 -0
  66. package/lib/chain/errors/executionPayloadBid.js.map +1 -1
  67. package/lib/chain/errors/executionPayloadEnvelope.d.ts +10 -11
  68. package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
  69. package/lib/chain/errors/executionPayloadEnvelope.js +0 -2
  70. package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
  71. package/lib/chain/errors/gossipValidation.d.ts +2 -1
  72. package/lib/chain/errors/gossipValidation.d.ts.map +1 -1
  73. package/lib/chain/errors/gossipValidation.js +1 -0
  74. package/lib/chain/errors/gossipValidation.js.map +1 -1
  75. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  76. package/lib/chain/forkChoice/index.js +2 -0
  77. package/lib/chain/forkChoice/index.js.map +1 -1
  78. package/lib/chain/interface.d.ts +4 -4
  79. package/lib/chain/interface.d.ts.map +1 -1
  80. package/lib/chain/lightClient/index.d.ts +3 -3
  81. package/lib/chain/lightClient/index.d.ts.map +1 -1
  82. package/lib/chain/lightClient/index.js +21 -23
  83. package/lib/chain/lightClient/index.js.map +1 -1
  84. package/lib/chain/lightClient/proofs.d.ts +2 -1
  85. package/lib/chain/lightClient/proofs.d.ts.map +1 -1
  86. package/lib/chain/lightClient/proofs.js +5 -1
  87. package/lib/chain/lightClient/proofs.js.map +1 -1
  88. package/lib/chain/opPools/aggregatedAttestationPool.js +1 -1
  89. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  90. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  91. package/lib/chain/prepareNextSlot.js +16 -14
  92. package/lib/chain/prepareNextSlot.js.map +1 -1
  93. package/lib/chain/produceBlock/produceBlockBody.d.ts +4 -2
  94. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  95. package/lib/chain/produceBlock/produceBlockBody.js +57 -72
  96. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  97. package/lib/chain/validation/block.d.ts.map +1 -1
  98. package/lib/chain/validation/block.js +27 -55
  99. package/lib/chain/validation/block.js.map +1 -1
  100. package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
  101. package/lib/chain/validation/dataColumnSidecar.js +38 -13
  102. package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
  103. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  104. package/lib/chain/validation/executionPayloadBid.js +56 -40
  105. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  106. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  107. package/lib/chain/validation/executionPayloadEnvelope.js +10 -29
  108. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  109. package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
  110. package/lib/chain/validation/payloadAttestationMessage.js +5 -6
  111. package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
  112. package/lib/chain/validatorMonitor.d.ts +7 -1
  113. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  114. package/lib/chain/validatorMonitor.js +22 -5
  115. package/lib/chain/validatorMonitor.js.map +1 -1
  116. package/lib/db/beacon.d.ts +14 -5
  117. package/lib/db/beacon.d.ts.map +1 -1
  118. package/lib/db/beacon.js +17 -3
  119. package/lib/db/beacon.js.map +1 -1
  120. package/lib/db/dataColumnStore.d.ts +39 -0
  121. package/lib/db/dataColumnStore.d.ts.map +1 -0
  122. package/lib/db/dataColumnStore.js +81 -0
  123. package/lib/db/dataColumnStore.js.map +1 -0
  124. package/lib/db/flatFileStore/atomicWrite.d.ts +8 -0
  125. package/lib/db/flatFileStore/atomicWrite.d.ts.map +1 -0
  126. package/lib/db/flatFileStore/atomicWrite.js +61 -0
  127. package/lib/db/flatFileStore/atomicWrite.js.map +1 -0
  128. package/lib/db/flatFileStore/dcolFormat.d.ts +90 -0
  129. package/lib/db/flatFileStore/dcolFormat.d.ts.map +1 -0
  130. package/lib/db/flatFileStore/dcolFormat.js +286 -0
  131. package/lib/db/flatFileStore/dcolFormat.js.map +1 -0
  132. package/lib/db/flatFileStore/errors.d.ts +82 -0
  133. package/lib/db/flatFileStore/errors.d.ts.map +1 -0
  134. package/lib/db/flatFileStore/errors.js +32 -0
  135. package/lib/db/flatFileStore/errors.js.map +1 -0
  136. package/lib/db/flatFileStore/flatFileStore.d.ts +41 -0
  137. package/lib/db/flatFileStore/flatFileStore.d.ts.map +1 -0
  138. package/lib/db/flatFileStore/flatFileStore.js +251 -0
  139. package/lib/db/flatFileStore/flatFileStore.js.map +1 -0
  140. package/lib/db/flatFileStore/index.d.ts +4 -0
  141. package/lib/db/flatFileStore/index.d.ts.map +1 -0
  142. package/lib/db/flatFileStore/index.js +2 -0
  143. package/lib/db/flatFileStore/index.js.map +1 -0
  144. package/lib/db/flatFileStore/interface.d.ts +25 -0
  145. package/lib/db/flatFileStore/interface.d.ts.map +1 -0
  146. package/lib/db/flatFileStore/interface.js +2 -0
  147. package/lib/db/flatFileStore/interface.js.map +1 -0
  148. package/lib/db/flatFileStore/metrics.d.ts +24 -0
  149. package/lib/db/flatFileStore/metrics.d.ts.map +1 -0
  150. package/lib/db/flatFileStore/metrics.js +25 -0
  151. package/lib/db/flatFileStore/metrics.js.map +1 -0
  152. package/lib/db/flatFileStore/path.d.ts +9 -0
  153. package/lib/db/flatFileStore/path.d.ts.map +1 -0
  154. package/lib/db/flatFileStore/path.js +21 -0
  155. package/lib/db/flatFileStore/path.js.map +1 -0
  156. package/lib/db/flatFileStore/slotIndex.d.ts +14 -0
  157. package/lib/db/flatFileStore/slotIndex.d.ts.map +1 -0
  158. package/lib/db/flatFileStore/slotIndex.js +46 -0
  159. package/lib/db/flatFileStore/slotIndex.js.map +1 -0
  160. package/lib/db/flatFileStore/snappy.d.ts +3 -0
  161. package/lib/db/flatFileStore/snappy.d.ts.map +1 -0
  162. package/lib/db/flatFileStore/snappy.js +12 -0
  163. package/lib/db/flatFileStore/snappy.js.map +1 -0
  164. package/lib/db/index.d.ts +1 -0
  165. package/lib/db/index.d.ts.map +1 -1
  166. package/lib/db/interface.d.ts +8 -1
  167. package/lib/db/interface.d.ts.map +1 -1
  168. package/lib/db/repositories/blockArchive.d.ts +8 -1
  169. package/lib/db/repositories/blockArchive.d.ts.map +1 -1
  170. package/lib/db/repositories/blockArchive.js +65 -28
  171. package/lib/db/repositories/blockArchive.js.map +1 -1
  172. package/lib/db/repositories/blockArchiveIndex.d.ts +1 -2
  173. package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
  174. package/lib/db/repositories/blockArchiveIndex.js +3 -7
  175. package/lib/db/repositories/blockArchiveIndex.js.map +1 -1
  176. package/lib/execution/builder/validateBid.d.ts.map +1 -1
  177. package/lib/execution/builder/validateBid.js +8 -5
  178. package/lib/execution/builder/validateBid.js.map +1 -1
  179. package/lib/execution/engine/mock.d.ts.map +1 -1
  180. package/lib/execution/engine/mock.js +4 -1
  181. package/lib/execution/engine/mock.js.map +1 -1
  182. package/lib/metrics/metrics/lodestar.d.ts +22 -3
  183. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  184. package/lib/metrics/metrics/lodestar.js +60 -6
  185. package/lib/metrics/metrics/lodestar.js.map +1 -1
  186. package/lib/monitoring/clientStats.js +1 -1
  187. package/lib/monitoring/clientStats.js.map +1 -1
  188. package/lib/network/gossip/encoding.d.ts.map +1 -1
  189. package/lib/network/gossip/encoding.js +0 -7
  190. package/lib/network/gossip/encoding.js.map +1 -1
  191. package/lib/network/gossip/topic.d.ts +2 -1
  192. package/lib/network/gossip/topic.d.ts.map +1 -1
  193. package/lib/network/gossip/topic.js +4 -20
  194. package/lib/network/gossip/topic.js.map +1 -1
  195. package/lib/network/libp2p/index.d.ts +9 -1
  196. package/lib/network/libp2p/index.d.ts.map +1 -1
  197. package/lib/network/libp2p/index.js +23 -0
  198. package/lib/network/libp2p/index.js.map +1 -1
  199. package/lib/network/network.js +2 -2
  200. package/lib/network/network.js.map +1 -1
  201. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  202. package/lib/network/processor/gossipHandlers.js +388 -285
  203. package/lib/network/processor/gossipHandlers.js.map +1 -1
  204. package/lib/network/processor/index.d.ts +49 -3
  205. package/lib/network/processor/index.d.ts.map +1 -1
  206. package/lib/network/processor/index.js +254 -114
  207. package/lib/network/processor/index.js.map +1 -1
  208. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
  209. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +112 -91
  210. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
  211. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.d.ts.map +1 -1
  212. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +2 -0
  213. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js.map +1 -1
  214. package/lib/network/reqresp/protocols.d.ts.map +1 -1
  215. package/lib/network/reqresp/protocols.js +6 -22
  216. package/lib/network/reqresp/protocols.js.map +1 -1
  217. package/lib/network/reqresp/rateLimit.js +2 -1
  218. package/lib/network/reqresp/rateLimit.js.map +1 -1
  219. package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts +2 -1
  220. package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts.map +1 -1
  221. package/lib/network/reqresp/utils/dataColumnResponseValidation.js +14 -9
  222. package/lib/network/reqresp/utils/dataColumnResponseValidation.js.map +1 -1
  223. package/lib/node/nodejs.d.ts +2 -1
  224. package/lib/node/nodejs.d.ts.map +1 -1
  225. package/lib/node/nodejs.js +4 -2
  226. package/lib/node/nodejs.js.map +1 -1
  227. package/lib/sync/range/range.d.ts.map +1 -1
  228. package/lib/sync/range/range.js +24 -1
  229. package/lib/sync/range/range.js.map +1 -1
  230. package/lib/util/sszBytes.d.ts +6 -0
  231. package/lib/util/sszBytes.d.ts.map +1 -1
  232. package/lib/util/sszBytes.js +1 -1
  233. package/lib/util/sszBytes.js.map +1 -1
  234. package/package.json +19 -20
  235. package/src/api/impl/beacon/blocks/index.ts +8 -14
  236. package/src/api/impl/beacon/state/utils.ts +15 -0
  237. package/src/api/impl/config/index.ts +4 -1
  238. package/src/api/impl/validator/index.ts +44 -43
  239. package/src/chain/archiveStore/archiveStore.ts +12 -1
  240. package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +1 -0
  241. package/src/chain/archiveStore/historicalState/metrics.ts +14 -1
  242. package/src/chain/archiveStore/historicalState/types.ts +2 -0
  243. package/src/chain/archiveStore/historicalState/worker.ts +4 -1
  244. package/src/chain/archiveStore/utils/archiveBlocks.ts +73 -42
  245. package/src/chain/blocks/importBlock.ts +25 -20
  246. package/src/chain/blocks/index.ts +120 -23
  247. package/src/chain/blocks/types.ts +9 -0
  248. package/src/chain/blocks/utils/chainSegment.ts +26 -12
  249. package/src/chain/blocks/writeBlockInputToDb.ts +10 -17
  250. package/src/chain/chain.ts +153 -84
  251. package/src/chain/emitter.ts +1 -1
  252. package/src/chain/errors/blockError.ts +19 -10
  253. package/src/chain/errors/dataColumnSidecarError.ts +24 -8
  254. package/src/chain/errors/executionPayloadBid.ts +2 -0
  255. package/src/chain/errors/executionPayloadEnvelope.ts +14 -11
  256. package/src/chain/errors/gossipValidation.ts +1 -0
  257. package/src/chain/forkChoice/index.ts +2 -0
  258. package/src/chain/interface.ts +4 -4
  259. package/src/chain/lightClient/index.ts +32 -36
  260. package/src/chain/lightClient/proofs.ts +10 -0
  261. package/src/chain/opPools/aggregatedAttestationPool.ts +1 -1
  262. package/src/chain/prepareNextSlot.ts +21 -17
  263. package/src/chain/produceBlock/produceBlockBody.ts +62 -79
  264. package/src/chain/validation/block.ts +27 -72
  265. package/src/chain/validation/dataColumnSidecar.ts +47 -14
  266. package/src/chain/validation/executionPayloadBid.ts +62 -44
  267. package/src/chain/validation/executionPayloadEnvelope.ts +10 -37
  268. package/src/chain/validation/payloadAttestationMessage.ts +8 -9
  269. package/src/chain/validatorMonitor.ts +24 -7
  270. package/src/db/beacon.ts +33 -6
  271. package/src/db/dataColumnStore.ts +113 -0
  272. package/src/db/flatFileStore/atomicWrite.ts +65 -0
  273. package/src/db/flatFileStore/dcolFormat.ts +389 -0
  274. package/src/db/flatFileStore/errors.ts +53 -0
  275. package/src/db/flatFileStore/flatFileStore.ts +310 -0
  276. package/src/db/flatFileStore/index.ts +3 -0
  277. package/src/db/flatFileStore/interface.ts +21 -0
  278. package/src/db/flatFileStore/metrics.ts +48 -0
  279. package/src/db/flatFileStore/path.ts +32 -0
  280. package/src/db/flatFileStore/slotIndex.ts +56 -0
  281. package/src/db/flatFileStore/snappy.ts +14 -0
  282. package/src/db/index.ts +1 -0
  283. package/src/db/interface.ts +9 -1
  284. package/src/db/repositories/blockArchive.ts +89 -30
  285. package/src/db/repositories/blockArchiveIndex.ts +4 -9
  286. package/src/execution/builder/validateBid.ts +10 -6
  287. package/src/execution/engine/mock.ts +4 -1
  288. package/src/metrics/metrics/lodestar.ts +63 -6
  289. package/src/monitoring/clientStats.ts +1 -1
  290. package/src/network/gossip/encoding.ts +0 -7
  291. package/src/network/gossip/topic.ts +3 -25
  292. package/src/network/libp2p/index.ts +28 -1
  293. package/src/network/network.ts +2 -2
  294. package/src/network/processor/gossipHandlers.ts +500 -355
  295. package/src/network/processor/index.ts +287 -165
  296. package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +139 -105
  297. package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +2 -0
  298. package/src/network/reqresp/protocols.ts +7 -24
  299. package/src/network/reqresp/rateLimit.ts +2 -1
  300. package/src/network/reqresp/utils/dataColumnResponseValidation.ts +15 -7
  301. package/src/node/nodejs.ts +6 -1
  302. package/src/sync/range/range.ts +23 -1
  303. package/src/util/sszBytes.ts +1 -1
@@ -35,7 +35,7 @@ import {IArchiveStore} from "./archiveStore/interface.js";
35
35
  import {CheckpointBalancesCache} from "./balancesCache.js";
36
36
  import {BeaconProposerCache, ProposerPreparationData} from "./beaconProposerCache.js";
37
37
  import {IBlockInput} from "./blocks/blockInput/index.js";
38
- import {ImportBlockOpts, ImportPayloadOpts} from "./blocks/types.js";
38
+ import {ImportBlockOpts, ImportPayloadOpts, ProcessBlocksResult} from "./blocks/types.js";
39
39
  import {IBlsVerifier} from "./bls/index.js";
40
40
  import {BuilderCircuitBreaker} from "./builderCircuitBreaker.js";
41
41
  import {ColumnReconstructionTracker} from "./ColumnReconstructionTracker.js";
@@ -262,7 +262,7 @@ export interface IBeaconChain {
262
262
  blocks: IBlockInput[],
263
263
  payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
264
264
  opts?: ImportBlockOpts
265
- ): Promise<void>;
265
+ ): Promise<ProcessBlocksResult>;
266
266
 
267
267
  /** Process execution payload envelope: verify, import to fork choice, and persist to DB */
268
268
  processExecutionPayload(payloadInput: PayloadEnvelopeInput, opts?: ImportPayloadOpts): Promise<void>;
@@ -290,8 +290,8 @@ export interface IBeaconChain {
290
290
  postState: IBeaconStateView,
291
291
  block: SignedBeaconBlock
292
292
  ): Promise<void>;
293
- persistInvalidSszValue<T>(type: Type<T>, sszObject: T | Uint8Array, suffix?: string): void;
294
- persistInvalidSszBytes(type: string, sszBytes: Uint8Array, suffix?: string): void;
293
+ persistInvalidSszValue<T>(type: Type<T>, sszObject: T, suffix?: string, rootHex?: RootHex): void;
294
+ persistInvalidSszBytes(type: string, sszBytes: Uint8Array, rootHex: RootHex, suffix?: string): void;
295
295
  regenStateForAttestationVerification(
296
296
  attEpoch: Epoch,
297
297
  shufflingDependentRoot: RootHex,
@@ -5,6 +5,7 @@ import {
5
5
  ForkName,
6
6
  ForkPostAltair,
7
7
  ForkPostBellatrix,
8
+ ForkPostGloas,
8
9
  ForkPreGloas,
9
10
  ForkSeq,
10
11
  MIN_SYNC_COMMITTEE_PARTICIPANTS,
@@ -40,7 +41,6 @@ import {
40
41
  Slot,
41
42
  SyncPeriod,
42
43
  altair,
43
- electra,
44
44
  phase0,
45
45
  ssz,
46
46
  } from "@lodestar/types";
@@ -52,7 +52,12 @@ import {Metrics} from "../../metrics/index.js";
52
52
  import {IClock} from "../../util/clock.js";
53
53
  import {ChainEventEmitter} from "../emitter.js";
54
54
  import {LightClientServerError, LightClientServerErrorCode} from "../errors/lightClientError.js";
55
- import {getBlockBodyExecutionHeaderProof, getCurrentSyncCommitteeBranch, getNextSyncCommitteeBranch} from "./proofs.js";
55
+ import {
56
+ getBlockBodyExecutionBlockHashProof,
57
+ getBlockBodyExecutionHeaderProof,
58
+ getCurrentSyncCommitteeBranch,
59
+ getNextSyncCommitteeBranch,
60
+ } from "./proofs.js";
56
61
 
57
62
  export type LightClientServerOpts = {
58
63
  disableLightClientServerOnImportBlockHead?: boolean;
@@ -61,6 +66,7 @@ export type LightClientServerOpts = {
61
66
 
62
67
  type DependentRootHex = RootHex;
63
68
  type BlockRooHex = RootHex;
69
+ type LightClientZeroFinality = Pick<LightClientUpdate, "finalityBranch" | "finalizedHeader">;
64
70
 
65
71
  export type SyncAttestedData = {
66
72
  attestedHeader: LightClientHeader;
@@ -199,6 +205,7 @@ export class LightClientServer {
199
205
  private readonly clock: IClock;
200
206
  private readonly signal: AbortSignal;
201
207
  private readonly knownSyncCommittee = new MapDef<SyncPeriod, Set<DependentRootHex>>(() => new Set());
208
+ private readonly zeroFinalityByFork = new Map<ForkName, LightClientZeroFinality>();
202
209
  private storedCurrentSyncCommittee = false;
203
210
 
204
211
  /**
@@ -208,10 +215,6 @@ export class LightClientServer {
208
215
  private checkpointHeaders = new Map<BlockRooHex, LightClientHeader>();
209
216
  private latestHeadUpdate: LightClientOptimisticUpdate | null = null;
210
217
 
211
- private readonly zero: Pick<
212
- altair.LightClientUpdate | electra.LightClientUpdate,
213
- "finalityBranch" | "finalizedHeader"
214
- >;
215
218
  private finalized: LightClientFinalityUpdate | null = null;
216
219
 
217
220
  constructor(
@@ -227,14 +230,6 @@ export class LightClientServer {
227
230
  this.logger = logger;
228
231
  this.signal = signal;
229
232
 
230
- this.zero = {
231
- // Assign the highest pre-Gloas light-client header because post-Gloas light-client updates are skipped for now.
232
- finalizedHeader: ssz.electra.LightClientHeader.defaultValue(),
233
- // Electra finalityBranch has fixed length of 5 whereas altair has 4. The fifth element will be ignored
234
- // when serializing as altair LightClientUpdate
235
- finalityBranch: ssz.electra.LightClientUpdate.fields.finalityBranch.defaultValue(),
236
- };
237
-
238
233
  if (metrics) {
239
234
  metrics.lightclientServer.highestSlot.addCollect(() => {
240
235
  if (this.latestHeadUpdate) {
@@ -270,14 +265,6 @@ export class LightClientServer {
270
265
  return;
271
266
  }
272
267
 
273
- // TODO GLOAS: Light client updates for gloas are not yet updated in the spec.
274
- // The block body no longer contains execution payload, so `blockToLightClientHeader`
275
- // cannot construct a header from a gloas block. Skip all light client processing
276
- // for post-gloas blocks, revisit once there is a spec for it.
277
- if (this.config.getForkSeq(block.slot) >= ForkSeq.gloas) {
278
- return;
279
- }
280
-
281
268
  // What is the syncAggregate signing?
282
269
  // From the state-transition
283
270
  // ```
@@ -695,9 +682,16 @@ export class LightClientServer {
695
682
  }
696
683
  } else {
697
684
  isFinalized = false;
698
- finalityBranch = this.zero.finalityBranch;
699
- // No need to upgrade finalizedHeader because its anyway set to zero of highest fork
700
- finalizedHeader = this.zero.finalizedHeader;
685
+ let zeroFinality = this.zeroFinalityByFork.get(attestedFork);
686
+ if (!zeroFinality) {
687
+ const {finalityBranch, finalizedHeader} = this.config
688
+ .getPostAltairForkTypes(attestedHeader.beacon.slot)
689
+ .LightClientUpdate.defaultValue();
690
+ zeroFinality = {finalityBranch, finalizedHeader};
691
+ this.zeroFinalityByFork.set(attestedFork, zeroFinality);
692
+ }
693
+ finalityBranch = zeroFinality.finalityBranch;
694
+ finalizedHeader = zeroFinality.finalizedHeader;
701
695
  }
702
696
 
703
697
  const newUpdate = {
@@ -769,22 +763,24 @@ export function sumBits(bits: BitArray): number {
769
763
  return bits.getTrueBitIndexes().length;
770
764
  }
771
765
 
772
- // TODO GLOAS: Pending light-client spec but this function probably won't be used
773
- // in Gloas. So we can assume any types here are pre-gloas
774
- export function blockToLightClientHeader(
775
- fork: ForkName,
776
- block: BeaconBlock<ForkPostAltair & ForkPreGloas>
777
- ): LightClientHeader {
778
- const blockSlot = block.slot;
766
+ export function blockToLightClientHeader(fork: ForkName, block: BeaconBlock<ForkPostAltair>): LightClientHeader {
779
767
  const beacon: phase0.BeaconBlockHeader = {
780
- slot: blockSlot,
768
+ slot: block.slot,
781
769
  proposerIndex: block.proposerIndex,
782
770
  parentRoot: block.parentRoot,
783
771
  stateRoot: block.stateRoot,
784
- bodyRoot: (ssz[fork].BeaconBlockBody as SSZTypesFor<ForkPostAltair & ForkPreGloas, "BeaconBlockBody">).hashTreeRoot(
785
- block.body
786
- ),
772
+ bodyRoot: (ssz[fork].BeaconBlockBody as SSZTypesFor<ForkPostAltair, "BeaconBlockBody">).hashTreeRoot(block.body),
787
773
  };
774
+
775
+ if (isForkPostGloas(fork)) {
776
+ const blockBody = block.body as BeaconBlockBody<ForkPostGloas>;
777
+ return {
778
+ beacon,
779
+ executionBlockHash: blockBody.signedExecutionPayloadBid.message.parentBlockHash,
780
+ executionBranch: getBlockBodyExecutionBlockHashProof(fork, blockBody),
781
+ };
782
+ }
783
+
788
784
  if (ForkSeq[fork] >= ForkSeq.capella) {
789
785
  const blockBody = block.body as BeaconBlockBody<ForkPostBellatrix & ForkPreGloas>;
790
786
  const execution = executionPayloadToPayloadHeader(ForkSeq[fork], blockBody.executionPayload);
@@ -2,11 +2,13 @@ import {Tree} from "@chainsafe/persistent-merkle-tree";
2
2
  import {
3
3
  BLOCK_BODY_EXECUTION_PAYLOAD_GINDEX,
4
4
  CURRENT_SYNC_COMMITTEE_GINDEX_GLOAS,
5
+ EXECUTION_BLOCK_HASH_GINDEX_GLOAS,
5
6
  FINALIZED_ROOT_GINDEX,
6
7
  FINALIZED_ROOT_GINDEX_ELECTRA,
7
8
  FINALIZED_ROOT_GINDEX_GLOAS,
8
9
  ForkName,
9
10
  ForkPostBellatrix,
11
+ ForkPostGloas,
10
12
  NEXT_SYNC_COMMITTEE_GINDEX_GLOAS,
11
13
  isForkPostElectra,
12
14
  isForkPostGloas,
@@ -116,3 +118,11 @@ export function getBlockBodyExecutionHeaderProof(
116
118
  const bodyView = (ssz[fork].BeaconBlockBody as SSZTypesFor<ForkPostBellatrix, "BeaconBlockBody">).toView(body);
117
119
  return new Tree(bodyView.node).getSingleProof(BigInt(BLOCK_BODY_EXECUTION_PAYLOAD_GINDEX));
118
120
  }
121
+
122
+ export function getBlockBodyExecutionBlockHashProof(
123
+ fork: ForkPostGloas,
124
+ body: BeaconBlockBody<ForkPostGloas>
125
+ ): Uint8Array[] {
126
+ const bodyView = (ssz[fork].BeaconBlockBody as SSZTypesFor<ForkPostGloas, "BeaconBlockBody">).toView(body);
127
+ return new Tree(bodyView.node).getSingleProof(BigInt(EXECUTION_BLOCK_HASH_GINDEX_GLOAS));
128
+ }
@@ -363,7 +363,7 @@ export class AggregatedAttestationPool {
363
363
  stateEpoch,
364
364
  rootCache,
365
365
  gloasState?.executionPayloadAvailability ?? null,
366
- gloasState?.latestExecutionPayloadBid.slot ?? null
366
+ gloasState?.latestBlockHeader.slot ?? null
367
367
  );
368
368
 
369
369
  const weight =
@@ -25,6 +25,7 @@ import {Bytes32, Slot, ValidatorIndex} from "@lodestar/types";
25
25
  import {Logger, fromHex, isErrorAborted, sleep} from "@lodestar/utils";
26
26
  import {GENESIS_SLOT} from "../constants/constants.js";
27
27
  import {BuilderStatus} from "../execution/builder/http.js";
28
+ import {PayloadAttributes} from "../execution/index.js";
28
29
  import {Metrics} from "../metrics/index.js";
29
30
  import {ClockEvent} from "../util/clock.js";
30
31
  import {isQueueErrorAborted} from "../util/queue/index.js";
@@ -243,6 +244,24 @@ export class PrepareNextSlotScheduler {
243
244
  parentBlockHash = preparedState.latestExecutionPayloadHeader.blockHash;
244
245
  }
245
246
 
247
+ let payloadAttributes: PayloadAttributes | undefined;
248
+ // If emitPayloadAttributes is true emit a SSE payloadAttributes event for
249
+ // every slot. Without the flag, only emit the event if we are proposing in the next slot.
250
+ if (
251
+ (feeRecipient || this.chain.opts.emitPayloadAttributes === true) &&
252
+ this.chain.emitter.listenerCount(routes.events.EventType.payloadAttributes)
253
+ ) {
254
+ const data = getPayloadAttributesForSSE(fork as ForkPostBellatrix, this.chain, {
255
+ prepareState: stateAfterParentPayload,
256
+ prepareSlot,
257
+ parentBlockRoot: fromHex(updatedHead.blockRoot),
258
+ parentBlockHash,
259
+ feeRecipient: feeRecipient ?? "0x0000000000000000000000000000000000000000",
260
+ });
261
+ this.chain.emitter.emit(routes.events.EventType.payloadAttributes, {data, version: fork});
262
+ payloadAttributes = data.payloadAttributes;
263
+ }
264
+
246
265
  if (feeRecipient) {
247
266
  const preparationTime =
248
267
  computeTimeAtSlot(this.config, prepareSlot, this.chain.genesisTime) - Date.now() / 1000;
@@ -263,7 +282,8 @@ export class PrepareNextSlotScheduler {
263
282
  safeBlockHash,
264
283
  finalizedBlockHash,
265
284
  stateAfterParentPayload,
266
- feeRecipient
285
+ feeRecipient,
286
+ payloadAttributes
267
287
  );
268
288
  this.logger.verbose("PrepareNextSlotScheduler prepared new payload", {
269
289
  prepareSlot,
@@ -273,22 +293,6 @@ export class PrepareNextSlotScheduler {
273
293
  }
274
294
 
275
295
  this.computeStateHashTreeRoot(preparedState, isEpochTransition);
276
-
277
- // If emitPayloadAttributes is true emit a SSE payloadAttributes event for
278
- // every slot. Without the flag, only emit the event if we are proposing in the next slot.
279
- if (
280
- (feeRecipient || this.chain.opts.emitPayloadAttributes === true) &&
281
- this.chain.emitter.listenerCount(routes.events.EventType.payloadAttributes)
282
- ) {
283
- const data = getPayloadAttributesForSSE(fork as ForkPostBellatrix, this.chain, {
284
- prepareState: stateAfterParentPayload,
285
- prepareSlot,
286
- parentBlockRoot: fromHex(updatedHead.blockRoot),
287
- parentBlockHash,
288
- feeRecipient: feeRecipient ?? "0x0000000000000000000000000000000000000000",
289
- });
290
- this.chain.emitter.emit(routes.events.EventType.payloadAttributes, {data, version: fork});
291
- }
292
296
  } else {
293
297
  // Pre-bellatrix only reaches here at an epoch transition to precompute the next epoch state
294
298
  const preparedState = await this.chain.regen.getBlockSlotState(
@@ -528,23 +528,18 @@ export async function produceBlockBody<T extends BlockType>(
528
528
  }
529
529
  }
530
530
 
531
- if (ForkSeq[fork] >= ForkSeq.deneb) {
532
- const {blobKzgCommitments} = builderRes;
533
- if (blobKzgCommitments === undefined) {
534
- throw Error(`Invalid builder getHeader response for fork=${fork}, missing blobKzgCommitments`);
535
- }
536
-
537
- (blockBody as deneb.BlindedBeaconBlockBody).blobKzgCommitments = blobKzgCommitments;
538
- Object.assign(logMeta, {blobs: blobKzgCommitments.length});
531
+ const {blobKzgCommitments, executionRequests} = builderRes;
532
+ if (blobKzgCommitments === undefined) {
533
+ throw Error(`Invalid builder getHeader response for fork=${fork}, missing blobKzgCommitments`);
539
534
  }
540
535
 
541
- if (ForkSeq[fork] >= ForkSeq.electra) {
542
- const {executionRequests} = builderRes;
543
- if (executionRequests === undefined) {
544
- throw Error(`Invalid builder getHeader response for fork=${fork}, missing executionRequests`);
545
- }
546
- (blockBody as electra.BlindedBeaconBlockBody).executionRequests = executionRequests;
536
+ (blockBody as BlindedBeaconBlockBody<ForkName.fulu>).blobKzgCommitments = blobKzgCommitments;
537
+ Object.assign(logMeta, {blobs: blobKzgCommitments.length});
538
+
539
+ if (executionRequests === undefined) {
540
+ throw Error(`Invalid builder getHeader response for fork=${fork}, missing executionRequests`);
547
541
  }
542
+ (blockBody as BlindedBeaconBlockBody<ForkName.fulu>).executionRequests = executionRequests;
548
543
  }
549
544
 
550
545
  // blockType === BlockType.Full
@@ -740,7 +735,9 @@ export async function prepareExecutionPayload(
740
735
  * parent execution payload first (see `withParentPayloadApplied`).
741
736
  */
742
737
  state: IBeaconStateViewBellatrix,
743
- suggestedFeeRecipient: string
738
+ suggestedFeeRecipient: string,
739
+ /** Attributes already computed for the same state and fee recipient, e.g. for the SSE event */
740
+ payloadAttributes?: PayloadAttributes
744
741
  ): Promise<{prepType: PayloadPreparationType; payloadId: PayloadId}> {
745
742
  const timestamp = computeTimeAtSlot(chain.config, state.slot, state.genesisTime);
746
743
  const prevRandao = state.getRandaoMix(state.epoch);
@@ -771,13 +768,15 @@ export async function prepareExecutionPayload(
771
768
  prepType = PayloadPreparationType.Fresh;
772
769
  }
773
770
 
774
- const attributes: PayloadAttributes = preparePayloadAttributes(fork, chain, {
775
- prepareState: state,
776
- prepareSlot: state.slot,
777
- parentBlockRoot,
778
- parentBlockHash,
779
- feeRecipient: suggestedFeeRecipient,
780
- });
771
+ const attributes: PayloadAttributes =
772
+ payloadAttributes ??
773
+ preparePayloadAttributes(fork, chain, {
774
+ prepareState: state,
775
+ prepareSlot: state.slot,
776
+ parentBlockRoot,
777
+ parentBlockHash,
778
+ feeRecipient: suggestedFeeRecipient,
779
+ });
781
780
 
782
781
  payloadId = await chain.executionEngine.notifyForkchoiceUpdate(
783
782
  fork,
@@ -899,45 +898,38 @@ function preparePayloadAttributes(
899
898
  ): SSEPayloadAttributes["payloadAttributes"] {
900
899
  const timestamp = computeTimeAtSlot(chain.config, prepareSlot, prepareState.genesisTime);
901
900
  const prevRandao = prepareState.getRandaoMix(prepareState.epoch);
902
- const payloadAttributes = {
903
- timestamp,
904
- prevRandao,
905
- suggestedFeeRecipient: feeRecipient,
906
- };
907
-
908
- if (ForkSeq[fork] >= ForkSeq.capella) {
909
- if (!isStatePostCapella(prepareState)) {
910
- throw new Error("Expected Capella state for withdrawals");
911
- }
901
+ if (!isStatePostCapella(prepareState)) {
902
+ throw new Error("Expected Capella state for withdrawals");
903
+ }
912
904
 
913
- if (isStatePostGloas(prepareState)) {
914
- const isExtendingPayload = byteArrayEquals(parentBlockHash, prepareState.latestExecutionPayloadBid.blockHash);
915
- if (isExtendingPayload) {
916
- // applyParentExecutionPayload sets latestBlockHash = parentBid.blockHash, so a mismatch
917
- // here means the caller did not apply parent payload to prepareState
918
- if (!byteArrayEquals(prepareState.latestBlockHash, prepareState.latestExecutionPayloadBid.blockHash)) {
919
- throw new Error("Expected state with parent execution payload applied for withdrawals");
920
- }
921
- (payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
922
- prepareState.getExpectedWithdrawals().expectedWithdrawals;
923
- } else {
924
- // When the parent block is empty, state.payloadExpectedWithdrawals holds a batch
925
- // already deducted from CL balances but never credited on the EL (the envelope
926
- // was not delivered). The next payload must carry those same withdrawals to
927
- // restore CL/EL consistency, otherwise validators permanently lose that balance.
928
- (payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
929
- prepareState.payloadExpectedWithdrawals;
905
+ let withdrawals: capella.Withdrawal[];
906
+ if (isStatePostGloas(prepareState)) {
907
+ const isExtendingPayload = byteArrayEquals(parentBlockHash, prepareState.latestExecutionPayloadBid.blockHash);
908
+ if (isExtendingPayload) {
909
+ // applyParentExecutionPayload sets latestBlockHash = parentBid.blockHash, so a mismatch
910
+ // here means the caller did not apply parent payload to prepareState
911
+ if (!byteArrayEquals(prepareState.latestBlockHash, prepareState.latestExecutionPayloadBid.blockHash)) {
912
+ throw new Error("Expected state with parent execution payload applied for withdrawals");
930
913
  }
914
+ withdrawals = prepareState.getExpectedWithdrawals().expectedWithdrawals;
931
915
  } else {
932
- // withdrawals logic is now fork aware as it changes on electra fork post capella
933
- (payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
934
- prepareState.getExpectedWithdrawals().expectedWithdrawals;
916
+ // When the parent block is empty, state.payloadExpectedWithdrawals holds a batch
917
+ // already deducted from CL balances but never credited on the EL (the envelope
918
+ // was not delivered). The next payload must carry those same withdrawals to
919
+ // restore CL/EL consistency, otherwise validators permanently lose that balance.
920
+ withdrawals = prepareState.payloadExpectedWithdrawals;
935
921
  }
922
+ } else {
923
+ withdrawals = prepareState.getExpectedWithdrawals().expectedWithdrawals;
936
924
  }
937
925
 
938
- if (ForkSeq[fork] >= ForkSeq.deneb) {
939
- (payloadAttributes as deneb.SSEPayloadAttributes["payloadAttributes"]).parentBeaconBlockRoot = parentBlockRoot;
940
- }
926
+ const payloadAttributes: deneb.SSEPayloadAttributes["payloadAttributes"] = {
927
+ timestamp,
928
+ prevRandao,
929
+ suggestedFeeRecipient: feeRecipient,
930
+ withdrawals,
931
+ parentBeaconBlockRoot: parentBlockRoot,
932
+ };
941
933
 
942
934
  if (ForkSeq[fork] >= ForkSeq.gloas) {
943
935
  if (!isStatePostGloas(prepareState)) {
@@ -1050,37 +1042,28 @@ export async function produceCommonBlockBody<T extends BlockType>(
1050
1042
  step: BlockProductionStep.attestations,
1051
1043
  });
1052
1044
 
1053
- const blockBody: Omit<CommonBlockBody, "blsToExecutionChanges" | "syncAggregate"> = {
1045
+ const endSyncAggregate = stepsMetrics?.startTimer();
1046
+ const parentBlockRoot = fromHex(parentBlock.blockRoot);
1047
+ const previousSlot = slot - 1;
1048
+ const syncAggregate = this.syncContributionAndProofPool.getAggregate(previousSlot, parentBlockRoot);
1049
+ this.metrics?.production.producedSyncAggregateParticipants.observe(
1050
+ syncAggregate.syncCommitteeBits.getTrueBitIndexes().length
1051
+ );
1052
+ endSyncAggregate?.({
1053
+ step: BlockProductionStep.syncAggregate,
1054
+ });
1055
+
1056
+ // Live proposal production is supported from Fulu onward.
1057
+ return {
1054
1058
  randaoReveal,
1055
1059
  graffiti,
1056
- // Eth1 data voting is no longer required since electra
1057
1060
  eth1Data: currentState.eth1Data,
1058
1061
  proposerSlashings: this.opts.disableProposerSlashings === true ? [] : proposerSlashings,
1059
1062
  attesterSlashings,
1060
1063
  attestations,
1061
- // Since electra, deposits are processed by the execution layer,
1062
- // we no longer support handling deposits from earlier forks.
1063
1064
  deposits: [],
1064
1065
  voluntaryExits,
1066
+ blsToExecutionChanges,
1067
+ syncAggregate,
1065
1068
  };
1066
-
1067
- if (ForkSeq[fork] >= ForkSeq.capella) {
1068
- (blockBody as CommonBlockBody).blsToExecutionChanges = blsToExecutionChanges;
1069
- }
1070
-
1071
- const endSyncAggregate = stepsMetrics?.startTimer();
1072
- if (ForkSeq[fork] >= ForkSeq.altair) {
1073
- const parentBlockRoot = fromHex(parentBlock.blockRoot);
1074
- const previousSlot = slot - 1;
1075
- const syncAggregate = this.syncContributionAndProofPool.getAggregate(previousSlot, parentBlockRoot);
1076
- this.metrics?.production.producedSyncAggregateParticipants.observe(
1077
- syncAggregate.syncCommitteeBits.getTrueBitIndexes().length
1078
- );
1079
- (blockBody as CommonBlockBody).syncAggregate = syncAggregate;
1080
- }
1081
- endSyncAggregate?.({
1082
- step: BlockProductionStep.syncAggregate,
1083
- });
1084
-
1085
- return blockBody as CommonBlockBody;
1086
1069
  }
@@ -1,22 +1,6 @@
1
1
  import {ChainForkConfig} from "@lodestar/config";
2
2
  import {ExecutionStatus} from "@lodestar/fork-choice";
3
- import {
4
- ForkName,
5
- MAX_ATTESTATIONS_ELECTRA,
6
- MAX_ATTESTER_SLASHINGS_ELECTRA,
7
- MAX_BLS_TO_EXECUTION_CHANGES,
8
- MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD,
9
- MAX_BUILDER_EXIT_REQUESTS_PER_PAYLOAD,
10
- MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD,
11
- MAX_PAYLOAD_ATTESTATIONS,
12
- MAX_PROPOSER_SLASHINGS,
13
- MAX_VOLUNTARY_EXITS,
14
- MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD,
15
- MIN_SEED_LOOKAHEAD,
16
- isForkPostBellatrix,
17
- isForkPostDeneb,
18
- isForkPostGloas,
19
- } from "@lodestar/params";
3
+ import {ForkName, MIN_SEED_LOOKAHEAD, isForkPostBellatrix, isForkPostDeneb, isForkPostGloas} from "@lodestar/params";
20
4
  import {
21
5
  computeEpochAtSlot,
22
6
  computeStartSlotAtEpoch,
@@ -150,8 +134,9 @@ export async function validateGossipBlock(
150
134
  if (parentBlock.slot >= blockSlot) {
151
135
  throw new BlockGossipError(GossipAction.REJECT, {
152
136
  code: BlockErrorCode.NOT_LATER_THAN_PARENT,
153
- parentSlot: parentBlock.slot,
154
137
  slot: blockSlot,
138
+ root: blockRoot,
139
+ parentSlot: parentBlock.slot,
155
140
  });
156
141
  }
157
142
 
@@ -166,6 +151,8 @@ export async function validateGossipBlock(
166
151
  if (blobKzgCommitmentsLen > maxBlobsPerBlock) {
167
152
  throw new BlockGossipError(GossipAction.REJECT, {
168
153
  code: BlockErrorCode.TOO_MANY_KZG_COMMITMENTS,
154
+ slot: blockSlot,
155
+ root: blockRoot,
169
156
  blobKzgCommitmentsLen,
170
157
  commitmentLimit: maxBlobsPerBlock,
171
158
  });
@@ -173,7 +160,8 @@ export async function validateGossipBlock(
173
160
  }
174
161
 
175
162
  if (isForkPostGloas(fork)) {
176
- const bid = (block as gloas.BeaconBlock).body.signedExecutionPayloadBid.message;
163
+ const body = (block as gloas.BeaconBlock).body;
164
+ const bid = body.signedExecutionPayloadBid.message;
177
165
 
178
166
  // [REJECT] The length of KZG commitments is less than or equal to the limitation defined in Consensus Layer
179
167
  // -- i.e. validate that len(bid.blob_kzg_commitments) <= max_blobs_per_block
@@ -182,6 +170,8 @@ export async function validateGossipBlock(
182
170
  if (blobKzgCommitmentsLen > maxBlobsPerBlock) {
183
171
  throw new BlockGossipError(GossipAction.REJECT, {
184
172
  code: BlockErrorCode.TOO_MANY_KZG_COMMITMENTS,
173
+ slot: blockSlot,
174
+ root: blockRoot,
185
175
  blobKzgCommitmentsLen,
186
176
  commitmentLimit: maxBlobsPerBlock,
187
177
  });
@@ -191,61 +181,13 @@ export async function validateGossipBlock(
191
181
  if (!byteArrayEquals(bid.parentBlockRoot, block.parentRoot)) {
192
182
  throw new BlockGossipError(GossipAction.REJECT, {
193
183
  code: BlockErrorCode.BID_PARENT_ROOT_MISMATCH,
184
+ slot: blockSlot,
185
+ root: blockRoot,
194
186
  bidParentRoot: toRootHex(bid.parentBlockRoot),
195
187
  blockParentRoot: parentRoot,
196
188
  });
197
189
  }
198
190
 
199
- // [REJECT] The counts of `block.body.parent_execution_requests` are within
200
- // their respective limits -- i.e. validate that
201
- // `len(block.body.parent_execution_requests.withdrawals) <= MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD`,
202
- // `len(block.body.parent_execution_requests.consolidations) <= MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD`,
203
- // `len(block.body.parent_execution_requests.builder_deposits) <= MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD`,
204
- // and
205
- // `len(block.body.parent_execution_requests.builder_exits) <= MAX_BUILDER_EXIT_REQUESTS_PER_PAYLOAD`.
206
- // [REJECT] The counts of the block body operations are within their respective
207
- // limits -- i.e. validate that
208
- // `len(block.body.proposer_slashings) <= MAX_PROPOSER_SLASHINGS`,
209
- // `len(block.body.attester_slashings) <= MAX_ATTESTER_SLASHINGS_ELECTRA`,
210
- // `len(block.body.attestations) <= MAX_ATTESTATIONS_ELECTRA`,
211
- // `len(block.body.deposits) == 0`,
212
- // `len(block.body.voluntary_exits) <= MAX_VOLUNTARY_EXITS`,
213
- // `len(block.body.bls_to_execution_changes) <= MAX_BLS_TO_EXECUTION_CHANGES`,
214
- // and `len(block.body.payload_attestations) <= MAX_PAYLOAD_ATTESTATIONS`.
215
- const body = (block as gloas.BeaconBlock).body;
216
- const requests = body.parentExecutionRequests;
217
- const countLimits: [string, number, number][] = [
218
- ["parentExecutionRequests.withdrawals", requests.withdrawals.length, MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD],
219
- [
220
- "parentExecutionRequests.consolidations",
221
- requests.consolidations.length,
222
- MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD,
223
- ],
224
- [
225
- "parentExecutionRequests.builderDeposits",
226
- requests.builderDeposits.length,
227
- MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD,
228
- ],
229
- ["parentExecutionRequests.builderExits", requests.builderExits.length, MAX_BUILDER_EXIT_REQUESTS_PER_PAYLOAD],
230
- ["proposerSlashings", body.proposerSlashings.length, MAX_PROPOSER_SLASHINGS],
231
- ["attesterSlashings", body.attesterSlashings.length, MAX_ATTESTER_SLASHINGS_ELECTRA],
232
- ["attestations", body.attestations.length, MAX_ATTESTATIONS_ELECTRA],
233
- ["deposits", body.deposits.length, 0],
234
- ["voluntaryExits", body.voluntaryExits.length, MAX_VOLUNTARY_EXITS],
235
- ["blsToExecutionChanges", body.blsToExecutionChanges.length, MAX_BLS_TO_EXECUTION_CHANGES],
236
- ["payloadAttestations", body.payloadAttestations.length, MAX_PAYLOAD_ATTESTATIONS],
237
- ];
238
- for (const [name, count, limit] of countLimits) {
239
- if (count > limit) {
240
- throw new BlockGossipError(GossipAction.REJECT, {
241
- code: BlockErrorCode.TOO_MANY_BLOCK_OPERATIONS,
242
- name,
243
- count,
244
- limit,
245
- });
246
- }
247
- }
248
-
249
191
  // TODO GLOAS: [REJECT] The block's execution payload parent (defined by bid.parent_block_hash) passes all validation
250
192
  // This requires execution engine integration to verify the parent block hash
251
193
  }
@@ -306,6 +248,8 @@ export async function validateGossipBlock(
306
248
  if (executionPayload.timestamp !== computeTimeAtSlot(config, blockSlot, chain.genesisTime)) {
307
249
  throw new BlockGossipError(GossipAction.REJECT, {
308
250
  code: BlockErrorCode.INCORRECT_TIMESTAMP,
251
+ slot: blockSlot,
252
+ root: blockRoot,
309
253
  timestamp: executionPayload.timestamp,
310
254
  expectedTimestamp,
311
255
  });
@@ -315,7 +259,12 @@ export async function validateGossipBlock(
315
259
 
316
260
  // [REJECT] The proposer index is a valid validator index
317
261
  if (proposerIndex >= state.validatorCount) {
318
- throw new BlockGossipError(GossipAction.REJECT, {code: BlockErrorCode.UNKNOWN_PROPOSER, proposerIndex});
262
+ throw new BlockGossipError(GossipAction.REJECT, {
263
+ code: BlockErrorCode.UNKNOWN_PROPOSER,
264
+ slot: blockSlot,
265
+ root: blockRoot,
266
+ proposerIndex,
267
+ });
319
268
  }
320
269
 
321
270
  // [REJECT] The proposer signature, signed_beacon_block.signature, is valid with respect to the proposer_index pubkey.
@@ -327,7 +276,12 @@ export async function validateGossipBlock(
327
276
  // shuffling, the block MAY be queued for later processing while proposers for the block's branch are calculated --
328
277
  // in such a case do not REJECT, instead IGNORE this message.
329
278
  if (state.getBeaconProposer(blockSlot) !== proposerIndex) {
330
- throw new BlockGossipError(GossipAction.REJECT, {code: BlockErrorCode.INCORRECT_PROPOSER, proposerIndex});
279
+ throw new BlockGossipError(GossipAction.REJECT, {
280
+ code: BlockErrorCode.INCORRECT_PROPOSER,
281
+ slot: blockSlot,
282
+ root: blockRoot,
283
+ proposerIndex,
284
+ });
331
285
  }
332
286
 
333
287
  // Simple implementation of a pending block queue. Keeping the block here recycles the queue logic, and keeps the
@@ -372,7 +326,8 @@ export async function verifyBlockProposerSignature(
372
326
  if (!(await chain.bls.verifySignatureSets([signatureSet], {verifyOnMainThread: opts.verifyOnMainThread ?? true}))) {
373
327
  throw new BlockGossipError(GossipAction.REJECT, {
374
328
  code: BlockErrorCode.PROPOSAL_SIGNATURE_INVALID,
375
- blockSlot,
329
+ slot: blockSlot,
330
+ root: blockRoot,
376
331
  });
377
332
  }
378
333