@lodestar/beacon-node 1.47.0 → 1.48.0-dev.02b355c4db

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 (327) 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 +37 -14
  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.map +1 -1
  101. package/lib/chain/produceBlock/produceBlockBody.js +46 -64
  102. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  103. package/lib/chain/regen/interface.d.ts +1 -0
  104. package/lib/chain/regen/interface.d.ts.map +1 -1
  105. package/lib/chain/regen/interface.js +1 -0
  106. package/lib/chain/regen/interface.js.map +1 -1
  107. package/lib/chain/validation/block.d.ts.map +1 -1
  108. package/lib/chain/validation/block.js +74 -63
  109. package/lib/chain/validation/block.js.map +1 -1
  110. package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
  111. package/lib/chain/validation/dataColumnSidecar.js +38 -13
  112. package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
  113. package/lib/chain/validation/executionPayloadBid.d.ts +15 -3
  114. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  115. package/lib/chain/validation/executionPayloadBid.js +199 -28
  116. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  117. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  118. package/lib/chain/validation/executionPayloadEnvelope.js +10 -29
  119. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  120. package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
  121. package/lib/chain/validation/payloadAttestationMessage.js +5 -6
  122. package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
  123. package/lib/chain/validatorMonitor.d.ts +7 -1
  124. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  125. package/lib/chain/validatorMonitor.js +22 -5
  126. package/lib/chain/validatorMonitor.js.map +1 -1
  127. package/lib/db/beacon.d.ts +14 -5
  128. package/lib/db/beacon.d.ts.map +1 -1
  129. package/lib/db/beacon.js +17 -3
  130. package/lib/db/beacon.js.map +1 -1
  131. package/lib/db/dataColumnStore.d.ts +39 -0
  132. package/lib/db/dataColumnStore.d.ts.map +1 -0
  133. package/lib/db/dataColumnStore.js +81 -0
  134. package/lib/db/dataColumnStore.js.map +1 -0
  135. package/lib/db/flatFileStore/atomicWrite.d.ts +8 -0
  136. package/lib/db/flatFileStore/atomicWrite.d.ts.map +1 -0
  137. package/lib/db/flatFileStore/atomicWrite.js +61 -0
  138. package/lib/db/flatFileStore/atomicWrite.js.map +1 -0
  139. package/lib/db/flatFileStore/dcolFormat.d.ts +90 -0
  140. package/lib/db/flatFileStore/dcolFormat.d.ts.map +1 -0
  141. package/lib/db/flatFileStore/dcolFormat.js +286 -0
  142. package/lib/db/flatFileStore/dcolFormat.js.map +1 -0
  143. package/lib/db/flatFileStore/errors.d.ts +82 -0
  144. package/lib/db/flatFileStore/errors.d.ts.map +1 -0
  145. package/lib/db/flatFileStore/errors.js +32 -0
  146. package/lib/db/flatFileStore/errors.js.map +1 -0
  147. package/lib/db/flatFileStore/flatFileStore.d.ts +41 -0
  148. package/lib/db/flatFileStore/flatFileStore.d.ts.map +1 -0
  149. package/lib/db/flatFileStore/flatFileStore.js +251 -0
  150. package/lib/db/flatFileStore/flatFileStore.js.map +1 -0
  151. package/lib/db/flatFileStore/index.d.ts +4 -0
  152. package/lib/db/flatFileStore/index.d.ts.map +1 -0
  153. package/lib/db/flatFileStore/index.js +2 -0
  154. package/lib/db/flatFileStore/index.js.map +1 -0
  155. package/lib/db/flatFileStore/interface.d.ts +25 -0
  156. package/lib/db/flatFileStore/interface.d.ts.map +1 -0
  157. package/lib/db/flatFileStore/interface.js +2 -0
  158. package/lib/db/flatFileStore/interface.js.map +1 -0
  159. package/lib/db/flatFileStore/metrics.d.ts +24 -0
  160. package/lib/db/flatFileStore/metrics.d.ts.map +1 -0
  161. package/lib/db/flatFileStore/metrics.js +25 -0
  162. package/lib/db/flatFileStore/metrics.js.map +1 -0
  163. package/lib/db/flatFileStore/path.d.ts +9 -0
  164. package/lib/db/flatFileStore/path.d.ts.map +1 -0
  165. package/lib/db/flatFileStore/path.js +21 -0
  166. package/lib/db/flatFileStore/path.js.map +1 -0
  167. package/lib/db/flatFileStore/slotIndex.d.ts +14 -0
  168. package/lib/db/flatFileStore/slotIndex.d.ts.map +1 -0
  169. package/lib/db/flatFileStore/slotIndex.js +46 -0
  170. package/lib/db/flatFileStore/slotIndex.js.map +1 -0
  171. package/lib/db/flatFileStore/snappy.d.ts +3 -0
  172. package/lib/db/flatFileStore/snappy.d.ts.map +1 -0
  173. package/lib/db/flatFileStore/snappy.js +12 -0
  174. package/lib/db/flatFileStore/snappy.js.map +1 -0
  175. package/lib/db/index.d.ts +1 -0
  176. package/lib/db/index.d.ts.map +1 -1
  177. package/lib/db/interface.d.ts +8 -1
  178. package/lib/db/interface.d.ts.map +1 -1
  179. package/lib/db/repositories/blockArchive.d.ts +8 -1
  180. package/lib/db/repositories/blockArchive.d.ts.map +1 -1
  181. package/lib/db/repositories/blockArchive.js +65 -28
  182. package/lib/db/repositories/blockArchive.js.map +1 -1
  183. package/lib/db/repositories/blockArchiveIndex.d.ts +1 -2
  184. package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
  185. package/lib/db/repositories/blockArchiveIndex.js +3 -7
  186. package/lib/db/repositories/blockArchiveIndex.js.map +1 -1
  187. package/lib/execution/builder/apiClient.d.ts +6 -0
  188. package/lib/execution/builder/apiClient.d.ts.map +1 -1
  189. package/lib/execution/builder/apiClient.js +19 -1
  190. package/lib/execution/builder/apiClient.js.map +1 -1
  191. package/lib/execution/builder/validateBid.d.ts +1 -0
  192. package/lib/execution/builder/validateBid.d.ts.map +1 -1
  193. package/lib/execution/builder/validateBid.js +17 -6
  194. package/lib/execution/builder/validateBid.js.map +1 -1
  195. package/lib/execution/engine/mock.d.ts.map +1 -1
  196. package/lib/execution/engine/mock.js +4 -1
  197. package/lib/execution/engine/mock.js.map +1 -1
  198. package/lib/metrics/metrics/lodestar.d.ts +32 -4
  199. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  200. package/lib/metrics/metrics/lodestar.js +78 -8
  201. package/lib/metrics/metrics/lodestar.js.map +1 -1
  202. package/lib/monitoring/clientStats.js +1 -1
  203. package/lib/monitoring/clientStats.js.map +1 -1
  204. package/lib/network/gossip/encoding.d.ts.map +1 -1
  205. package/lib/network/gossip/encoding.js +0 -6
  206. package/lib/network/gossip/encoding.js.map +1 -1
  207. package/lib/network/gossip/topic.d.ts +2 -1
  208. package/lib/network/gossip/topic.d.ts.map +1 -1
  209. package/lib/network/gossip/topic.js +4 -20
  210. package/lib/network/gossip/topic.js.map +1 -1
  211. package/lib/network/network.d.ts.map +1 -1
  212. package/lib/network/network.js +7 -6
  213. package/lib/network/network.js.map +1 -1
  214. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  215. package/lib/network/processor/gossipHandlers.js +388 -285
  216. package/lib/network/processor/gossipHandlers.js.map +1 -1
  217. package/lib/network/processor/gossipQueues/indexed.d.ts.map +1 -1
  218. package/lib/network/processor/gossipQueues/indexed.js +0 -1
  219. package/lib/network/processor/gossipQueues/indexed.js.map +1 -1
  220. package/lib/network/processor/index.d.ts +49 -3
  221. package/lib/network/processor/index.d.ts.map +1 -1
  222. package/lib/network/processor/index.js +270 -122
  223. package/lib/network/processor/index.js.map +1 -1
  224. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
  225. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +112 -91
  226. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
  227. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.d.ts.map +1 -1
  228. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +2 -0
  229. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js.map +1 -1
  230. package/lib/network/reqresp/protocols.d.ts.map +1 -1
  231. package/lib/network/reqresp/protocols.js +6 -22
  232. package/lib/network/reqresp/protocols.js.map +1 -1
  233. package/lib/network/reqresp/rateLimit.js +2 -1
  234. package/lib/network/reqresp/rateLimit.js.map +1 -1
  235. package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts +2 -1
  236. package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts.map +1 -1
  237. package/lib/network/reqresp/utils/dataColumnResponseValidation.js +14 -9
  238. package/lib/network/reqresp/utils/dataColumnResponseValidation.js.map +1 -1
  239. package/lib/node/nodejs.d.ts +2 -1
  240. package/lib/node/nodejs.d.ts.map +1 -1
  241. package/lib/node/nodejs.js +4 -2
  242. package/lib/node/nodejs.js.map +1 -1
  243. package/lib/sync/range/chain.d.ts.map +1 -1
  244. package/lib/sync/range/chain.js +9 -2
  245. package/lib/sync/range/chain.js.map +1 -1
  246. package/lib/sync/range/range.d.ts.map +1 -1
  247. package/lib/sync/range/range.js +25 -2
  248. package/lib/sync/range/range.js.map +1 -1
  249. package/lib/util/sszBytes.d.ts +6 -0
  250. package/lib/util/sszBytes.d.ts.map +1 -1
  251. package/lib/util/sszBytes.js +1 -1
  252. package/lib/util/sszBytes.js.map +1 -1
  253. package/package.json +18 -18
  254. package/src/api/impl/beacon/blocks/index.ts +12 -14
  255. package/src/api/impl/beacon/state/utils.ts +15 -0
  256. package/src/api/impl/config/index.ts +4 -1
  257. package/src/api/impl/validator/index.ts +49 -43
  258. package/src/chain/archiveStore/archiveStore.ts +12 -1
  259. package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +1 -0
  260. package/src/chain/archiveStore/historicalState/metrics.ts +14 -1
  261. package/src/chain/archiveStore/historicalState/types.ts +2 -0
  262. package/src/chain/archiveStore/historicalState/worker.ts +4 -1
  263. package/src/chain/archiveStore/utils/archiveBlocks.ts +73 -42
  264. package/src/chain/blocks/importBlock.ts +25 -20
  265. package/src/chain/blocks/index.ts +126 -29
  266. package/src/chain/blocks/types.ts +9 -0
  267. package/src/chain/blocks/utils/chainSegment.ts +26 -12
  268. package/src/chain/blocks/verifyBlock.ts +5 -2
  269. package/src/chain/blocks/writeBlockInputToDb.ts +10 -17
  270. package/src/chain/chain.ts +155 -85
  271. package/src/chain/emitter.ts +1 -1
  272. package/src/chain/errors/blockError.ts +22 -10
  273. package/src/chain/errors/dataColumnSidecarError.ts +24 -8
  274. package/src/chain/errors/executionPayloadBid.ts +8 -0
  275. package/src/chain/errors/executionPayloadEnvelope.ts +14 -11
  276. package/src/chain/errors/gossipValidation.ts +1 -0
  277. package/src/chain/forkChoice/index.ts +2 -0
  278. package/src/chain/interface.ts +6 -6
  279. package/src/chain/lightClient/index.ts +32 -36
  280. package/src/chain/lightClient/proofs.ts +10 -0
  281. package/src/chain/opPools/aggregatedAttestationPool.ts +1 -1
  282. package/src/chain/prepareNextSlot.ts +42 -17
  283. package/src/chain/produceBlock/computeNewStateRoot.ts +3 -38
  284. package/src/chain/produceBlock/produceBlockBody.ts +50 -71
  285. package/src/chain/regen/interface.ts +1 -0
  286. package/src/chain/validation/block.ts +77 -79
  287. package/src/chain/validation/dataColumnSidecar.ts +47 -14
  288. package/src/chain/validation/executionPayloadBid.ts +230 -32
  289. package/src/chain/validation/executionPayloadEnvelope.ts +10 -37
  290. package/src/chain/validation/payloadAttestationMessage.ts +8 -9
  291. package/src/chain/validatorMonitor.ts +24 -7
  292. package/src/db/beacon.ts +33 -6
  293. package/src/db/dataColumnStore.ts +113 -0
  294. package/src/db/flatFileStore/atomicWrite.ts +65 -0
  295. package/src/db/flatFileStore/dcolFormat.ts +389 -0
  296. package/src/db/flatFileStore/errors.ts +53 -0
  297. package/src/db/flatFileStore/flatFileStore.ts +310 -0
  298. package/src/db/flatFileStore/index.ts +3 -0
  299. package/src/db/flatFileStore/interface.ts +21 -0
  300. package/src/db/flatFileStore/metrics.ts +48 -0
  301. package/src/db/flatFileStore/path.ts +32 -0
  302. package/src/db/flatFileStore/slotIndex.ts +56 -0
  303. package/src/db/flatFileStore/snappy.ts +14 -0
  304. package/src/db/index.ts +1 -0
  305. package/src/db/interface.ts +9 -1
  306. package/src/db/repositories/blockArchive.ts +89 -30
  307. package/src/db/repositories/blockArchiveIndex.ts +4 -9
  308. package/src/execution/builder/apiClient.ts +21 -1
  309. package/src/execution/builder/validateBid.ts +26 -7
  310. package/src/execution/engine/mock.ts +4 -1
  311. package/src/metrics/metrics/lodestar.ts +83 -9
  312. package/src/monitoring/clientStats.ts +1 -1
  313. package/src/network/gossip/encoding.ts +0 -6
  314. package/src/network/gossip/topic.ts +3 -25
  315. package/src/network/network.ts +9 -6
  316. package/src/network/processor/gossipHandlers.ts +500 -355
  317. package/src/network/processor/gossipQueues/indexed.ts +0 -1
  318. package/src/network/processor/index.ts +312 -176
  319. package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +139 -105
  320. package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +2 -0
  321. package/src/network/reqresp/protocols.ts +7 -24
  322. package/src/network/reqresp/rateLimit.ts +2 -1
  323. package/src/network/reqresp/utils/dataColumnResponseValidation.ts +15 -7
  324. package/src/node/nodejs.ts +6 -1
  325. package/src/sync/range/chain.ts +9 -2
  326. package/src/sync/range/range.ts +24 -2
  327. package/src/util/sszBytes.ts +1 -1
