@lodestar/beacon-node 1.47.0 → 1.48.0-dev.042c96183c

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 (328) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +8 -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 +44 -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 +89 -23
  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/verifyBlock.d.ts.map +1 -1
  48. package/lib/chain/blocks/verifyBlock.js +5 -2
  49. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  50. package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
  51. package/lib/chain/blocks/writeBlockInputToDb.js +9 -16
  52. package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
  53. package/lib/chain/chain.d.ts +12 -6
  54. package/lib/chain/chain.d.ts.map +1 -1
  55. package/lib/chain/chain.js +131 -76
  56. package/lib/chain/chain.js.map +1 -1
  57. package/lib/chain/emitter.d.ts +1 -1
  58. package/lib/chain/emitter.js +1 -1
  59. package/lib/chain/errors/blockError.d.ts +19 -7
  60. package/lib/chain/errors/blockError.d.ts.map +1 -1
  61. package/lib/chain/errors/blockError.js +2 -2
  62. package/lib/chain/errors/blockError.js.map +1 -1
  63. package/lib/chain/errors/dataColumnSidecarError.d.ts +15 -2
  64. package/lib/chain/errors/dataColumnSidecarError.d.ts.map +1 -1
  65. package/lib/chain/errors/dataColumnSidecarError.js.map +1 -1
  66. package/lib/chain/errors/executionPayloadBid.d.ts +9 -0
  67. package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
  68. package/lib/chain/errors/executionPayloadBid.js +2 -0
  69. package/lib/chain/errors/executionPayloadBid.js.map +1 -1
  70. package/lib/chain/errors/executionPayloadEnvelope.d.ts +10 -11
  71. package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
  72. package/lib/chain/errors/executionPayloadEnvelope.js +0 -2
  73. package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
  74. package/lib/chain/errors/gossipValidation.d.ts +2 -1
  75. package/lib/chain/errors/gossipValidation.d.ts.map +1 -1
  76. package/lib/chain/errors/gossipValidation.js +1 -0
  77. package/lib/chain/errors/gossipValidation.js.map +1 -1
  78. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  79. package/lib/chain/forkChoice/index.js +2 -0
  80. package/lib/chain/forkChoice/index.js.map +1 -1
  81. package/lib/chain/interface.d.ts +6 -6
  82. package/lib/chain/interface.d.ts.map +1 -1
  83. package/lib/chain/lightClient/index.d.ts +3 -3
  84. package/lib/chain/lightClient/index.d.ts.map +1 -1
  85. package/lib/chain/lightClient/index.js +21 -23
  86. package/lib/chain/lightClient/index.js.map +1 -1
  87. package/lib/chain/lightClient/proofs.d.ts +2 -1
  88. package/lib/chain/lightClient/proofs.d.ts.map +1 -1
  89. package/lib/chain/lightClient/proofs.js +5 -1
  90. package/lib/chain/lightClient/proofs.js.map +1 -1
  91. package/lib/chain/opPools/aggregatedAttestationPool.js +1 -1
  92. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  93. package/lib/chain/prepareNextSlot.d.ts +5 -0
  94. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  95. package/lib/chain/prepareNextSlot.js +40 -15
  96. package/lib/chain/prepareNextSlot.js.map +1 -1
  97. package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
  98. package/lib/chain/produceBlock/computeNewStateRoot.js +3 -25
  99. package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
  100. package/lib/chain/produceBlock/produceBlockBody.d.ts +4 -2
  101. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  102. package/lib/chain/produceBlock/produceBlockBody.js +57 -72
  103. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  104. package/lib/chain/regen/interface.d.ts +1 -0
  105. package/lib/chain/regen/interface.d.ts.map +1 -1
  106. package/lib/chain/regen/interface.js +1 -0
  107. package/lib/chain/regen/interface.js.map +1 -1
  108. package/lib/chain/validation/block.d.ts.map +1 -1
  109. package/lib/chain/validation/block.js +74 -63
  110. package/lib/chain/validation/block.js.map +1 -1
  111. package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
  112. package/lib/chain/validation/dataColumnSidecar.js +38 -13
  113. package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
  114. package/lib/chain/validation/executionPayloadBid.d.ts +15 -3
  115. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  116. package/lib/chain/validation/executionPayloadBid.js +199 -28
  117. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  118. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  119. package/lib/chain/validation/executionPayloadEnvelope.js +10 -29
  120. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  121. package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
  122. package/lib/chain/validation/payloadAttestationMessage.js +5 -6
  123. package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
  124. package/lib/chain/validatorMonitor.d.ts +7 -1
  125. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  126. package/lib/chain/validatorMonitor.js +22 -5
  127. package/lib/chain/validatorMonitor.js.map +1 -1
  128. package/lib/db/beacon.d.ts +14 -5
  129. package/lib/db/beacon.d.ts.map +1 -1
  130. package/lib/db/beacon.js +17 -3
  131. package/lib/db/beacon.js.map +1 -1
  132. package/lib/db/dataColumnStore.d.ts +39 -0
  133. package/lib/db/dataColumnStore.d.ts.map +1 -0
  134. package/lib/db/dataColumnStore.js +81 -0
  135. package/lib/db/dataColumnStore.js.map +1 -0
  136. package/lib/db/flatFileStore/atomicWrite.d.ts +8 -0
  137. package/lib/db/flatFileStore/atomicWrite.d.ts.map +1 -0
  138. package/lib/db/flatFileStore/atomicWrite.js +61 -0
  139. package/lib/db/flatFileStore/atomicWrite.js.map +1 -0
  140. package/lib/db/flatFileStore/dcolFormat.d.ts +90 -0
  141. package/lib/db/flatFileStore/dcolFormat.d.ts.map +1 -0
  142. package/lib/db/flatFileStore/dcolFormat.js +286 -0
  143. package/lib/db/flatFileStore/dcolFormat.js.map +1 -0
  144. package/lib/db/flatFileStore/errors.d.ts +82 -0
  145. package/lib/db/flatFileStore/errors.d.ts.map +1 -0
  146. package/lib/db/flatFileStore/errors.js +32 -0
  147. package/lib/db/flatFileStore/errors.js.map +1 -0
  148. package/lib/db/flatFileStore/flatFileStore.d.ts +41 -0
  149. package/lib/db/flatFileStore/flatFileStore.d.ts.map +1 -0
  150. package/lib/db/flatFileStore/flatFileStore.js +251 -0
  151. package/lib/db/flatFileStore/flatFileStore.js.map +1 -0
  152. package/lib/db/flatFileStore/index.d.ts +4 -0
  153. package/lib/db/flatFileStore/index.d.ts.map +1 -0
  154. package/lib/db/flatFileStore/index.js +2 -0
  155. package/lib/db/flatFileStore/index.js.map +1 -0
  156. package/lib/db/flatFileStore/interface.d.ts +25 -0
  157. package/lib/db/flatFileStore/interface.d.ts.map +1 -0
  158. package/lib/db/flatFileStore/interface.js +2 -0
  159. package/lib/db/flatFileStore/interface.js.map +1 -0
  160. package/lib/db/flatFileStore/metrics.d.ts +24 -0
  161. package/lib/db/flatFileStore/metrics.d.ts.map +1 -0
  162. package/lib/db/flatFileStore/metrics.js +25 -0
  163. package/lib/db/flatFileStore/metrics.js.map +1 -0
  164. package/lib/db/flatFileStore/path.d.ts +9 -0
  165. package/lib/db/flatFileStore/path.d.ts.map +1 -0
  166. package/lib/db/flatFileStore/path.js +21 -0
  167. package/lib/db/flatFileStore/path.js.map +1 -0
  168. package/lib/db/flatFileStore/slotIndex.d.ts +14 -0
  169. package/lib/db/flatFileStore/slotIndex.d.ts.map +1 -0
  170. package/lib/db/flatFileStore/slotIndex.js +46 -0
  171. package/lib/db/flatFileStore/slotIndex.js.map +1 -0
  172. package/lib/db/flatFileStore/snappy.d.ts +3 -0
  173. package/lib/db/flatFileStore/snappy.d.ts.map +1 -0
  174. package/lib/db/flatFileStore/snappy.js +12 -0
  175. package/lib/db/flatFileStore/snappy.js.map +1 -0
  176. package/lib/db/index.d.ts +1 -0
  177. package/lib/db/index.d.ts.map +1 -1
  178. package/lib/db/interface.d.ts +8 -1
  179. package/lib/db/interface.d.ts.map +1 -1
  180. package/lib/db/repositories/blockArchive.d.ts +8 -1
  181. package/lib/db/repositories/blockArchive.d.ts.map +1 -1
  182. package/lib/db/repositories/blockArchive.js +65 -28
  183. package/lib/db/repositories/blockArchive.js.map +1 -1
  184. package/lib/db/repositories/blockArchiveIndex.d.ts +1 -2
  185. package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
  186. package/lib/db/repositories/blockArchiveIndex.js +3 -7
  187. package/lib/db/repositories/blockArchiveIndex.js.map +1 -1
  188. package/lib/execution/builder/apiClient.d.ts +6 -0
  189. package/lib/execution/builder/apiClient.d.ts.map +1 -1
  190. package/lib/execution/builder/apiClient.js +19 -1
  191. package/lib/execution/builder/apiClient.js.map +1 -1
  192. package/lib/execution/builder/validateBid.d.ts +1 -0
  193. package/lib/execution/builder/validateBid.d.ts.map +1 -1
  194. package/lib/execution/builder/validateBid.js +17 -6
  195. package/lib/execution/builder/validateBid.js.map +1 -1
  196. package/lib/execution/engine/mock.d.ts.map +1 -1
  197. package/lib/execution/engine/mock.js +4 -1
  198. package/lib/execution/engine/mock.js.map +1 -1
  199. package/lib/metrics/metrics/lodestar.d.ts +32 -4
  200. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  201. package/lib/metrics/metrics/lodestar.js +78 -8
  202. package/lib/metrics/metrics/lodestar.js.map +1 -1
  203. package/lib/monitoring/clientStats.js +1 -1
  204. package/lib/monitoring/clientStats.js.map +1 -1
  205. package/lib/network/gossip/encoding.d.ts.map +1 -1
  206. package/lib/network/gossip/encoding.js +0 -7
  207. package/lib/network/gossip/encoding.js.map +1 -1
  208. package/lib/network/gossip/topic.d.ts +2 -1
  209. package/lib/network/gossip/topic.d.ts.map +1 -1
  210. package/lib/network/gossip/topic.js +4 -20
  211. package/lib/network/gossip/topic.js.map +1 -1
  212. package/lib/network/network.d.ts.map +1 -1
  213. package/lib/network/network.js +7 -6
  214. package/lib/network/network.js.map +1 -1
  215. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  216. package/lib/network/processor/gossipHandlers.js +388 -285
  217. package/lib/network/processor/gossipHandlers.js.map +1 -1
  218. package/lib/network/processor/gossipQueues/indexed.d.ts.map +1 -1
  219. package/lib/network/processor/gossipQueues/indexed.js +0 -1
  220. package/lib/network/processor/gossipQueues/indexed.js.map +1 -1
  221. package/lib/network/processor/index.d.ts +49 -3
  222. package/lib/network/processor/index.d.ts.map +1 -1
  223. package/lib/network/processor/index.js +270 -122
  224. package/lib/network/processor/index.js.map +1 -1
  225. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
  226. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +112 -91
  227. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
  228. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.d.ts.map +1 -1
  229. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +2 -0
  230. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js.map +1 -1
  231. package/lib/network/reqresp/protocols.d.ts.map +1 -1
  232. package/lib/network/reqresp/protocols.js +6 -22
  233. package/lib/network/reqresp/protocols.js.map +1 -1
  234. package/lib/network/reqresp/rateLimit.js +2 -1
  235. package/lib/network/reqresp/rateLimit.js.map +1 -1
  236. package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts +2 -1
  237. package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts.map +1 -1
  238. package/lib/network/reqresp/utils/dataColumnResponseValidation.js +14 -9
  239. package/lib/network/reqresp/utils/dataColumnResponseValidation.js.map +1 -1
  240. package/lib/node/nodejs.d.ts +2 -1
  241. package/lib/node/nodejs.d.ts.map +1 -1
  242. package/lib/node/nodejs.js +4 -2
  243. package/lib/node/nodejs.js.map +1 -1
  244. package/lib/sync/range/chain.d.ts.map +1 -1
  245. package/lib/sync/range/chain.js +9 -2
  246. package/lib/sync/range/chain.js.map +1 -1
  247. package/lib/sync/range/range.d.ts.map +1 -1
  248. package/lib/sync/range/range.js +25 -2
  249. package/lib/sync/range/range.js.map +1 -1
  250. package/lib/util/sszBytes.d.ts +6 -0
  251. package/lib/util/sszBytes.d.ts.map +1 -1
  252. package/lib/util/sszBytes.js +1 -1
  253. package/lib/util/sszBytes.js.map +1 -1
  254. package/package.json +19 -20
  255. package/src/api/impl/beacon/blocks/index.ts +12 -14
  256. package/src/api/impl/beacon/state/utils.ts +15 -0
  257. package/src/api/impl/config/index.ts +4 -1
  258. package/src/api/impl/validator/index.ts +49 -43
  259. package/src/chain/archiveStore/archiveStore.ts +12 -1
  260. package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +1 -0
  261. package/src/chain/archiveStore/historicalState/metrics.ts +14 -1
  262. package/src/chain/archiveStore/historicalState/types.ts +2 -0
  263. package/src/chain/archiveStore/historicalState/worker.ts +4 -1
  264. package/src/chain/archiveStore/utils/archiveBlocks.ts +73 -42
  265. package/src/chain/blocks/importBlock.ts +25 -20
  266. package/src/chain/blocks/index.ts +126 -29
  267. package/src/chain/blocks/types.ts +9 -0
  268. package/src/chain/blocks/utils/chainSegment.ts +26 -12
  269. package/src/chain/blocks/verifyBlock.ts +5 -2
  270. package/src/chain/blocks/writeBlockInputToDb.ts +10 -17
  271. package/src/chain/chain.ts +155 -85
  272. package/src/chain/emitter.ts +1 -1
  273. package/src/chain/errors/blockError.ts +22 -10
  274. package/src/chain/errors/dataColumnSidecarError.ts +24 -8
  275. package/src/chain/errors/executionPayloadBid.ts +8 -0
  276. package/src/chain/errors/executionPayloadEnvelope.ts +14 -11
  277. package/src/chain/errors/gossipValidation.ts +1 -0
  278. package/src/chain/forkChoice/index.ts +2 -0
  279. package/src/chain/interface.ts +6 -6
  280. package/src/chain/lightClient/index.ts +32 -36
  281. package/src/chain/lightClient/proofs.ts +10 -0
  282. package/src/chain/opPools/aggregatedAttestationPool.ts +1 -1
  283. package/src/chain/prepareNextSlot.ts +47 -18
  284. package/src/chain/produceBlock/computeNewStateRoot.ts +3 -38
  285. package/src/chain/produceBlock/produceBlockBody.ts +62 -79
  286. package/src/chain/regen/interface.ts +1 -0
  287. package/src/chain/validation/block.ts +77 -79
  288. package/src/chain/validation/dataColumnSidecar.ts +47 -14
  289. package/src/chain/validation/executionPayloadBid.ts +230 -32
  290. package/src/chain/validation/executionPayloadEnvelope.ts +10 -37
  291. package/src/chain/validation/payloadAttestationMessage.ts +8 -9
  292. package/src/chain/validatorMonitor.ts +24 -7
  293. package/src/db/beacon.ts +33 -6
  294. package/src/db/dataColumnStore.ts +113 -0
  295. package/src/db/flatFileStore/atomicWrite.ts +65 -0
  296. package/src/db/flatFileStore/dcolFormat.ts +389 -0
  297. package/src/db/flatFileStore/errors.ts +53 -0
  298. package/src/db/flatFileStore/flatFileStore.ts +310 -0
  299. package/src/db/flatFileStore/index.ts +3 -0
  300. package/src/db/flatFileStore/interface.ts +21 -0
  301. package/src/db/flatFileStore/metrics.ts +48 -0
  302. package/src/db/flatFileStore/path.ts +32 -0
  303. package/src/db/flatFileStore/slotIndex.ts +56 -0
  304. package/src/db/flatFileStore/snappy.ts +14 -0
  305. package/src/db/index.ts +1 -0
  306. package/src/db/interface.ts +9 -1
  307. package/src/db/repositories/blockArchive.ts +89 -30
  308. package/src/db/repositories/blockArchiveIndex.ts +4 -9
  309. package/src/execution/builder/apiClient.ts +21 -1
  310. package/src/execution/builder/validateBid.ts +26 -7
  311. package/src/execution/engine/mock.ts +4 -1
  312. package/src/metrics/metrics/lodestar.ts +83 -9
  313. package/src/monitoring/clientStats.ts +1 -1
  314. package/src/network/gossip/encoding.ts +0 -7
  315. package/src/network/gossip/topic.ts +3 -25
  316. package/src/network/network.ts +9 -6
  317. package/src/network/processor/gossipHandlers.ts +500 -355
  318. package/src/network/processor/gossipQueues/indexed.ts +0 -1
  319. package/src/network/processor/index.ts +312 -176
  320. package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +139 -105
  321. package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +2 -0
  322. package/src/network/reqresp/protocols.ts +7 -24
  323. package/src/network/reqresp/rateLimit.ts +2 -1
  324. package/src/network/reqresp/utils/dataColumnResponseValidation.ts +15 -7
  325. package/src/node/nodejs.ts +6 -1
  326. package/src/sync/range/chain.ts +9 -2
  327. package/src/sync/range/range.ts +24 -2
  328. package/src/util/sszBytes.ts +1 -1