@@ -5,10 +5,12 @@ export enum ExecutionPayloadBidErrorCode {
5
5
  BUILDER_NOT_ELIGIBLE = "EXECUTION_PAYLOAD_BID_ERROR_BUILDER_NOT_ELIGIBLE",
6
6
  INVALID_BUILDER_VERSION = "EXECUTION_PAYLOAD_BID_ERROR_INVALID_BUILDER_VERSION",
7
7
  NON_ZERO_EXECUTION_PAYMENT = "EXECUTION_PAYLOAD_BID_ERROR_NON_ZERO_EXECUTION_PAYMENT",
8
+ BLOCK_HASH_EQUALS_PARENT_BLOCK_HASH = "EXECUTION_PAYLOAD_BID_ERROR_BLOCK_HASH_EQUALS_PARENT_BLOCK_HASH",
8
9
  INCOMPATIBLE_WITH_HEAD = "EXECUTION_PAYLOAD_BID_ERROR_INCOMPATIBLE_WITH_HEAD",
9
10
  BID_ALREADY_KNOWN = "EXECUTION_PAYLOAD_BID_ERROR_BID_ALREADY_KNOWN",
10
11
  BID_TOO_LOW = "EXECUTION_PAYLOAD_BID_ERROR_BID_TOO_LOW",
11
12
  BID_TOO_HIGH = "EXECUTION_PAYLOAD_BID_ERROR_BID_TOO_HIGH",
13
+ BUILDER_MAY_EXIT = "EXECUTION_PAYLOAD_BID_ERROR_BUILDER_MAY_EXIT",
12
14
  TOO_MANY_KZG_COMMITMENTS = "EXECUTION_PAYLOAD_BID_ERROR_TOO_MANY_KZG_COMMITMENTS",
13
15
  UNKNOWN_BLOCK_ROOT = "EXECUTION_PAYLOAD_BID_ERROR_UNKNOWN_BLOCK_ROOT",
14
16
  UNKNOWN_PARENT_BLOCK_HASH = "EXECUTION_PAYLOAD_BID_ERROR_UNKNOWN_PARENT_BLOCK_HASH",
@@ -50,6 +52,11 @@ export type ExecutionPayloadBidErrorType =
50
52
  }
51
53
  | {code: ExecutionPayloadBidErrorCode.BID_TOO_LOW; bidValue: number; currentHighestBid: number}
52
54
  | {code: ExecutionPayloadBidErrorCode.BID_TOO_HIGH; bidValue: number; builderBalance: number}
55
+ | {
56
+ code: ExecutionPayloadBidErrorCode.BUILDER_MAY_EXIT;
57
+ builderIndex: BuilderIndex;
58
+ parentBlockRoot: RootHex;
59
+ }
53
60
  | {
54
61
  code: ExecutionPayloadBidErrorCode.TOO_MANY_KZG_COMMITMENTS;
55
62
  blobKzgCommitmentsLen: number;
@@ -57,6 +64,7 @@ export type ExecutionPayloadBidErrorType =
57
64
  }
58
65
  | {code: ExecutionPayloadBidErrorCode.UNKNOWN_BLOCK_ROOT; parentBlockRoot: RootHex}
59
66
  | {code: ExecutionPayloadBidErrorCode.UNKNOWN_PARENT_BLOCK_HASH; parentBlockHash: RootHex}
67
+ | {code: ExecutionPayloadBidErrorCode.BLOCK_HASH_EQUALS_PARENT_BLOCK_HASH; blockHash: RootHex}
60
68
  | {code: ExecutionPayloadBidErrorCode.INVALID_SLOT; builderIndex: BuilderIndex; slot: Slot}