@@ -132,12 +132,15 @@ export async function verifyBlocksInEpoch(
132
132
  }> =
133
133
  fork >= ForkSeq.gloas
134
134
  ? (async () => {
135
- // Validate DA for ALL payloads in the Map, not just those paired with blockInputs.
135
+ // Range sync creates a PayloadEnvelopeInput for every Gloas block, but an entry without
136
+ // an envelope represents a valid EMPTY slot and has no payload DA to verify.
136
137
  // A checkpoint-sync batch may include a payload for a slot whose block was filtered
137
138
  // out of relevantBlocks (e.g., the anchor at the finalized slot); that payload still
138
139
  // needs DA validation so it can be imported in processBlocks.
139
140
  const payloadInputsForDa: PayloadEnvelopeInput[] =
140
- payloadEnvelopes !== null ? Array.from(payloadEnvelopes.values()) : [];
141
+ payloadEnvelopes !== null
142
+ ? Array.from(payloadEnvelopes.values()).filter((payloadInput) => payloadInput.hasPayloadEnvelope())
143
+ : [];
141
144
  const {dataAvailabilityStatuses, availableTime} = await verifyPayloadsDataAvailability(
142
145
  payloadInputsForDa,
143
146
  abortController.signal
@@ -1,6 +1,6 @@
1
- import {ForkPostDeneb, isForkPostDeneb} from "@lodestar/params";
1
+ import {ForkPostDeneb, ForkPostFulu, isForkPostDeneb} from "@lodestar/params";
2
2
  import {SignedBeaconBlock} from "@lodestar/types";
3
- import {fromHex, toRootHex} from "@lodestar/utils";
3
+ import {toRootHex} from "@lodestar/utils";
4
4
  import {getBlobKzgCommitments} from "../../util/dataColumns.js";
5
5
  import {BeaconChain} from "../chain.js";
6
6
  import {IBlockInput, IDataColumnsInput, isBlockInputBlobs, isBlockInputColumns} from "./blockInput/index.js";
@@ -76,7 +76,6 @@ async function writeBlockAndBlobsToDb(this: BeaconChain, blockInput: IBlockInput
76
76
  */
77
77
  export async function writeDataColumnsToDb(this: BeaconChain, blockInput: IDataColumnsInput): Promise<void> {
78
78
  const {slot, blockRootHex} = blockInput;
79
- const blockRoot = fromHex(blockRootHex);
80
79
 
81
80
  if (!blockInput.hasComputedAllData()) {
82
81
  // Supernodes may only have a subset of the data columns by the time the block begins to be imported
@@ -89,25 +88,19 @@ export async function writeDataColumnsToDb(this: BeaconChain, blockInput: IDataC
89
88
 
90
89
  const {custodyColumns} = this.custodyConfig;
91
90
  const dataColumnSidecars = blockInput.getCustodyColumns();
91
+ const dataColumnSidecarType = this.config.getForkTypes<ForkPostFulu>(slot).DataColumnSidecar;
92
92
 
93
- const binaryPuts: {key: number; value: Uint8Array}[] = [];
94
- const nonbinaryPuts = [];
93
+ const binaryColumns: {index: number; data: Uint8Array}[] = [];
95
94
  for (const dataColumnSidecar of dataColumnSidecars) {
96
- // skip reserializing column if we already have it
97
95
  const serialized = this.serializedCache.get(dataColumnSidecar);
98
- if (serialized) {
99
- binaryPuts.push({key: dataColumnSidecar.index, value: serialized});
100
- } else {
101
- nonbinaryPuts.push(dataColumnSidecar);
102
- }
96
+ binaryColumns.push({
97
+ index: dataColumnSidecar.index,
98
+ data: serialized ?? dataColumnSidecarType.serialize(dataColumnSidecar),
99
+ });
103
100
  }
101
+ await this.db.dataColumns.putManyBinary({slot, blockRoot: blockRootHex}, binaryColumns);
104
102
 
105
- await Promise.all([
106
- this.db.dataColumnSidecar.putManyBinary(blockRoot, binaryPuts),
107
- this.db.dataColumnSidecar.putMany(blockRoot, nonbinaryPuts),
108
- ]);
109
-
110
- this.logger.debug("Persisted dataColumnSidecars to hot DB", {
103
+ this.logger.debug("Persisted dataColumnSidecars", {
111
104
  slot,
112
105
  root: blockRootHex,
113
106
  dataColumnSidecars: dataColumnSidecars.length,
@@ -82,7 +82,7 @@ import {IBlockInput, isBlockInputBlobs, isBlockInputColumns} from "./blocks/bloc
82
82
  import {BlockProcessor, ImportBlockOpts} from "./blocks/index.js";
83
83
  import {PayloadEnvelopeInputSource} from "./blocks/payloadEnvelopeInput/index.js";
84
84
  import {PayloadEnvelopeProcessor} from "./blocks/payloadEnvelopeProcessor.js";
85
- import {ImportPayloadOpts} from "./blocks/types.js";
85
+ import {ImportPayloadOpts, ProcessBlocksResult} from "./blocks/types.js";
86
86
  import {persistBlockInput} from "./blocks/writeBlockInputToDb.js";
87
87
  import {persistPayloadEnvelopeInput} from "./blocks/writePayloadEnvelopeInputToDb.js";
88
88
  import {BlsMultiThreadWorkerPool, BlsSingleThreadVerifier, IBlsVerifier} from "./bls/index.js";
@@ -268,6 +268,7 @@ export class BeaconChain implements IBeaconChain {
268
268
  db,
269
269
  dbName,
270
270
  dataDir,
271
+ dataColumnDir,
271
272
  logger,
272
273
  processShutdownCallback,
273
274
  clock,
@@ -285,6 +286,7 @@ export class BeaconChain implements IBeaconChain {
285
286
  db: IBeaconDb;
286
287
  dbName: string;
287
288
  dataDir: string;
289
+ dataColumnDir?: string;
288
290
  logger: Logger;
289
291
  processShutdownCallback: ProcessShutdownCallback;
290
292
  /** Used for testing to supply fake clock */
@@ -505,7 +507,12 @@ export class BeaconChain implements IBeaconChain {
505
507
 
506
508
  this.archiveStore = new ArchiveStore(
507
509
  {db, chain: this, logger: logger as LoggerNode, metrics},
508
- {...opts, dbName, anchorState: {finalizedCheckpoint: anchorState.finalizedCheckpoint}},
510
+ {
511
+ ...opts,
512
+ dbName,
513
+ dataColumnDir: dataColumnDir ?? path.join(dataDir, "data_columns"),
514
+ anchorState: {finalizedCheckpoint: anchorState.finalizedCheckpoint},
515
+ },
509
516
  signal
510
517
  );
511
518
 
@@ -969,12 +976,15 @@ export class BeaconChain implements IBeaconChain {
969
976
 
970
977
  async getDataColumnSidecars(blockSlot: Slot, blockRootHex: string): Promise<DataColumnSidecar[]> {
971
978
  const fork = this.config.getForkName(blockSlot);
979
+ const sidecarsByIndex = new Map<number, DataColumnSidecar>();
972
980
 
973
981
  if (isForkPostGloas(fork)) {
974
982
  // After gloas, columns are tracked in PayloadEnvelopeInput
975
983
  const payloadInput = this.seenPayloadEnvelopeInputCache.get(blockRootHex);
976
984
  if (payloadInput) {
977
- return payloadInput.getAllColumns();
985
+ for (const sidecar of payloadInput.getAllColumns()) {
986
+ sidecarsByIndex.set(sidecar.index, sidecar);
987
+ }
978
988
  }
979
989
  } else {
980
990
  // Before gloas, columns are tracked in BlockInput
@@ -983,16 +993,17 @@ export class BeaconChain implements IBeaconChain {
983
993
  if (!isBlockInputColumns(blockInput)) {
984
994
  throw new Error(`Expected block input to have columns: slot=${blockSlot} root=${blockRootHex}`);
985
995
  }
986
- return blockInput.getAllColumns();
996
+ for (const sidecar of blockInput.getAllColumns()) {
997
+ sidecarsByIndex.set(sidecar.index, sidecar);
998
+ }
987
999
  }
988
1000
  }
989
1001
 
990
- const sidecarsUnfinalized = await this.db.dataColumnSidecar.values(fromHex(blockRootHex));
991
- if (sidecarsUnfinalized.length > 0) {
992
- return sidecarsUnfinalized;
1002
+ for (const sidecar of await this.db.dataColumns.getAll({slot: blockSlot, blockRoot: blockRootHex})) {
1003
+ if (!sidecarsByIndex.has(sidecar.index)) sidecarsByIndex.set(sidecar.index, sidecar);
993
1004
  }
994
- const sidecarsFinalized = await this.db.dataColumnSidecarArchive.values(blockSlot);
995
- return sidecarsFinalized;
1005
+
1006
+ return [...sidecarsByIndex.values()].sort((a, b) => a.index - b.index);
996
1007
  }
997
1008
 
998
1009
  async getSerializedDataColumnSidecars(
@@ -1001,22 +1012,25 @@ export class BeaconChain implements IBeaconChain {
1001
1012
  indices: number[]
1002
1013
  ): Promise<(Uint8Array | undefined)[]> {
1003
1014
  const fork = this.config.getForkName(blockSlot);
1015
+ const dataColumnSidecars: (Uint8Array | undefined)[] = indices.map(() => undefined);
1004
1016
 
1005
1017
  if (isForkPostGloas(fork)) {
1006
1018
  // After gloas, columns are tracked in PayloadEnvelopeInput
1007
1019
  const payloadInput = this.seenPayloadEnvelopeInputCache.get(blockRootHex);
1008
1020
  if (payloadInput) {
1009
- return indices.map((index) => {
1021
+ for (let i = 0; i < indices.length; i++) {
1022
+ const index = indices[i];
1010
1023
  const sidecar = payloadInput.getColumn(index);
1011
1024
  if (!sidecar) {
1012
- return undefined;
1025
+ continue;
1013
1026
  }
1014
1027
  const serialized = this.serializedCache.get(sidecar);
1015
1028
  if (serialized) {
1016
- return serialized;
1029
+ dataColumnSidecars[i] = serialized;
1030
+ } else {
1031
+ dataColumnSidecars[i] = sszTypesFor(fork as ForkPostGloas).DataColumnSidecar.serialize(sidecar);
1017
1032
  }
1018
- return sszTypesFor(fork as ForkPostGloas).DataColumnSidecar.serialize(sidecar);
1019
- });
1033
+ }
1020
1034
  }
1021
1035
  } else {
1022
1036
  // Before gloas, columns are tracked in BlockInput
@@ -1025,26 +1039,42 @@ export class BeaconChain implements IBeaconChain {
1025
1039
  if (!isBlockInputColumns(blockInput)) {
1026
1040
  throw new Error(`Expected block input to have columns: slot=${blockSlot} root=${blockRootHex}`);
1027
1041
  }
1028
- return indices.map((index) => {
1042
+ for (let i = 0; i < indices.length; i++) {
1043
+ const index = indices[i];
1029
1044
  const sidecar = blockInput.getColumn(index);
1030
1045
  if (!sidecar) {
1031
- return undefined;
1046
+ continue;
1032
1047
  }
1033
1048
  const serialized = this.serializedCache.get(sidecar);
1034
1049
  if (serialized) {
1035
- return serialized;
1050
+ dataColumnSidecars[i] = serialized;
1051
+ } else {
1052
+ dataColumnSidecars[i] = sszTypesFor(blockInput.forkName as ForkPostFulu).DataColumnSidecar.serialize(
1053
+ sidecar
1054
+ );
1036
1055
  }
1037
- return sszTypesFor(blockInput.forkName as ForkPostFulu).DataColumnSidecar.serialize(sidecar);
1038
- });
1056
+ }
1039
1057
  }
1040
1058
  }
1041
1059
 
1042
- const sidecarsUnfinalized = await this.db.dataColumnSidecar.getManyBinary(fromHex(blockRootHex), indices);
1043
- if (sidecarsUnfinalized.some((sidecar) => sidecar != null)) {
1044
- return sidecarsUnfinalized;
1060
+ const missingPositions = dataColumnSidecars
1061
+ .map((sidecar, position) => (sidecar === undefined ? position : -1))
1062
+ .filter((position) => position !== -1);
1063
+
1064
+ if (missingPositions.length > 0) {
1065
+ const persistedSidecars = await this.db.dataColumns.getManyBinary(
1066
+ {slot: blockSlot, blockRoot: blockRootHex},
1067
+ missingPositions.map((position) => indices[position])
1068
+ );
1069
+ for (let i = 0; i < missingPositions.length; i++) {
1070
+ const sidecar = persistedSidecars[i];
1071
+ if (sidecar !== undefined) {
1072
+ dataColumnSidecars[missingPositions[i]] = sidecar;
1073
+ }
1074
+ }
1045
1075
  }
1046
- const sidecarsFinalized = await this.db.dataColumnSidecarArchive.getManyBinary(blockSlot, indices);
1047
- return sidecarsFinalized;
1076
+
1077
+ return dataColumnSidecars;
1048
1078
  }
1049
1079
 
1050
1080
  async produceCommonBlockBody(blockAttributes: BlockAttributes): Promise<CommonBlockBody> {
@@ -1167,15 +1197,15 @@ export class BeaconChain implements IBeaconChain {
1167
1197
  }
1168
1198
 
1169
1199
  async processBlock(block: IBlockInput, opts?: ImportBlockOpts): Promise<void> {
1170
- return this.blockProcessor.processBlocksJob([block], null, opts);
1200
+ await this.blockProcessor.processBlocksJob([block], null, opts);
1171
1201
  }
1172
1202
 
1173
1203
  async processChainSegment(
1174
1204
  blocks: IBlockInput[],
1175
1205
  payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
1176
1206
  opts?: ImportBlockOpts
1177
- ): Promise<void> {
1178
- await this.blockProcessor.processBlocksJob(blocks, payloadEnvelopes, opts);
1207
+ ): Promise<ProcessBlocksResult> {
1208
+ return this.blockProcessor.processBlocksJob(blocks, payloadEnvelopes, opts);
1179
1209
  }
1180
1210
 
1181
1211
  async processExecutionPayload(payloadInput: PayloadEnvelopeInput, opts?: ImportPayloadOpts): Promise<void> {
@@ -1271,65 +1301,72 @@ export class BeaconChain implements IBeaconChain {
1271
1301
  try {
1272
1302
  const prevHead = this.forkChoice.getHead();
1273
1303
  const head = this.forkChoice.updateAndGetHead({mode: UpdateHeadOpt.GetCanonicalHead}).head;
1304
+ this.emitHeadEvents(prevHead, head);
1305
+ return head;
1306
+ } catch (e) {
1307
+ this.metrics?.forkChoice.errors.inc({entrypoint: UpdateHeadOpt.GetCanonicalHead});
1308
+ throw e;
1309
+ } finally {
1310
+ timer?.();
1311
+ }
1312
+ }
1274
1313
 
1275
- const headRootChanged = head.blockRoot !== prevHead.blockRoot;
1276
-
1277
- if (!headRootChanged && prevHead.payloadStatus === head.payloadStatus) {
1278
- return head;
1279
- }
1314
+ /**
1315
+ * Emit `head` and `head_v2` when the fork choice head differs between two observations. Every caller that
1316
+ * can move the head, `updateAndGetHead()` and `updateTime()`, must capture the head before and pass both.
1317
+ */
1318
+ private emitHeadEvents(prevHead: ProtoBlock, head: ProtoBlock): void {
1319
+ const headRootChanged = head.blockRoot !== prevHead.blockRoot;
1280
1320
 
1281
- try {
1282
- const previousDutyDependentRoot = this.forkChoice.getDependentRoot(head, EpochDifference.previous);
1283
- const currentDutyDependentRoot = this.forkChoice.getDependentRoot(head, EpochDifference.current);
1284
- const epochTransition = computeStartSlotAtEpoch(computeEpochAtSlot(head.slot)) === head.slot;
1285
- const executionOptimistic = isOptimisticBlock(head);
1286
-
1287
- if (headRootChanged) {
1288
- this.emitter.emit(routes.events.EventType.head, {
1289
- block: head.blockRoot,
1290
- epochTransition,
1291
- slot: head.slot,
1292
- state: head.stateRoot,
1293
- previousDutyDependentRoot,
1294
- currentDutyDependentRoot,
1295
- executionOptimistic,
1296
- });
1297
- }
1321
+ if (!headRootChanged && prevHead.payloadStatus === head.payloadStatus) {
1322
+ return;
1323
+ }
1298
1324
 
1299
- this.emitter.emit(routes.events.EventType.headV2, {
1300
- version: this.config.getForkName(head.slot),
1301
- data: {
1302
- slot: head.slot,
1303
- block: head.blockRoot,
1304
- state: head.stateRoot,
1305
- payloadStatus: head.payloadStatus === PayloadStatus.FULL ? "full" : "empty",
1306
- epochTransition,
1307
- currentEpochDependentRoot: previousDutyDependentRoot,
1308
- nextEpochDependentRoot: currentDutyDependentRoot,
1309
- executionOptimistic,
1310
- },
1325
+ try {
1326
+ const previousDutyDependentRoot = this.forkChoice.getDependentRoot(head, EpochDifference.previous);
1327
+ const currentDutyDependentRoot = this.forkChoice.getDependentRoot(head, EpochDifference.current);
1328
+ const epochTransition = computeStartSlotAtEpoch(computeEpochAtSlot(head.slot)) === head.slot;
1329
+ const executionOptimistic = isOptimisticBlock(head);
1330
+
1331
+ if (headRootChanged) {
1332
+ this.emitter.emit(routes.events.EventType.head, {
1333
+ block: head.blockRoot,
1334
+ epochTransition,
1335
+ slot: head.slot,
1336
+ state: head.stateRoot,
1337
+ previousDutyDependentRoot,
1338
+ currentDutyDependentRoot,
1339
+ executionOptimistic,
1311
1340
  });
1312
- } catch (e) {
1313
- // getDependentRoot() may fail with error: "No block for root" as we can see in holesky non-finality issue
1314
- this.logger.debug(
1315
- "Error emitting head/head_v2 event",
1316
- {slot: head.slot, root: head.blockRoot, headRootChanged},
1317
- e as Error
1318
- );
1319
1341
  }
1320
1342
 
1321
- return head;
1343
+ this.emitter.emit(routes.events.EventType.headV2, {
1344
+ version: this.config.getForkName(head.slot),
1345
+ data: {
1346
+ slot: head.slot,
1347
+ block: head.blockRoot,
1348
+ state: head.stateRoot,
1349
+ payloadStatus: head.payloadStatus === PayloadStatus.FULL ? "full" : "empty",
1350
+ epochTransition,
1351
+ currentEpochDependentRoot: previousDutyDependentRoot,
1352
+ nextEpochDependentRoot: currentDutyDependentRoot,
1353
+ executionOptimistic,
1354
+ },
1355
+ });
1322
1356
  } catch (e) {
1323
- this.metrics?.forkChoice.errors.inc({entrypoint: UpdateHeadOpt.GetCanonicalHead});
1324
- throw e;
1325
- } finally {
1326
- timer?.();
1357
+ // getDependentRoot() may fail with error: "No block for root" as we can see in holesky non-finality issue
1358
+ this.logger.debug(
1359
+ "Error emitting head/head_v2 event",
1360
+ {slot: head.slot, root: head.blockRoot, headRootChanged},
1361
+ e as Error
1362
+ );
1327
1363
  }
1328
1364
  }
1329
1365
 
1330
- predictProposerHead(slot: Slot): ProtoBlock {
1366
+ predictProposerHead(): ProtoBlock {
1331
1367
  this.metrics?.forkChoice.requests.inc();
1332
1368
  const timer = this.metrics?.forkChoice.findHead.startTimer({caller: FindHeadFnName.predictProposerHead});
1369
+ const slot = this.clock.currentSlot;
1333
1370
  const secFromSlot = this.clock.secFromSlot(slot);
1334
1371
 
1335
1372
  try {
@@ -1380,10 +1417,15 @@ export class BeaconChain implements IBeaconChain {
1380
1417
  const slot = data.slot;
1381
1418
  if (isBlindedBeaconBlock(data)) {
1382
1419
  const sszType = this.config.getPostBellatrixForkTypes(slot).BlindedBeaconBlock;
1383
- void this.persistSszObject("BlindedBeaconBlock", sszType.serialize(data), sszType.hashTreeRoot(data), suffix);
1420
+ void this.persistSszObject(
1421
+ "BlindedBeaconBlock",
1422
+ sszType.serialize(data),
1423
+ toRootHex(sszType.hashTreeRoot(data)),
1424
+ suffix
1425
+ );
1384
1426
  } else {
1385
1427
  const sszType = this.config.getForkTypes(slot).BeaconBlock;
1386
- void this.persistSszObject("BeaconBlock", sszType.serialize(data), sszType.hashTreeRoot(data), suffix);
1428
+ void this.persistSszObject("BeaconBlock", sszType.serialize(data), toRootHex(sszType.hashTreeRoot(data)), suffix);
1387
1429
  }
1388
1430
  }
1389
1431
 
@@ -1404,33 +1446,39 @@ export class BeaconChain implements IBeaconChain {
1404
1446
  this.persistSszObject(
1405
1447
  `SignedBeaconBlock_slot_${blockSlot}`,
1406
1448
  blockType.serialize(block),
1407
- blockType.hashTreeRoot(block),
1449
+ toRootHex(this.config.getForkTypes(blockSlot).BeaconBlock.hashTreeRoot(block.message)),
1408
1450
  `${logStr}_block`
1409
1451
  ),
1410
1452
  this.persistSszObject(
1411
1453
  `preState_slot_${preState.slot}_BeaconState`,
1412
1454
  preState.serialize(),
1413
- preState.hashTreeRoot(),
1455
+ toRootHex(preState.hashTreeRoot()),
1414
1456
  `${logStr}_pre_state`
1415
1457
  ),
1416
1458
  this.persistSszObject(
1417
1459
  `postState_slot_${postState.slot}_BeaconState`,
1418
1460
  postState.serialize(),
1419
- postState.hashTreeRoot(),
1461
+ toRootHex(postStateRoot),
1420
1462
  `${logStr}_post_state`
1421
1463
  ),
1422
1464
  ]);
1423
1465
  }
1424
1466
 
1425
- persistInvalidSszValue<T>(type: Type<T>, sszObject: T, suffix?: string): void {
1467
+ persistInvalidSszValue<T>(type: Type<T>, sszObject: T, suffix?: string, rootHex?: RootHex): void {
1426
1468
  if (this.opts.persistInvalidSszObjects) {
1427
- void this.persistSszObject(type.typeName, type.serialize(sszObject), type.hashTreeRoot(sszObject), suffix);
1469
+ void this.persistSszObject(
1470
+ type.typeName,
1471
+ type.serialize(sszObject),
1472
+ // in SignedBeaconBlock case, we want to use BeaconBlock root instead
1473
+ rootHex ?? toRootHex(type.hashTreeRoot(sszObject)),
1474
+ suffix
1475
+ );
1428
1476
  }
1429
1477
  }
1430
1478
 
1431
- persistInvalidSszBytes(typeName: string, sszBytes: Uint8Array, suffix?: string): void {
1479
+ persistInvalidSszBytes(typeName: string, sszBytes: Uint8Array, rootHex: RootHex, suffix?: string): void {
1432
1480
  if (this.opts.persistInvalidSszObjects) {
1433
- void this.persistSszObject(typeName, sszBytes, sszBytes, suffix);
1481
+ void this.persistSszObject(typeName, sszBytes, rootHex, suffix);
1434
1482
  }
1435
1483
  }
1436
1484
 
@@ -1561,14 +1609,14 @@ export class BeaconChain implements IBeaconChain {
1561
1609
  return {state: blockState, stateId: "block_state_any_epoch", shouldWarn: true};
1562
1610
  }
1563
1611
 
1564
- private async persistSszObject(prefix: string, bytes: Uint8Array, root: Uint8Array, logStr?: string): Promise<void> {
1612
+ private async persistSszObject(prefix: string, bytes: Uint8Array, rootHex: RootHex, logStr?: string): Promise<void> {
1565
1613
  const now = new Date();
1566
1614
  // yyyy-MM-dd
1567
1615
  const dateStr = now.toISOString().split("T")[0];
1568
1616
 
1569
1617
  // by default store to lodestar_archive of current dir
1570
1618
  const dirpath = path.join(this.opts.persistInvalidSszObjectsDir ?? "invalid_ssz_objects", dateStr);
1571
- const filepath = path.join(dirpath, `${prefix}_${toRootHex(root)}.ssz`);
1619
+ const filepath = path.join(dirpath, `${prefix}_${rootHex}.ssz`);
1572
1620
 
1573
1621
  await ensureDir(dirpath);
1574
1622
 
@@ -1611,7 +1659,10 @@ export class BeaconChain implements IBeaconChain {
1611
1659
  this.processShutdownCallback(this.forkChoice.irrecoverableError);
1612
1660
  }
1613
1661
 
1662
+ // updateTime() recomputes the head on epoch-boundary checkpoint pull-up and under fast confirmation
1663
+ const prevHead = this.forkChoice.getHead();
1614
1664
  this.forkChoice.updateTime(slot);
1665
+ this.emitHeadEvents(prevHead, this.forkChoice.getHead());
1615
1666
  this.metrics?.clockSlot.set(slot);
1616
1667
 
1617
1668
  this.attestationPool.prune(slot);
@@ -1669,6 +1720,25 @@ export class BeaconChain implements IBeaconChain {
1669
1720
 
1670
1721
  private async onForkChoiceFinalized(this: BeaconChain, cp: CheckpointWithHex): Promise<void> {
1671
1722
  this.logger.verbose("Fork choice finalized", {epoch: cp.epoch, root: cp.rootHex});
1723
+ this.metrics?.finalizedEpoch.set(cp.epoch);
1724
+ const finalizedBlock = this.forkChoice.getBlockHexDefaultStatus(cp.rootHex);
1725
+ if (finalizedBlock) {
1726
+ // The callback runs synchronously inside fork choice checkpoint updates, defer writing to subscribers
1727
+ callInNextEventLoop(() => {
1728
+ this.emitter.emit(routes.events.EventType.finalizedCheckpoint, {
1729
+ block: cp.rootHex,
1730
+ epoch: cp.epoch,
1731
+ state: finalizedBlock.stateRoot,
1732
+ executionOptimistic: isOptimisticBlock(finalizedBlock),
1733
+ });
1734
+ });
1735
+ } else {
1736
+ this.logger.debug("Finalized block not found in fork choice, skip finalized_checkpoint event", {
1737
+ epoch: cp.epoch,
1738
+ root: cp.rootHex,
1739
+ });
1740
+ }
1741
+
1672
1742
  const finalizedSlot = computeStartSlotAtEpoch(cp.epoch);
1673
1743
  this.seenBlockProposers.prune(finalizedSlot);
1674
1744
 
@@ -33,7 +33,7 @@ export enum ChainEvent {
33
33
  /**
34
34
  * This event signals that the fork choice store has been updated.
35
35
  *
36
- * This event is guaranteed to be triggered whenever the fork choice justified checkpoint is updated. This is in response to a newly processed block.
36
+ * This event is guaranteed to be triggered whenever the fork choice finalized checkpoint is updated. This is either in response to a newly processed block or a new clock tick.
37
37
  */
38
38
  forkChoiceFinalized = "forkChoice:finalized",
39
39
  /**
@@ -78,8 +78,8 @@ export enum BlockErrorCode {
78
78
  TOO_MANY_KZG_COMMITMENTS = "BLOCK_ERROR_TOO_MANY_KZG_COMMITMENTS",
79
79
  /** Bid parent block root does not match block parent root */
80
80
  BID_PARENT_ROOT_MISMATCH = "BLOCK_ERROR_BID_PARENT_ROOT_MISMATCH",
81
- /** A block body operation or parent execution request list exceeds its per-block limit */
82
- TOO_MANY_BLOCK_OPERATIONS = "BLOCK_ERROR_TOO_MANY_BLOCK_OPERATIONS",
81
+ /** A block contains deposits where none are allowed */
82
+ NON_ZERO_DEPOSITS = "BLOCK_ERROR_NON_ZERO_DEPOSITS",
83
83
  /** The parent block's execution payload has been verified as invalid */
84
84
  PARENT_EXECUTION_INVALID = "BLOCK_ERROR_PARENT_EXECUTION_INVALID",
85
85
  /**
@@ -120,9 +120,9 @@ export type BlockErrorType =
120
120
  | {code: BlockErrorCode.ALREADY_KNOWN; root: RootHex}
121
121
  | {code: BlockErrorCode.REPEAT_PROPOSAL; proposerIndex: ValidatorIndex; root: RootHex}
122
122
  | {code: BlockErrorCode.BLOCK_SLOT_LIMIT_REACHED}
123
- | {code: BlockErrorCode.INCORRECT_PROPOSER; proposerIndex: ValidatorIndex}
124
- | {code: BlockErrorCode.PROPOSAL_SIGNATURE_INVALID; blockSlot: Slot}
125
- | {code: BlockErrorCode.UNKNOWN_PROPOSER; proposerIndex: ValidatorIndex}
123
+ | {code: BlockErrorCode.INCORRECT_PROPOSER; slot: Slot; root: RootHex; proposerIndex: ValidatorIndex}
124
+ | {code: BlockErrorCode.PROPOSAL_SIGNATURE_INVALID; slot: Slot; root: RootHex}
125
+ | {code: BlockErrorCode.UNKNOWN_PROPOSER; slot: Slot; root: RootHex; proposerIndex: ValidatorIndex}
126
126
  | {code: BlockErrorCode.INVALID_SIGNATURE; state: IBeaconStateView}
127
127
  | {
128
128
  code: BlockErrorCode.INVALID_STATE_ROOT;
@@ -132,7 +132,7 @@ export type BlockErrorType =
132
132
  postState: IBeaconStateView;
133
133
  }
134
134
  | {code: BlockErrorCode.NOT_FINALIZED_DESCENDANT; parentRoot: RootHex}
135
- | {code: BlockErrorCode.NOT_LATER_THAN_PARENT; parentSlot: Slot; slot: Slot}
135
+ | {code: BlockErrorCode.NOT_LATER_THAN_PARENT; slot: Slot; root: RootHex; parentSlot: Slot}
136
136
  | {code: BlockErrorCode.NON_LINEAR_PARENT_ROOTS}
137
137
  | {code: BlockErrorCode.NON_LINEAR_SLOTS}
138
138
  | {code: BlockErrorCode.ENVELOPE_BLOCK_ROOT_MISMATCH; envelopeBlockRoot: RootHex; blockRoot: RootHex}
@@ -140,7 +140,7 @@ export type BlockErrorType =
140
140
  | {code: BlockErrorCode.BEACON_CHAIN_ERROR; error: Error}
141
141
  | {code: BlockErrorCode.KNOWN_BAD_BLOCK}
142
142
  | {code: BlockErrorCode.BLACKLISTED_BLOCK}
143
- | {code: BlockErrorCode.INCORRECT_TIMESTAMP; timestamp: number; expectedTimestamp: number}
143
+ | {code: BlockErrorCode.INCORRECT_TIMESTAMP; slot: Slot; root: RootHex; timestamp: number; expectedTimestamp: number}
144
144
  | {code: BlockErrorCode.TOO_MUCH_GAS_USED; gasUsed: number; gasLimit: number}
145
145
  | {code: BlockErrorCode.SAME_PARENT_HASH; blockHash: RootHex}
146
146
  | {code: BlockErrorCode.TRANSACTIONS_TOO_BIG; size: number; max: number}
@@ -151,9 +151,21 @@ export type BlockErrorType =
151
151
  errorMessage: string;
152
152
  }
153
153
  | {code: BlockErrorCode.DATA_UNAVAILABLE}
154
- | {code: BlockErrorCode.TOO_MANY_KZG_COMMITMENTS; blobKzgCommitmentsLen: number; commitmentLimit: number}
155
- | {code: BlockErrorCode.BID_PARENT_ROOT_MISMATCH; bidParentRoot: RootHex; blockParentRoot: RootHex}
156
- | {code: BlockErrorCode.TOO_MANY_BLOCK_OPERATIONS; name: string; count: number; limit: number}
154
+ | {
155
+ code: BlockErrorCode.TOO_MANY_KZG_COMMITMENTS;
156
+ slot: Slot;
157
+ root: RootHex;
158
+ blobKzgCommitmentsLen: number;
159
+ commitmentLimit: number;
160
+ }
161
+ | {
162
+ code: BlockErrorCode.BID_PARENT_ROOT_MISMATCH;
163
+ slot: Slot;
164
+ root: RootHex;
165
+ bidParentRoot: RootHex;
166
+ blockParentRoot: RootHex;
167
+ }
168
+ | {code: BlockErrorCode.NON_ZERO_DEPOSITS; slot: Slot; root: RootHex; count: number}
157
169
  | {code: BlockErrorCode.PARENT_EXECUTION_INVALID; parentRoot: RootHex}
158
170
  | {code: BlockErrorCode.PARENT_PAYLOAD_UNKNOWN; parentRoot: RootHex; parentBlockHash: RootHex}
159
171
  | {code: BlockErrorCode.NON_LINEAR_PAYLOAD_ROOTS; parentBlockHash: RootHex; expectedBlockHash: RootHex};
@@ -47,10 +47,12 @@ export enum DataColumnSidecarErrorCode {
47
47
  }
48
48
 
49
49
  export type DataColumnSidecarErrorType =
50
- | {code: DataColumnSidecarErrorCode.INVALID_INDEX; slot: Slot; columnIndex: number}
51
- | {code: DataColumnSidecarErrorCode.NO_COMMITMENTS; slot: Slot; columnIndex: number}
50
+ | {code: DataColumnSidecarErrorCode.INVALID_INDEX; slot: Slot; root: RootHex; columnIndex: number}
51
+ | {code: DataColumnSidecarErrorCode.NO_COMMITMENTS; slot: Slot; root: RootHex; columnIndex: number}
52
52
  | {
53
53
  code: DataColumnSidecarErrorCode.MISMATCHED_LENGTHS;
54
+ slot: Slot;
55
+ root: RootHex;
54
56
  columnLength: number;
55
57
  commitmentsLength: number;
56
58
  proofsLength: number;
@@ -61,10 +63,17 @@ export type DataColumnSidecarErrorType =
61
63
  columnIndex: number;
62
64
  fork: ForkName;
63
65
  }
64
- | {code: DataColumnSidecarErrorCode.INVALID_SUBNET; columnIndex: number; gossipSubnet: SubnetID}
66
+ | {
67
+ code: DataColumnSidecarErrorCode.INVALID_SUBNET;
68
+ slot: Slot;
69
+ root: RootHex;
70
+ columnIndex: number;
71
+ gossipSubnet: SubnetID;
72
+ }
65
73
  | {
66
74
  code: DataColumnSidecarErrorCode.TOO_MANY_KZG_COMMITMENTS;
67
75
  slot: number;
76
+ root: RootHex;
68
77
  columnIndex: number;
69
78
  count: number;
70
79
  limit: number;
@@ -85,12 +94,12 @@ export type DataColumnSidecarErrorType =
85
94
  | {
86
95
  code: DataColumnSidecarErrorCode.PROPOSAL_SIGNATURE_INVALID;
87
96
  slot: Slot;
88
- blockRoot: RootHex;
97
+ root: RootHex;
89
98
  index: number;
90
99
  }
91
- | {code: DataColumnSidecarErrorCode.NOT_LATER_THAN_PARENT; parentSlot: Slot; slot: Slot}
92
- | {code: DataColumnSidecarErrorCode.INCLUSION_PROOF_INVALID; slot: Slot; columnIndex: number}
93
- | {code: DataColumnSidecarErrorCode.INVALID_KZG_PROOF; slot: Slot; columnIndex: number}
100
+ | {code: DataColumnSidecarErrorCode.NOT_LATER_THAN_PARENT; slot: Slot; root: RootHex; parentSlot: Slot}
101
+ | {code: DataColumnSidecarErrorCode.INCLUSION_PROOF_INVALID; slot: Slot; root: RootHex; columnIndex: number}
102
+ | {code: DataColumnSidecarErrorCode.INVALID_KZG_PROOF; slot: Slot; root: RootHex; columnIndex: number}
94
103
  | {code: DataColumnSidecarErrorCode.INCORRECT_SIDECAR_COUNT; slot: number; expected: number; actual: number}
95
104
  | {
96
105
  code: DataColumnSidecarErrorCode.INCORRECT_BLOCK;
@@ -106,6 +115,7 @@ export type DataColumnSidecarErrorType =
106
115
  }
107
116
  | {
108
117
  code: DataColumnSidecarErrorCode.INCORRECT_SIDECAR_SLOT;
118
+ root: RootHex;
109
119
  columnIndex: number;
110
120
  expected: Slot;
111
121
  actual: Slot;
@@ -127,7 +137,13 @@ export type DataColumnSidecarErrorType =
127
137
  actual: number;
128
138
  }
129
139
  | {code: DataColumnSidecarErrorCode.INVALID_KZG_PROOF_BATCH; slot: number; reason: string}
130
- | {code: DataColumnSidecarErrorCode.INCORRECT_PROPOSER; actualProposerIndex: number; expectedProposerIndex: number}
140
+ | {
141
+ code: DataColumnSidecarErrorCode.INCORRECT_PROPOSER;
142
+ slot: Slot;
143
+ root: RootHex;
144
+ actualProposerIndex: number;
145
+ expectedProposerIndex: number;
146
+ }
131
147
  | {code: DataColumnSidecarErrorCode.PAYLOAD_ENVELOPE_INPUT_MISSING; slot: Slot; blockRoot: RootHex};
132
148
 
133
149
  export class DataColumnSidecarGossipError extends GossipActionError<DataColumnSidecarErrorType> {}