61
69
  | {code: ExecutionPayloadBidErrorCode.NOT_LATER_THAN_PARENT; parentSlot: Slot; slot: Slot}
62
70
  | {
@@ -12,8 +12,6 @@ export enum ExecutionPayloadEnvelopeErrorCode {
12
12
  BUILDER_INDEX_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_BUILDER_INDEX_MISMATCH",
13
13
  BLOCK_HASH_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_BLOCK_HASH_MISMATCH",
14
14
  EXECUTION_REQUESTS_ROOT_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_EXECUTION_REQUESTS_ROOT_MISMATCH",
15
- EXECUTION_REQUESTS_COUNT_EXCEEDED = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_EXECUTION_REQUESTS_COUNT_EXCEEDED",
16
- WITHDRAWALS_COUNT_EXCEEDED = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_WITHDRAWALS_COUNT_EXCEEDED",
17
15
  INVALID_SIGNATURE = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_INVALID_SIGNATURE",
18
16
  PAYLOAD_ENVELOPE_INPUT_MISSING = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_PAYLOAD_ENVELOPE_INPUT_MISSING",
19
17
  }
@@ -28,30 +26,35 @@ export type ExecutionPayloadEnvelopeErrorType =
28
26
  slot: Slot;
29
27
  }
30
28
  | {code: ExecutionPayloadEnvelopeErrorCode.INVALID_BLOCK; blockRoot: RootHex}
31
- | {code: ExecutionPayloadEnvelopeErrorCode.SLOT_MISMATCH; envelopeSlot: Slot; blockSlot: Slot}
29
+ | {
30
+ code: ExecutionPayloadEnvelopeErrorCode.SLOT_MISMATCH;
31
+ slot: Slot;
32
+ root: RootHex;
33
+ envelopeSlot: Slot;
34
+ blockSlot: Slot;
35
+ }
32
36
  | {
33
37
  code: ExecutionPayloadEnvelopeErrorCode.BUILDER_INDEX_MISMATCH;
38
+ slot: Slot;
39
+ root: RootHex;
34
40
  envelopeBuilderIndex: BuilderIndex;
35
41
  bidBuilderIndex: BuilderIndex | null;
36
42
  }
37
43
  | {
38
44
  code: ExecutionPayloadEnvelopeErrorCode.BLOCK_HASH_MISMATCH;
45
+ slot: Slot;
46
+ root: RootHex;
39
47
  envelopeBlockHash: RootHex;
40
48
  bidBlockHash: RootHex | null;
41
49
  }
42
50
  | {
43
51
  code: ExecutionPayloadEnvelopeErrorCode.EXECUTION_REQUESTS_ROOT_MISMATCH;
52
+ slot: Slot;
53
+ root: RootHex;
44
54
  envelopeRequestsRoot: RootHex;
45
55
  bidRequestsRoot: RootHex;
46
56
  }
47
- | {
48
- code: ExecutionPayloadEnvelopeErrorCode.EXECUTION_REQUESTS_COUNT_EXCEEDED;
49
- name: string;
50
- count: number;
51
- limit: number;
52
- }
53
- | {code: ExecutionPayloadEnvelopeErrorCode.WITHDRAWALS_COUNT_EXCEEDED; count: number; limit: number}
54
- | {code: ExecutionPayloadEnvelopeErrorCode.INVALID_SIGNATURE}
57
+ | {code: ExecutionPayloadEnvelopeErrorCode.INVALID_SIGNATURE; slot: Slot; root: RootHex}
55
58
  | {code: ExecutionPayloadEnvelopeErrorCode.PAYLOAD_ENVELOPE_INPUT_MISSING; blockRoot: RootHex};
56
59
 
57
60
  export class ExecutionPayloadEnvelopeError extends GossipActionError<ExecutionPayloadEnvelopeErrorType> {}
@@ -8,6 +8,7 @@ export enum GossipAction {
8
8
  export enum GossipErrorCode {
9
9
  INVALID_SERIALIZED_BYTES_ERROR_CODE = "GOSSIP_ERROR_INVALID_SERIALIZED_BYTES",
10
10
  PAST_SLOT = "GOSSIP_ERROR_PAST_SLOT",
11
+ FUTURE_SLOT = "GOSSIP_ERROR_FUTURE_SLOT",
11
12
  }
12
13
 
13
14
  export class GossipActionError<T extends {code: string}> extends LodestarError<T> {
@@ -135,6 +135,7 @@ export function initializeForkChoiceFromFinalizedState(
135
135
  blockRoot: toRootHex(checkpoint.root),
136
136
  timeliness: true, // Optimistically assume is timely
137
137
  ptcTimeliness: true, // Spec: block_timeliness for anchor = [True, True]
138
+ importedTimely: true, // Optimistically assume is timely
138
139
  proposerIndex: blockHeader.proposerIndex,
139
140
 
140
141
  justifiedEpoch: justifiedCheckpoint.epoch,
@@ -233,6 +234,7 @@ export function initializeForkChoiceFromUnfinalizedState(
233
234
  targetRoot: headRoot,
234
235
  timeliness: true, // Optimistically assume is timely
235
236
  ptcTimeliness: true, // Spec: block_timeliness for anchor = [True, True]
237
+ importedTimely: true, // Optimistically assume is timely
236
238
  proposerIndex: blockHeader.proposerIndex,
237
239
 
238
240
  justifiedEpoch: justifiedCheckpoint.epoch,
@@ -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>;
@@ -274,8 +274,8 @@ export interface IBeaconChain {
274
274
 
275
275
  recomputeForkChoiceHead(caller: ForkchoiceCaller): ProtoBlock;
276
276
 
277
- /** When proposerBoostReorg is enabled, this is called at slot n-1 to predict the head block to build on if we are proposing at slot n */
278
- predictProposerHead(slot: Slot): ProtoBlock;
277
+ /** When proposerBoostReorg is enabled, predict (as of the current slot) the head block a proposer would build on next slot */
278
+ predictProposerHead(): ProtoBlock;
279
279
 
280
280
  /** When proposerBoostReorg is enabled and we are proposing a block, this is called to determine which head block to build on */
281
281
  getProposerHead(slot: Slot): ProtoBlock;
@@ -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 =
@@ -45,6 +45,14 @@ const PREPARE_EPOCH_LIMIT = 1;
45
45
  * Expressed in bps so it scales with slot duration (mainnet vs minimal/devnet). */
46
46
  const BUILDER_PREVERIFY_LIMIT_BPS = 2000;
47
47
 
48
+ /**
49
+ * How far before the next slot builder connections are pre-established, see `checkBuilderStatusBeforeSlot`.
50
+ *
51
+ * 1667 = 16.67% of slot (2s on mainnet). Must stay under the few seconds an idle connection survives,
52
+ * while leaving room for a round trip to a distant builder to complete before the slot begins.
53
+ */
54
+ const BUILDER_STATUS_CHECK_BEFORE_SLOT_BPS = 1667;
55
+
48
56
  /**
49
57
  * At Bellatrix, if we are responsible for proposing in next slot, we want to prepare payload
50
58
  * 4s before the start of next slot at PREPARE_NEXT_SLOT_BPS of the current slot.
@@ -157,7 +165,7 @@ export class PrepareNextSlotScheduler {
157
165
  // last-block-of-epoch and build slot 0 on the strong parent (epoch-boundary reorg),
158
166
  // so we should dial the strong parent through the boundary instead of the weak head.
159
167
  if (feeRecipient || isEpochTransition) {
160
- const proposerHead = this.chain.predictProposerHead(clockSlot);
168
+ const proposerHead = this.chain.predictProposerHead();
161
169
  const {slot: proposerHeadSlot, blockRoot: proposerHeadRoot} = proposerHead;
162
170
 
163
171
  // If we predict a reorg, we build the epoch transition on the proposer head (parent) instead
@@ -185,6 +193,7 @@ export class PrepareNextSlotScheduler {
185
193
  if (feeRecipient) {
186
194
  if (isForkPostGloas(fork)) {
187
195
  this.chain.builderCircuitBreaker.update(clockSlot, updatedHead);
196
+ this.checkBuilderStatusBeforeSlot(prepareSlot);
188
197
  } else {
189
198
  // Update the builder status, if enabled shoot an api call to check status
190
199
  this.chain.updateBuilderStatus(clockSlot);
@@ -234,6 +243,22 @@ export class PrepareNextSlotScheduler {
234
243
  parentBlockHash = preparedState.latestExecutionPayloadHeader.blockHash;
235
244
  }
236
245
 
246
+ // If emitPayloadAttributes is true emit a SSE payloadAttributes event for
247
+ // every slot. Without the flag, only emit the event if we are proposing in the next slot.
248
+ if (
249
+ (feeRecipient || this.chain.opts.emitPayloadAttributes === true) &&
250
+ this.chain.emitter.listenerCount(routes.events.EventType.payloadAttributes)
251
+ ) {
252
+ const data = getPayloadAttributesForSSE(fork as ForkPostBellatrix, this.chain, {
253
+ prepareState: stateAfterParentPayload,
254
+ prepareSlot,
255
+ parentBlockRoot: fromHex(updatedHead.blockRoot),
256
+ parentBlockHash,
257
+ feeRecipient: feeRecipient ?? "0x0000000000000000000000000000000000000000",
258
+ });
259
+ this.chain.emitter.emit(routes.events.EventType.payloadAttributes, {data, version: fork});
260
+ }
261
+
237
262
  if (feeRecipient) {
238
263
  const preparationTime =
239
264
  computeTimeAtSlot(this.config, prepareSlot, this.chain.genesisTime) - Date.now() / 1000;
@@ -264,22 +289,6 @@ export class PrepareNextSlotScheduler {
264
289
  }
265
290
 
266
291
  this.computeStateHashTreeRoot(preparedState, isEpochTransition);
267
-
268
- // If emitPayloadAttributes is true emit a SSE payloadAttributes event for
269
- // every slot. Without the flag, only emit the event if we are proposing in the next slot.
270
- if (
271
- (feeRecipient || this.chain.opts.emitPayloadAttributes === true) &&
272
- this.chain.emitter.listenerCount(routes.events.EventType.payloadAttributes)
273
- ) {
274
- const data = getPayloadAttributesForSSE(fork as ForkPostBellatrix, this.chain, {
275
- prepareState: stateAfterParentPayload,
276
- prepareSlot,
277
- parentBlockRoot: fromHex(updatedHead.blockRoot),
278
- parentBlockHash,
279
- feeRecipient: feeRecipient ?? "0x0000000000000000000000000000000000000000",
280
- });
281
- this.chain.emitter.emit(routes.events.EventType.payloadAttributes, {data, version: fork});
282
- }
283
292
  } else {
284
293
  // Pre-bellatrix only reaches here at an epoch transition to precompute the next epoch state
285
294
  const preparedState = await this.chain.regen.getBlockSlotState(
@@ -390,6 +399,22 @@ export class PrepareNextSlotScheduler {
390
399
  }
391
400
  };
392
401
 
402
+ /**
403
+ * Pre-establish the builder connections so the handshake lands outside the bid deadline. Scheduled
404
+ * later in the slot, connecting at PREPARE_NEXT_SLOT_BPS would go cold before bids are requested.
405
+ */
406
+ private checkBuilderStatusBeforeSlot(prepareSlot: Slot): void {
407
+ const msBeforeSlot = this.config.getSlotComponentDurationMs(BUILDER_STATUS_CHECK_BEFORE_SLOT_BPS);
408
+ const msUntilCheck = -this.chain.clock.msFromSlot(prepareSlot) - msBeforeSlot;
409
+ sleep(Math.max(0, msUntilCheck), this.signal)
410
+ .then(() => this.chain.builderApiClient.checkStatus())
411
+ .catch((e) => {
412
+ if (!isErrorAborted(e)) {
413
+ this.logger.debug("Failed to check builder status", {prepareSlot}, e as Error);
414
+ }
415
+ });
416
+ }
417
+
393
418
  computeStateHashTreeRoot(state: IBeaconStateView, isEpochTransition: boolean): void {
394
419
  // cache HashObjects for faster hashTreeRoot() later, especially for computeNewStateRoot() if we need to produce a block at slot 0 of epoch
395
420
  // see https://github.com/ChainSafe/lodestar/issues/6194
@@ -1,11 +1,5 @@
1
- import {
2
- DataAvailabilityStatus,
3
- ExecutionPayloadStatus,
4
- IBeaconStateView,
5
- StateHashTreeRootSource,
6
- } from "@lodestar/state-transition";
1
+ import {EMPTY_SIGNATURE, IBeaconStateView} from "@lodestar/state-transition";
7
2
  import {BeaconBlock, BlindedBeaconBlock, Gwei, Root} from "@lodestar/types";
8
- import {ZERO_HASH} from "../../constants/index.js";
9
3
  import {Metrics} from "../../metrics/index.js";
10
4
 
11
5
  /**
@@ -19,35 +13,6 @@ export function computeNewStateRoot(
19
13
  block: BeaconBlock | BlindedBeaconBlock
20
14
  ): {newStateRoot: Root; proposerReward: Gwei; postState: IBeaconStateView} {
21
15
  // Set signature to zero to re-use stateTransition() function which requires the SignedBeaconBlock type
22
- const blockEmptySig = {message: block, signature: ZERO_HASH};
23
-
24
- const postState = state.stateTransition(
25
- blockEmptySig,
26
- {
27
- // ExecutionPayloadStatus.valid: Assume payload valid, it has been produced by a trusted EL
28
- executionPayloadStatus: ExecutionPayloadStatus.valid,
29
- // DataAvailabilityStatus.available: Assume the blobs to be available, have just been produced by trusted EL
30
- dataAvailabilityStatus: DataAvailabilityStatus.Available,
31
- // verifyStateRoot: false | the root in the block is zero-ed, it's being computed here
32
- verifyStateRoot: false,
33
- // verifyProposer: false | as the block signature is zero-ed
34
- verifyProposer: false,
35
- // verifySignatures: false | since the data to assemble the block is trusted
36
- verifySignatures: false,
37
- // Preserve cache in source state, since the resulting state is not added to the state cache
38
- dontTransferCache: true,
39
- },
40
- {metrics}
41
- );
42
-
43
- const {attestations, syncAggregate, slashing} = postState.proposerRewards;
44
- const proposerReward = BigInt(attestations + syncAggregate + slashing);
45
-
46
- const hashTreeRootTimer = metrics?.stateHashTreeRootTime.startTimer({
47
- source: StateHashTreeRootSource.computeNewStateRoot,
48
- });
49
- const newStateRoot = postState.hashTreeRoot();
50
- hashTreeRootTimer?.();
51
-
52
- return {newStateRoot, proposerReward, postState};
16
+ const signedBlock = {message: block, signature: EMPTY_SIGNATURE};
17
+ return state.computeNewStateRoot({block: signedBlock}, {metrics});
53
18
  }
@@ -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
@@ -899,45 +894,38 @@ function preparePayloadAttributes(
899
894
  ): SSEPayloadAttributes["payloadAttributes"] {
900
895
  const timestamp = computeTimeAtSlot(chain.config, prepareSlot, prepareState.genesisTime);
901
896
  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
- }
897
+ if (!isStatePostCapella(prepareState)) {
898
+ throw new Error("Expected Capella state for withdrawals");
899
+ }
912
900
 
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;
901
+ let withdrawals: capella.Withdrawal[];
902
+ if (isStatePostGloas(prepareState)) {
903
+ const isExtendingPayload = byteArrayEquals(parentBlockHash, prepareState.latestExecutionPayloadBid.blockHash);
904
+ if (isExtendingPayload) {
905
+ // applyParentExecutionPayload sets latestBlockHash = parentBid.blockHash, so a mismatch
906
+ // here means the caller did not apply parent payload to prepareState
907
+ if (!byteArrayEquals(prepareState.latestBlockHash, prepareState.latestExecutionPayloadBid.blockHash)) {
908
+ throw new Error("Expected state with parent execution payload applied for withdrawals");
930
909
  }
910
+ withdrawals = prepareState.getExpectedWithdrawals().expectedWithdrawals;
931
911
  } 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;
912
+ // When the parent block is empty, state.payloadExpectedWithdrawals holds a batch
913
+ // already deducted from CL balances but never credited on the EL (the envelope
914
+ // was not delivered). The next payload must carry those same withdrawals to
915
+ // restore CL/EL consistency, otherwise validators permanently lose that balance.
916
+ withdrawals = prepareState.payloadExpectedWithdrawals;
935
917
  }
918
+ } else {
919
+ withdrawals = prepareState.getExpectedWithdrawals().expectedWithdrawals;
936
920
  }
937
921
 
938
- if (ForkSeq[fork] >= ForkSeq.deneb) {
939
- (payloadAttributes as deneb.SSEPayloadAttributes["payloadAttributes"]).parentBeaconBlockRoot = parentBlockRoot;
940
- }
922
+ const payloadAttributes: deneb.SSEPayloadAttributes["payloadAttributes"] = {
923
+ timestamp,
924
+ prevRandao,
925
+ suggestedFeeRecipient: feeRecipient,
926
+ withdrawals,
927
+ parentBeaconBlockRoot: parentBlockRoot,
928
+ };
941
929
 
942
930
  if (ForkSeq[fork] >= ForkSeq.gloas) {
943
931
  if (!isStatePostGloas(prepareState)) {
@@ -1050,37 +1038,28 @@ export async function produceCommonBlockBody<T extends BlockType>(
1050
1038
  step: BlockProductionStep.attestations,
1051
1039
  });
1052
1040
 
1053
- const blockBody: Omit<CommonBlockBody, "blsToExecutionChanges" | "syncAggregate"> = {
1041
+ const endSyncAggregate = stepsMetrics?.startTimer();
1042
+ const parentBlockRoot = fromHex(parentBlock.blockRoot);
1043
+ const previousSlot = slot - 1;
1044
+ const syncAggregate = this.syncContributionAndProofPool.getAggregate(previousSlot, parentBlockRoot);
1045
+ this.metrics?.production.producedSyncAggregateParticipants.observe(
1046
+ syncAggregate.syncCommitteeBits.getTrueBitIndexes().length
1047
+ );
1048
+ endSyncAggregate?.({
1049
+ step: BlockProductionStep.syncAggregate,
1050
+ });
1051
+
1052
+ // Live proposal production is supported from Fulu onward.
1053
+ return {
1054
1054
  randaoReveal,
1055
1055
  graffiti,
1056
- // Eth1 data voting is no longer required since electra
1057
1056
  eth1Data: currentState.eth1Data,
1058
1057
  proposerSlashings: this.opts.disableProposerSlashings === true ? [] : proposerSlashings,
1059
1058
  attesterSlashings,
1060
1059
  attestations,
1061
- // Since electra, deposits are processed by the execution layer,
1062
- // we no longer support handling deposits from earlier forks.
1063
1060
  deposits: [],
1064
1061
  voluntaryExits,
1062
+ blsToExecutionChanges,
1063
+ syncAggregate,
1065
1064
  };
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
1065
  }
@@ -24,6 +24,7 @@ export enum RegenCaller {
24
24
  validateApiVoluntaryExit = "validateApiVoluntaryExit",
25
25
  publishDeferredVoluntaryExits = "publishDeferredVoluntaryExits",
26
26
  validateGossipExecutionPayloadBid = "validateGossipExecutionPayloadBid",
27
+ validateApiExecutionPayloadBid = "validateApiExecutionPayloadBid",
27
28
  validateGossipPayloadAttestationMessage = "validateGossipPayloadAttestationMessage",
28
29
  validateGossipProposerPreferences = "validateGossipProposerPreferences",
29
30
  onForkChoiceFinalized = "onForkChoiceFinalized",