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

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 (372) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +14 -2
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/beacon/pool/index.js +1 -1
  5. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  6. package/lib/api/impl/beacon/state/index.d.ts.map +1 -1
  7. package/lib/api/impl/beacon/state/index.js +27 -32
  8. package/lib/api/impl/beacon/state/index.js.map +1 -1
  9. package/lib/api/impl/beacon/state/utils.d.ts +4 -4
  10. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  11. package/lib/api/impl/beacon/state/utils.js +7 -10
  12. package/lib/api/impl/beacon/state/utils.js.map +1 -1
  13. package/lib/api/impl/lodestar/index.d.ts.map +1 -1
  14. package/lib/api/impl/lodestar/index.js +4 -6
  15. package/lib/api/impl/lodestar/index.js.map +1 -1
  16. package/lib/api/impl/proof/index.d.ts.map +1 -1
  17. package/lib/api/impl/proof/index.js +2 -6
  18. package/lib/api/impl/proof/index.js.map +1 -1
  19. package/lib/api/impl/validator/index.d.ts.map +1 -1
  20. package/lib/api/impl/validator/index.js +27 -27
  21. package/lib/api/impl/validator/index.js.map +1 -1
  22. package/lib/api/impl/validator/utils.d.ts +2 -2
  23. package/lib/api/impl/validator/utils.d.ts.map +1 -1
  24. package/lib/api/impl/validator/utils.js +3 -3
  25. package/lib/api/impl/validator/utils.js.map +1 -1
  26. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  27. package/lib/chain/archiveStore/archiveStore.js +1 -0
  28. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  29. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts +3 -7
  30. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
  31. package/lib/chain/archiveStore/historicalState/getHistoricalState.js +8 -26
  32. package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
  33. package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts +2 -2
  34. package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts.map +1 -1
  35. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -0
  36. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
  37. package/lib/chain/archiveStore/historicalState/types.d.ts +2 -0
  38. package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
  39. package/lib/chain/archiveStore/historicalState/types.js.map +1 -1
  40. package/lib/chain/archiveStore/historicalState/worker.js +1 -3
  41. package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
  42. package/lib/chain/archiveStore/interface.d.ts +1 -0
  43. package/lib/chain/archiveStore/interface.d.ts.map +1 -1
  44. package/lib/chain/balancesCache.d.ts +2 -2
  45. package/lib/chain/balancesCache.d.ts.map +1 -1
  46. package/lib/chain/balancesCache.js +4 -4
  47. package/lib/chain/balancesCache.js.map +1 -1
  48. package/lib/chain/blocks/blockInput/types.d.ts +1 -0
  49. package/lib/chain/blocks/blockInput/types.d.ts.map +1 -1
  50. package/lib/chain/blocks/blockInput/types.js +1 -0
  51. package/lib/chain/blocks/blockInput/types.js.map +1 -1
  52. package/lib/chain/blocks/importBlock.d.ts +3 -3
  53. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  54. package/lib/chain/blocks/importBlock.js +21 -21
  55. package/lib/chain/blocks/importBlock.js.map +1 -1
  56. package/lib/chain/blocks/importExecutionPayload.d.ts +10 -8
  57. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  58. package/lib/chain/blocks/importExecutionPayload.js +78 -51
  59. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  60. package/lib/chain/blocks/index.d.ts.map +1 -1
  61. package/lib/chain/blocks/index.js +3 -2
  62. package/lib/chain/blocks/index.js.map +1 -1
  63. package/lib/chain/blocks/types.d.ts +21 -15
  64. package/lib/chain/blocks/types.d.ts.map +1 -1
  65. package/lib/chain/blocks/types.js.map +1 -1
  66. package/lib/chain/blocks/utils/checkpoint.d.ts +2 -2
  67. package/lib/chain/blocks/utils/checkpoint.d.ts.map +1 -1
  68. package/lib/chain/blocks/utils/checkpoint.js.map +1 -1
  69. package/lib/chain/blocks/verifyBlock.d.ts +2 -2
  70. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  71. package/lib/chain/blocks/verifyBlock.js +4 -4
  72. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  73. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +5 -5
  74. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  75. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +4 -4
  76. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  77. package/lib/chain/blocks/verifyBlocksSignatures.d.ts +2 -2
  78. package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
  79. package/lib/chain/blocks/verifyBlocksSignatures.js +1 -1
  80. package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
  81. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts +3 -3
  82. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts.map +1 -1
  83. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js +3 -3
  84. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js.map +1 -1
  85. package/lib/chain/chain.d.ts +12 -12
  86. package/lib/chain/chain.d.ts.map +1 -1
  87. package/lib/chain/chain.js +47 -39
  88. package/lib/chain/chain.js.map +1 -1
  89. package/lib/chain/emitter.d.ts +2 -2
  90. package/lib/chain/emitter.d.ts.map +1 -1
  91. package/lib/chain/errors/blockError.d.ts +4 -4
  92. package/lib/chain/errors/blockError.d.ts.map +1 -1
  93. package/lib/chain/forkChoice/index.d.ts +4 -4
  94. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  95. package/lib/chain/forkChoice/index.js +27 -23
  96. package/lib/chain/forkChoice/index.js.map +1 -1
  97. package/lib/chain/initState.d.ts +2 -2
  98. package/lib/chain/initState.d.ts.map +1 -1
  99. package/lib/chain/initState.js +1 -1
  100. package/lib/chain/initState.js.map +1 -1
  101. package/lib/chain/interface.d.ts +11 -12
  102. package/lib/chain/interface.d.ts.map +1 -1
  103. package/lib/chain/lightClient/index.d.ts +2 -2
  104. package/lib/chain/lightClient/index.d.ts.map +1 -1
  105. package/lib/chain/lightClient/index.js +4 -4
  106. package/lib/chain/lightClient/index.js.map +1 -1
  107. package/lib/chain/opPools/aggregatedAttestationPool.d.ts +6 -6
  108. package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
  109. package/lib/chain/opPools/aggregatedAttestationPool.js +10 -13
  110. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  111. package/lib/chain/opPools/opPool.d.ts +3 -3
  112. package/lib/chain/opPools/opPool.d.ts.map +1 -1
  113. package/lib/chain/opPools/opPool.js +7 -7
  114. package/lib/chain/opPools/opPool.js.map +1 -1
  115. package/lib/chain/opPools/utils.d.ts +2 -2
  116. package/lib/chain/opPools/utils.d.ts.map +1 -1
  117. package/lib/chain/opPools/utils.js +1 -1
  118. package/lib/chain/opPools/utils.js.map +1 -1
  119. package/lib/chain/options.d.ts +1 -0
  120. package/lib/chain/options.d.ts.map +1 -1
  121. package/lib/chain/options.js +1 -0
  122. package/lib/chain/options.js.map +1 -1
  123. package/lib/chain/prepareNextSlot.d.ts +2 -2
  124. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  125. package/lib/chain/prepareNextSlot.js +3 -3
  126. package/lib/chain/prepareNextSlot.js.map +1 -1
  127. package/lib/chain/produceBlock/computeNewStateRoot.d.ts +4 -4
  128. package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
  129. package/lib/chain/produceBlock/computeNewStateRoot.js +3 -4
  130. package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
  131. package/lib/chain/produceBlock/produceBlockBody.d.ts +5 -5
  132. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  133. package/lib/chain/produceBlock/produceBlockBody.js +12 -16
  134. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  135. package/lib/chain/regen/interface.d.ts +13 -13
  136. package/lib/chain/regen/interface.d.ts.map +1 -1
  137. package/lib/chain/regen/queued.d.ts +14 -14
  138. package/lib/chain/regen/queued.d.ts.map +1 -1
  139. package/lib/chain/regen/queued.js.map +1 -1
  140. package/lib/chain/regen/regen.d.ts +6 -5
  141. package/lib/chain/regen/regen.d.ts.map +1 -1
  142. package/lib/chain/regen/regen.js +6 -6
  143. package/lib/chain/regen/regen.js.map +1 -1
  144. package/lib/chain/serializeState.d.ts +2 -2
  145. package/lib/chain/serializeState.d.ts.map +1 -1
  146. package/lib/chain/serializeState.js +1 -1
  147. package/lib/chain/serializeState.js.map +1 -1
  148. package/lib/chain/shufflingCache.d.ts +2 -2
  149. package/lib/chain/shufflingCache.d.ts.map +1 -1
  150. package/lib/chain/shufflingCache.js +3 -4
  151. package/lib/chain/shufflingCache.js.map +1 -1
  152. package/lib/chain/stateCache/fifoBlockStateCache.d.ts +6 -6
  153. package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
  154. package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
  155. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +11 -11
  156. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  157. package/lib/chain/stateCache/persistentCheckpointsCache.js +12 -16
  158. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  159. package/lib/chain/stateCache/types.d.ts +14 -14
  160. package/lib/chain/stateCache/types.d.ts.map +1 -1
  161. package/lib/chain/stateCache/types.js.map +1 -1
  162. package/lib/chain/validation/attesterSlashing.js +3 -3
  163. package/lib/chain/validation/attesterSlashing.js.map +1 -1
  164. package/lib/chain/validation/blobSidecar.js +1 -1
  165. package/lib/chain/validation/blobSidecar.js.map +1 -1
  166. package/lib/chain/validation/block.d.ts.map +1 -1
  167. package/lib/chain/validation/block.js +3 -3
  168. package/lib/chain/validation/block.js.map +1 -1
  169. package/lib/chain/validation/blsToExecutionChange.js +2 -2
  170. package/lib/chain/validation/blsToExecutionChange.js.map +1 -1
  171. package/lib/chain/validation/dataColumnSidecar.js +1 -1
  172. package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
  173. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  174. package/lib/chain/validation/executionPayloadBid.js +4 -4
  175. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  176. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  177. package/lib/chain/validation/executionPayloadEnvelope.js +2 -3
  178. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  179. package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
  180. package/lib/chain/validation/payloadAttestationMessage.js +1 -2
  181. package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
  182. package/lib/chain/validation/proposerSlashing.js +1 -1
  183. package/lib/chain/validation/proposerSlashing.js.map +1 -1
  184. package/lib/chain/validation/signatureSets/contributionAndProof.d.ts +2 -2
  185. package/lib/chain/validation/signatureSets/contributionAndProof.d.ts.map +1 -1
  186. package/lib/chain/validation/signatureSets/contributionAndProof.js +1 -1
  187. package/lib/chain/validation/signatureSets/contributionAndProof.js.map +1 -1
  188. package/lib/chain/validation/signatureSets/syncCommittee.d.ts +2 -2
  189. package/lib/chain/validation/signatureSets/syncCommittee.d.ts.map +1 -1
  190. package/lib/chain/validation/signatureSets/syncCommittee.js +1 -1
  191. package/lib/chain/validation/signatureSets/syncCommittee.js.map +1 -1
  192. package/lib/chain/validation/signatureSets/syncCommitteeContribution.d.ts +2 -2
  193. package/lib/chain/validation/signatureSets/syncCommitteeContribution.d.ts.map +1 -1
  194. package/lib/chain/validation/signatureSets/syncCommitteeContribution.js.map +1 -1
  195. package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.d.ts +2 -2
  196. package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.d.ts.map +1 -1
  197. package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.js +1 -1
  198. package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.js.map +1 -1
  199. package/lib/chain/validation/syncCommittee.d.ts +4 -4
  200. package/lib/chain/validation/syncCommittee.d.ts.map +1 -1
  201. package/lib/chain/validation/syncCommittee.js +13 -12
  202. package/lib/chain/validation/syncCommittee.js.map +1 -1
  203. package/lib/chain/validation/syncCommitteeContributionAndProof.d.ts.map +1 -1
  204. package/lib/chain/validation/syncCommitteeContributionAndProof.js +1 -1
  205. package/lib/chain/validation/syncCommitteeContributionAndProof.js.map +1 -1
  206. package/lib/chain/validation/voluntaryExit.d.ts.map +1 -1
  207. package/lib/chain/validation/voluntaryExit.js +3 -3
  208. package/lib/chain/validation/voluntaryExit.js.map +1 -1
  209. package/lib/chain/validatorMonitor.d.ts +3 -3
  210. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  211. package/lib/chain/validatorMonitor.js +9 -7
  212. package/lib/chain/validatorMonitor.js.map +1 -1
  213. package/lib/metrics/metrics/lodestar.d.ts +12 -4
  214. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  215. package/lib/metrics/metrics/lodestar.js +19 -15
  216. package/lib/metrics/metrics/lodestar.js.map +1 -1
  217. package/lib/network/gossip/encoding.d.ts.map +1 -1
  218. package/lib/network/gossip/encoding.js +15 -0
  219. package/lib/network/gossip/encoding.js.map +1 -1
  220. package/lib/network/gossip/topic.d.ts +2 -729
  221. package/lib/network/gossip/topic.d.ts.map +1 -1
  222. package/lib/network/interface.d.ts +4 -2
  223. package/lib/network/interface.d.ts.map +1 -1
  224. package/lib/network/libp2p/index.d.ts.map +1 -1
  225. package/lib/network/libp2p/index.js +5 -0
  226. package/lib/network/libp2p/index.js.map +1 -1
  227. package/lib/network/network.d.ts +4 -2
  228. package/lib/network/network.d.ts.map +1 -1
  229. package/lib/network/network.js +9 -3
  230. package/lib/network/network.js.map +1 -1
  231. package/lib/network/processor/extractSlotRootFns.d.ts +1 -1
  232. package/lib/network/processor/extractSlotRootFns.js +1 -1
  233. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  234. package/lib/network/processor/gossipHandlers.js +24 -15
  235. package/lib/network/processor/gossipHandlers.js.map +1 -1
  236. package/lib/network/processor/index.d.ts +12 -7
  237. package/lib/network/processor/index.d.ts.map +1 -1
  238. package/lib/network/processor/index.js +99 -78
  239. package/lib/network/processor/index.js.map +1 -1
  240. package/lib/network/reqresp/ReqRespBeaconNode.d.ts.map +1 -1
  241. package/lib/network/reqresp/ReqRespBeaconNode.js +9 -0
  242. package/lib/network/reqresp/ReqRespBeaconNode.js.map +1 -1
  243. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts +8 -0
  244. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -0
  245. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +69 -0
  246. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -0
  247. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.d.ts +6 -0
  248. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.d.ts.map +1 -0
  249. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js +28 -0
  250. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js.map +1 -0
  251. package/lib/network/reqresp/handlers/index.d.ts.map +1 -1
  252. package/lib/network/reqresp/handlers/index.js +11 -1
  253. package/lib/network/reqresp/handlers/index.js.map +1 -1
  254. package/lib/network/reqresp/protocols.d.ts +2 -0
  255. package/lib/network/reqresp/protocols.d.ts.map +1 -1
  256. package/lib/network/reqresp/protocols.js +10 -0
  257. package/lib/network/reqresp/protocols.js.map +1 -1
  258. package/lib/network/reqresp/rateLimit.d.ts.map +1 -1
  259. package/lib/network/reqresp/rateLimit.js +8 -0
  260. package/lib/network/reqresp/rateLimit.js.map +1 -1
  261. package/lib/network/reqresp/score.d.ts.map +1 -1
  262. package/lib/network/reqresp/score.js +2 -0
  263. package/lib/network/reqresp/score.js.map +1 -1
  264. package/lib/network/reqresp/types.d.ts +8 -2
  265. package/lib/network/reqresp/types.d.ts.map +1 -1
  266. package/lib/network/reqresp/types.js +7 -1
  267. package/lib/network/reqresp/types.js.map +1 -1
  268. package/lib/node/nodejs.d.ts +2 -2
  269. package/lib/node/nodejs.d.ts.map +1 -1
  270. package/lib/node/nodejs.js +1 -4
  271. package/lib/node/nodejs.js.map +1 -1
  272. package/lib/node/notifier.d.ts.map +1 -1
  273. package/lib/node/notifier.js +3 -3
  274. package/lib/node/notifier.js.map +1 -1
  275. package/lib/sync/backfill/backfill.d.ts +2 -2
  276. package/lib/sync/backfill/backfill.d.ts.map +1 -1
  277. package/lib/sync/backfill/backfill.js +2 -2
  278. package/lib/sync/backfill/backfill.js.map +1 -1
  279. package/lib/sync/unknownBlock.d.ts +3 -9
  280. package/lib/sync/unknownBlock.d.ts.map +1 -1
  281. package/lib/sync/unknownBlock.js +8 -41
  282. package/lib/sync/unknownBlock.js.map +1 -1
  283. package/lib/util/types.d.ts +2 -0
  284. package/lib/util/types.d.ts.map +1 -1
  285. package/lib/util/types.js +1 -0
  286. package/lib/util/types.js.map +1 -1
  287. package/package.json +16 -16
  288. package/src/api/impl/beacon/blocks/index.ts +16 -2
  289. package/src/api/impl/beacon/pool/index.ts +1 -1
  290. package/src/api/impl/beacon/state/index.ts +29 -41
  291. package/src/api/impl/beacon/state/utils.ts +11 -25
  292. package/src/api/impl/lodestar/index.ts +4 -8
  293. package/src/api/impl/proof/index.ts +2 -9
  294. package/src/api/impl/validator/index.ts +29 -41
  295. package/src/api/impl/validator/utils.ts +4 -7
  296. package/src/chain/archiveStore/archiveStore.ts +1 -0
  297. package/src/chain/archiveStore/historicalState/getHistoricalState.ts +10 -39
  298. package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +2 -1
  299. package/src/chain/archiveStore/historicalState/types.ts +2 -0
  300. package/src/chain/archiveStore/historicalState/worker.ts +1 -4
  301. package/src/chain/archiveStore/interface.ts +1 -0
  302. package/src/chain/balancesCache.ts +5 -11
  303. package/src/chain/blocks/blockInput/types.ts +1 -0
  304. package/src/chain/blocks/importBlock.ts +23 -25
  305. package/src/chain/blocks/importExecutionPayload.ts +89 -63
  306. package/src/chain/blocks/index.ts +3 -2
  307. package/src/chain/blocks/types.ts +26 -15
  308. package/src/chain/blocks/utils/checkpoint.ts +2 -2
  309. package/src/chain/blocks/verifyBlock.ts +5 -10
  310. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +9 -14
  311. package/src/chain/blocks/verifyBlocksSignatures.ts +3 -3
  312. package/src/chain/blocks/verifyBlocksStateTransitionOnly.ts +6 -8
  313. package/src/chain/chain.ts +75 -67
  314. package/src/chain/emitter.ts +2 -2
  315. package/src/chain/errors/blockError.ts +4 -4
  316. package/src/chain/forkChoice/index.ts +33 -42
  317. package/src/chain/initState.ts +7 -2
  318. package/src/chain/interface.ts +12 -13
  319. package/src/chain/lightClient/index.ts +9 -22
  320. package/src/chain/opPools/aggregatedAttestationPool.ts +15 -21
  321. package/src/chain/opPools/opPool.ts +13 -14
  322. package/src/chain/opPools/utils.ts +3 -3
  323. package/src/chain/options.ts +2 -0
  324. package/src/chain/prepareNextSlot.ts +6 -8
  325. package/src/chain/produceBlock/computeNewStateRoot.ts +6 -10
  326. package/src/chain/produceBlock/produceBlockBody.ts +22 -49
  327. package/src/chain/regen/interface.ts +13 -17
  328. package/src/chain/regen/queued.ts +16 -20
  329. package/src/chain/regen/regen.ts +16 -17
  330. package/src/chain/serializeState.ts +3 -3
  331. package/src/chain/shufflingCache.ts +5 -7
  332. package/src/chain/stateCache/fifoBlockStateCache.ts +7 -7
  333. package/src/chain/stateCache/persistentCheckpointsCache.ts +27 -42
  334. package/src/chain/stateCache/types.ts +14 -18
  335. package/src/chain/validation/attesterSlashing.ts +3 -3
  336. package/src/chain/validation/blobSidecar.ts +1 -1
  337. package/src/chain/validation/block.ts +2 -4
  338. package/src/chain/validation/blsToExecutionChange.ts +2 -2
  339. package/src/chain/validation/dataColumnSidecar.ts +1 -1
  340. package/src/chain/validation/executionPayloadBid.ts +3 -7
  341. package/src/chain/validation/executionPayloadEnvelope.ts +2 -8
  342. package/src/chain/validation/payloadAttestationMessage.ts +2 -4
  343. package/src/chain/validation/proposerSlashing.ts +1 -1
  344. package/src/chain/validation/signatureSets/contributionAndProof.ts +2 -7
  345. package/src/chain/validation/signatureSets/syncCommittee.ts +2 -7
  346. package/src/chain/validation/signatureSets/syncCommitteeContribution.ts +2 -2
  347. package/src/chain/validation/signatureSets/syncCommitteeSelectionProof.ts +2 -7
  348. package/src/chain/validation/syncCommittee.ts +21 -20
  349. package/src/chain/validation/syncCommitteeContributionAndProof.ts +5 -10
  350. package/src/chain/validation/voluntaryExit.ts +3 -8
  351. package/src/chain/validatorMonitor.ts +12 -11
  352. package/src/metrics/metrics/lodestar.ts +23 -19
  353. package/src/network/gossip/encoding.ts +16 -0
  354. package/src/network/interface.ts +15 -2
  355. package/src/network/libp2p/index.ts +5 -0
  356. package/src/network/network.ts +32 -4
  357. package/src/network/processor/extractSlotRootFns.ts +1 -1
  358. package/src/network/processor/gossipHandlers.ts +25 -16
  359. package/src/network/processor/index.ts +110 -89
  360. package/src/network/reqresp/ReqRespBeaconNode.ts +13 -0
  361. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +94 -0
  362. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRoot.ts +43 -0
  363. package/src/network/reqresp/handlers/index.ts +12 -0
  364. package/src/network/reqresp/protocols.ts +12 -0
  365. package/src/network/reqresp/rateLimit.ts +18 -0
  366. package/src/network/reqresp/score.ts +2 -0
  367. package/src/network/reqresp/types.ts +13 -0
  368. package/src/node/nodejs.ts +3 -5
  369. package/src/node/notifier.ts +4 -10
  370. package/src/sync/backfill/backfill.ts +3 -3
  371. package/src/sync/unknownBlock.ts +10 -50
  372. package/src/util/types.ts +6 -0
@@ -2,7 +2,7 @@ import {routes} from "@lodestar/api";
2
2
  import {ForkSeq} from "@lodestar/params";
3
3
  import {computeStartSlotAtEpoch} from "@lodestar/state-transition";
4
4
  import {RootHex, Slot, SlotRootHex} from "@lodestar/types";
5
- import {Logger, MapDef, mapValues, pruneSetToMax, sleep} from "@lodestar/utils";
5
+ import {Logger, MapDef, mapValues, sleep} from "@lodestar/utils";
6
6
  import {BlockInputSource} from "../../chain/blocks/blockInput/types.js";
7
7
  import {ChainEvent} from "../../chain/emitter.js";
8
8
  import {GossipErrorCode} from "../../chain/errors/gossipValidation.js";
@@ -87,27 +87,27 @@ const executeGossipWorkOrder = Object.keys(executeGossipWorkOrderObj) as (keyof
87
87
  // TODO: Arbitrary constant, check metrics
88
88
  const MAX_JOBS_SUBMITTED_PER_TICK = 128;
89
89
 
90
- // How many attestations (aggregate + unaggregate) we keep before new ones get dropped.
90
+ // How many gossip messages we keep before new ones get dropped.
91
91
  const MAX_QUEUED_UNKNOWN_BLOCK_GOSSIP_OBJECTS = 16_384;
92
92
 
93
- // We don't want to process too many attestations in a single tick
94
- // As seen on mainnet, attestation concurrency metric ranges from 1000 to 2000
93
+ // We don't want to process too many gossip messages in a single tick
94
+ // As seen on mainnet, gossip messages concurrency metric ranges from 1000 to 2000
95
95
  // so make this constant a little bit conservative
96
- const MAX_UNKNOWN_BLOCK_GOSSIP_OBJECTS_PER_TICK = 1024;
96
+ const MAX_AWAITING_GOSSIP_OBJECTS_PER_TICK = 1024;
97
97
 
98
98
  // Same motivation to JobItemQueue, we don't want to block the event loop
99
- const PROCESS_UNKNOWN_BLOCK_GOSSIP_OBJECTS_YIELD_EVERY_MS = 50;
99
+ const AWAITING_GOSSIP_OBJECTS_YIELD_EVERY_MS = 50;
100
100
 
101
101
  /**
102
102
  * Reprocess reject reason for metrics
103
103
  */
104
104
  export enum ReprocessRejectReason {
105
105
  /**
106
- * There are too many attestations that have unknown block root.
106
+ * There are too many gossip messages that have unknown block root.
107
107
  */
108
108
  reached_limit = "reached_limit",
109
109
  /**
110
- * The awaiting attestation is pruned per clock slot.
110
+ * The awaiting gossip message is pruned per clock slot.
111
111
  */
112
112
  expired = "expired",
113
113
  }
@@ -137,7 +137,7 @@ export enum CannotAcceptWorkReason {
137
137
  *
138
138
  * ### PendingGossipsubMessage beacon_attestation example
139
139
  *
140
- * For attestations, processing the message includes the steps:
140
+ * For gossip messages, processing the message includes the steps:
141
141
  * 1. Pre shuffling sync validation
142
142
  * 2. Retrieve shuffling: async + goes into the regen queue and can be expensive
143
143
  * 3. Pre sig validation sync validation
@@ -156,11 +156,10 @@ export class NetworkProcessor {
156
156
  private readonly gossipQueues: ReturnType<typeof createGossipQueues>;
157
157
  private readonly gossipTopicConcurrency: {[K in GossipType]: number};
158
158
  private readonly extractBlockSlotRootFns = createExtractBlockSlotRootFns();
159
- // we may not receive the block for Attestation and SignedAggregateAndProof messages, in that case PendingGossipsubMessage needs
159
+ // we may not receive the block for messages like Attestation and SignedAggregateAndProof messages, in that case PendingGossipsubMessage needs
160
160
  // to be stored in this Map and reprocessed once the block comes
161
- private readonly awaitingGossipsubMessagesByRootBySlot: MapDef<Slot, MapDef<RootHex, Set<PendingGossipsubMessage>>>;
162
- private unknownBlockGossipsubMessagesCount = 0;
163
- private unknownRootsBySlot = new MapDef<Slot, Set<RootHex>>(() => new Set());
161
+ private readonly awaitingMessagesByBlockRoot: MapDef<RootHex, Set<PendingGossipsubMessage>>;
162
+ private unknownBlocksBySlot = new MapDef<Slot, Set<RootHex>>(() => new Set());
164
163
 
165
164
  constructor(
166
165
  modules: NetworkProcessorModules,
@@ -184,9 +183,7 @@ export class NetworkProcessor {
184
183
  this.chain.emitter.on(routes.events.EventType.block, this.onBlockProcessed.bind(this));
185
184
  this.chain.clock.on(ClockEvent.slot, this.onClockSlot.bind(this));
186
185
 
187
- this.awaitingGossipsubMessagesByRootBySlot = new MapDef(
188
- () => new MapDef<RootHex, Set<PendingGossipsubMessage>>(() => new Set())
189
- );
186
+ this.awaitingMessagesByBlockRoot = new MapDef<RootHex, Set<PendingGossipsubMessage>>(() => new Set());
190
187
 
191
188
  // TODO: Implement queues and priorization for ReqResp incoming requests
192
189
  // Listens to NetworkEvent.reqRespIncomingRequest event
@@ -198,7 +195,7 @@ export class NetworkProcessor {
198
195
  metrics.gossipValidationQueue.keySize.set({topic}, this.gossipQueues[topic].keySize);
199
196
  metrics.gossipValidationQueue.concurrency.set({topic}, this.gossipTopicConcurrency[topic]);
200
197
  }
201
- metrics.reprocessGossipAttestations.countPerSlot.set(this.unknownBlockGossipsubMessagesCount);
198
+ metrics.awaitingBlockGossipMessages.countPerSlot.set(this.unknownBlockGossipsubMessagesCount);
202
199
  // specific metric for beacon_attestation topic
203
200
  metrics.gossipValidationQueue.keyAge.reset();
204
201
  for (const ageMs of this.gossipQueues.beacon_attestation.getDataAgeMs()) {
@@ -233,64 +230,77 @@ export class NetworkProcessor {
233
230
  return queue.getAll();
234
231
  }
235
232
 
236
- searchUnknownSlotRoot({slot, root}: SlotRootHex, source: BlockInputSource, peer?: PeerIdStr): void {
237
- if (this.chain.seenBlock(root) || this.unknownRootsBySlot.getOrDefault(slot).has(root)) {
233
+ /**
234
+ * Search block via `ChainEvent.unknownBlockRoot` event
235
+ * Note that slot is not necessarily the same to the block's slot but it can be used for a good prune strategy.
236
+ * In the rare case, if 2 messages on 2 slots search for the same root (for example beacon_attestation) we may emit the same root twice but BlockInputSync should handle it well.
237
+ */
238
+ searchUnknownBlock({slot, root}: SlotRootHex, source: BlockInputSource, peer?: PeerIdStr): void {
239
+ if (
240
+ this.chain.seenBlock(root) ||
241
+ this.awaitingMessagesByBlockRoot.has(root) ||
242
+ this.unknownBlocksBySlot.getOrDefault(slot).has(root)
243
+ ) {
238
244
  return;
239
245
  }
240
246
  // Search for the unknown block
241
- this.unknownRootsBySlot.getOrDefault(slot).add(root);
247
+ this.unknownBlocksBySlot.getOrDefault(slot).add(root);
242
248
  this.chain.emitter.emit(ChainEvent.unknownBlockRoot, {rootHex: root, peer, source});
243
249
  }
244
250
 
245
251
  private onPendingGossipsubMessage(message: PendingGossipsubMessage): void {
246
252
  const topicType = message.topic.type;
247
253
  const extractBlockSlotRootFn = this.extractBlockSlotRootFns[topicType];
248
- // check block root of Attestation and SignedAggregateAndProof messages
249
- if (extractBlockSlotRootFn) {
250
- const slotRoot = extractBlockSlotRootFn(message.msg.data, message.topic.boundary.fork);
251
- // if slotRoot is null, it means the msg.data is invalid
252
- // in that case message will be rejected when deserializing data in later phase (gossipValidatorFn)
253
- if (slotRoot) {
254
- // DOS protection: avoid processing messages that are too old
255
- const {slot, root} = slotRoot;
256
- const clockSlot = this.chain.clock.currentSlot;
257
- const {fork} = message.topic.boundary;
258
- let earliestPermissableSlot = clockSlot - DEFAULT_EARLIEST_PERMISSIBLE_SLOT_DISTANCE;
259
- if (ForkSeq[fork] >= ForkSeq.deneb && topicType === GossipType.beacon_attestation) {
260
- // post deneb, the attestations could be in current or previous epoch
261
- earliestPermissableSlot = computeStartSlotAtEpoch(this.chain.clock.currentEpoch - 1);
262
- }
263
- if (slot < earliestPermissableSlot) {
264
- // TODO: Should report the dropped job to gossip? It will be eventually pruned from the mcache
265
- this.metrics?.networkProcessor.gossipValidationError.inc({
266
- topic: topicType,
267
- error: GossipErrorCode.PAST_SLOT,
268
- });
269
- return;
270
- }
271
- message.msgSlot = slot;
272
- // check if we processed a block with this root
273
- // no need to check if root is a descendant of the current finalized block, it will be checked once we validate the message if needed
274
- if (root && !this.chain.forkChoice.hasBlockHexUnsafe(root)) {
275
- this.searchUnknownSlotRoot({slot, root}, BlockInputSource.gossip, message.propagationSource.toString());
276
-
277
- if (this.unknownBlockGossipsubMessagesCount > MAX_QUEUED_UNKNOWN_BLOCK_GOSSIP_OBJECTS) {
278
- // TODO: Should report the dropped job to gossip? It will be eventually pruned from the mcache
279
- this.metrics?.reprocessGossipAttestations.reject.inc({reason: ReprocessRejectReason.reached_limit});
280
- return;
281
- }
254
+ const slotRoot = extractBlockSlotRootFn
255
+ ? extractBlockSlotRootFn(message.msg.data, message.topic.boundary.fork)
256
+ : null;
257
+ if (slotRoot === null) {
258
+ // some messages don't have slot and root
259
+ // if the msg.data is invalid, message will be rejected when deserializing data in later phase (gossipValidatorFn)
260
+ this.pushPendingGossipsubMessageToQueue(message);
261
+ return;
262
+ }
282
263
 
283
- this.metrics?.reprocessGossipAttestations.total.inc();
284
- const awaitingGossipsubMessagesByRoot = this.awaitingGossipsubMessagesByRootBySlot.getOrDefault(slot);
285
- const awaitingGossipsubMessages = awaitingGossipsubMessagesByRoot.getOrDefault(root);
286
- awaitingGossipsubMessages.add(message);
287
- this.unknownBlockGossipsubMessagesCount++;
288
- return;
289
- }
264
+ // common check for all topics
265
+ // DOS protection: avoid processing messages that are too old
266
+ const {slot, root} = slotRoot;
267
+ const clockSlot = this.chain.clock.currentSlot;
268
+ const {fork} = message.topic.boundary;
269
+ let earliestPermissableSlot = clockSlot - DEFAULT_EARLIEST_PERMISSIBLE_SLOT_DISTANCE;
270
+ if (ForkSeq[fork] >= ForkSeq.deneb && topicType === GossipType.beacon_attestation) {
271
+ // post deneb, the attestations could be in current or previous epoch
272
+ earliestPermissableSlot = computeStartSlotAtEpoch(this.chain.clock.currentEpoch - 1);
273
+ }
274
+ if (slot < earliestPermissableSlot) {
275
+ // No need to report the dropped job to gossip. It will be eventually pruned from the mcache
276
+ this.metrics?.networkProcessor.gossipValidationError.inc({
277
+ topic: topicType,
278
+ error: GossipErrorCode.PAST_SLOT,
279
+ });
280
+ return;
281
+ }
282
+
283
+ message.msgSlot = slot;
284
+
285
+ // no need to check if root is a descendant of the current finalized block, it will be checked once we validate the message if needed
286
+ if (root && !this.chain.forkChoice.hasBlockHexUnsafe(root)) {
287
+ this.searchUnknownBlock({slot, root}, BlockInputSource.network_processor, message.propagationSource.toString());
288
+
289
+ if (this.unknownBlockGossipsubMessagesCount > MAX_QUEUED_UNKNOWN_BLOCK_GOSSIP_OBJECTS) {
290
+ // No need to report the dropped job to gossip. It will be eventually pruned from the mcache
291
+ this.metrics?.awaitingBlockGossipMessages.reject.inc({
292
+ reason: ReprocessRejectReason.reached_limit,
293
+ topic: topicType,
294
+ });
295
+ return;
290
296
  }
297
+
298
+ this.metrics?.awaitingBlockGossipMessages.queue.inc({topic: topicType});
299
+ const awaitingGossipsubMessages = this.awaitingMessagesByBlockRoot.getOrDefault(root);
300
+ awaitingGossipsubMessages.add(message);
301
+ return;
291
302
  }
292
303
 
293
- // bypass the check for other messages
294
304
  this.pushPendingGossipsubMessageToQueue(message);
295
305
  }
296
306
 
@@ -298,7 +308,7 @@ export class NetworkProcessor {
298
308
  const topicType = message.topic.type;
299
309
  const droppedCount = this.gossipQueues[topicType].add(message);
300
310
  if (droppedCount) {
301
- // TODO: Should report the dropped job to gossip? It will be eventually pruned from the mcache
311
+ // No need to report the dropped job to gossip. It will be eventually pruned from the mcache
302
312
  this.metrics?.gossipValidationQueue.droppedJobs.inc({topic: message.topic.type}, droppedCount);
303
313
  }
304
314
 
@@ -306,58 +316,61 @@ export class NetworkProcessor {
306
316
  this.executeWork();
307
317
  }
308
318
 
309
- private async onBlockProcessed({
310
- slot,
311
- block: rootHex,
312
- }: {
313
- slot: Slot;
314
- block: string;
315
- executionOptimistic: boolean;
316
- }): Promise<void> {
317
- const byRootGossipsubMessages = this.awaitingGossipsubMessagesByRootBySlot.getOrDefault(slot);
318
- const waitingGossipsubMessages = byRootGossipsubMessages.getOrDefault(rootHex);
319
- if (waitingGossipsubMessages.size === 0) {
319
+ private async onBlockProcessed({block: rootHex}: {block: string; executionOptimistic: boolean}): Promise<void> {
320
+ const waitingGossipsubMessages = this.awaitingMessagesByBlockRoot.get(rootHex);
321
+ if (!waitingGossipsubMessages || waitingGossipsubMessages.size === 0) {
320
322
  return;
321
323
  }
322
324
 
323
- this.metrics?.reprocessGossipAttestations.resolve.inc(waitingGossipsubMessages.size);
324
325
  const nowSec = Date.now() / 1000;
325
326
  let count = 0;
326
327
  // TODO: we can group attestations to process in batches but since we have the SeenAttestationDatas
327
328
  // cache, it may not be necessary at this time
328
329
  for (const message of waitingGossipsubMessages) {
329
- this.metrics?.reprocessGossipAttestations.waitSecBeforeResolve.set(nowSec - message.seenTimestampSec);
330
+ const topicType = message.topic.type;
331
+ this.metrics?.awaitingBlockGossipMessages.waitSecBeforeResolve.set(
332
+ {topic: topicType},
333
+ nowSec - message.seenTimestampSec
334
+ );
335
+ this.metrics?.awaitingBlockGossipMessages.resolve.inc({topic: topicType});
330
336
  this.pushPendingGossipsubMessageToQueue(message);
331
337
  count++;
332
338
  // don't want to block the event loop, worse case it'd wait for 16_084 / 1024 * 50ms = 800ms which is not a big deal
333
- if (count === MAX_UNKNOWN_BLOCK_GOSSIP_OBJECTS_PER_TICK) {
339
+ if (count === MAX_AWAITING_GOSSIP_OBJECTS_PER_TICK) {
334
340
  count = 0;
335
- await sleep(PROCESS_UNKNOWN_BLOCK_GOSSIP_OBJECTS_YIELD_EVERY_MS);
341
+ await sleep(AWAITING_GOSSIP_OBJECTS_YIELD_EVERY_MS);
336
342
  }
337
343
  }
338
344
 
339
- byRootGossipsubMessages.delete(rootHex);
345
+ this.awaitingMessagesByBlockRoot.delete(rootHex);
340
346
  }
341
347
 
342
348
  private onClockSlot(clockSlot: Slot): void {
343
349
  const nowSec = Date.now() / 1000;
344
- for (const [slot, gossipMessagesByRoot] of this.awaitingGossipsubMessagesByRootBySlot.entries()) {
345
- if (slot < clockSlot) {
346
- for (const gossipMessages of gossipMessagesByRoot.values()) {
350
+ const minSlot = clockSlot - MAX_UNKNOWN_ROOTS_SLOT_CACHE_SIZE;
351
+
352
+ for (const [slot, roots] of this.unknownBlocksBySlot) {
353
+ if (slot > minSlot) continue;
354
+ for (const rootHex of roots) {
355
+ const gossipMessages = this.awaitingMessagesByBlockRoot.get(rootHex);
356
+ if (gossipMessages !== undefined) {
347
357
  for (const message of gossipMessages) {
348
- this.metrics?.reprocessGossipAttestations.reject.inc({reason: ReprocessRejectReason.expired});
349
- this.metrics?.reprocessGossipAttestations.waitSecBeforeReject.set(
350
- {reason: ReprocessRejectReason.expired},
358
+ const topicType = message.topic.type;
359
+ this.metrics?.awaitingBlockGossipMessages.reject.inc({
360
+ topic: topicType,
361
+ reason: ReprocessRejectReason.expired,
362
+ });
363
+ this.metrics?.awaitingBlockGossipMessages.waitSecBeforeReject.set(
364
+ {topic: topicType, reason: ReprocessRejectReason.expired},
351
365
  nowSec - message.seenTimestampSec
352
366
  );
353
- // TODO: Should report the dropped job to gossip? It will be eventually pruned from the mcache
367
+ // No need to report the dropped job to gossip. It will be eventually pruned from the mcache
354
368
  }
369
+ this.awaitingMessagesByBlockRoot.delete(rootHex);
355
370
  }
356
- this.awaitingGossipsubMessagesByRootBySlot.delete(slot);
357
371
  }
372
+ this.unknownBlocksBySlot.delete(slot);
358
373
  }
359
- pruneSetToMax(this.unknownRootsBySlot, MAX_UNKNOWN_ROOTS_SLOT_CACHE_SIZE);
360
- this.unknownBlockGossipsubMessagesCount = 0;
361
374
  }
362
375
 
363
376
  private executeWork(): void {
@@ -496,4 +509,12 @@ export class NetworkProcessor {
496
509
 
497
510
  return null;
498
511
  }
512
+
513
+ private get unknownBlockGossipsubMessagesCount(): number {
514
+ let count = 0;
515
+ for (const messages of this.awaitingMessagesByBlockRoot.values()) {
516
+ count += messages.size;
517
+ }
518
+ return count;
519
+ }
499
520
  }
@@ -297,6 +297,19 @@ export class ReqRespBeaconNode extends ReqResp {
297
297
  );
298
298
  }
299
299
 
300
+ if (ForkSeq[fork] >= ForkSeq.gloas) {
301
+ protocolsAtFork.push(
302
+ [
303
+ protocols.ExecutionPayloadEnvelopesByRoot(fork, this.config),
304
+ this.getHandler(ReqRespMethod.ExecutionPayloadEnvelopesByRoot),
305
+ ],
306
+ [
307
+ protocols.ExecutionPayloadEnvelopesByRange(fork, this.config),
308
+ this.getHandler(ReqRespMethod.ExecutionPayloadEnvelopesByRange),
309
+ ]
310
+ );
311
+ }
312
+
300
313
  return protocolsAtFork;
301
314
  }
302
315
 
@@ -0,0 +1,94 @@
1
+ import {ChainConfig} from "@lodestar/config";
2
+ import {PayloadStatus} from "@lodestar/fork-choice";
3
+ import {GENESIS_SLOT} from "@lodestar/params";
4
+ import {RespStatus, ResponseError, ResponseOutgoing} from "@lodestar/reqresp";
5
+ import {computeEpochAtSlot} from "@lodestar/state-transition";
6
+ import {gloas} from "@lodestar/types";
7
+ import {IBeaconChain} from "../../../chain/index.js";
8
+ import {IBeaconDb} from "../../../db/index.js";
9
+
10
+ export async function* onExecutionPayloadEnvelopesByRange(
11
+ request: gloas.ExecutionPayloadEnvelopesByRangeRequest,
12
+ chain: IBeaconChain,
13
+ db: IBeaconDb
14
+ ): AsyncIterable<ResponseOutgoing> {
15
+ const {startSlot, count} = validateExecutionPayloadEnvelopesByRangeRequest(chain.config, request);
16
+ const endSlot = startSlot + count;
17
+
18
+ if (startSlot < chain.earliestAvailableSlot) {
19
+ return;
20
+ }
21
+
22
+ const finalized = db.executionPayloadEnvelopeArchive;
23
+ const finalizedSlot = chain.forkChoice.getFinalizedCheckpointSlot();
24
+
25
+ // Finalized range of envelopes
26
+ if (startSlot <= finalizedSlot) {
27
+ for await (const {key, value: envelopeBytes} of finalized.binaryEntriesStream({
28
+ gte: startSlot,
29
+ lt: endSlot,
30
+ })) {
31
+ const slot = finalized.decodeKey(key);
32
+ yield {
33
+ data: envelopeBytes,
34
+ boundary: chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(slot)),
35
+ };
36
+ }
37
+ }
38
+
39
+ // Non-finalized range of envelopes
40
+ if (endSlot > finalizedSlot) {
41
+ const headBlock = chain.forkChoice.getHead();
42
+ const headRoot = headBlock.blockRoot;
43
+ const headChain = chain.forkChoice.getAllAncestorBlocks(headRoot, headBlock.payloadStatus);
44
+
45
+ // Iterate head chain with ascending block numbers
46
+ for (let i = headChain.length - 1; i >= 0; i--) {
47
+ const block = headChain[i];
48
+
49
+ if (block.slot >= startSlot && block.slot < endSlot) {
50
+ // Skip EMPTY blocks
51
+ if (block.payloadStatus !== PayloadStatus.FULL) {
52
+ continue;
53
+ }
54
+
55
+ const envelopeBytes = await chain.getSerializedExecutionPayloadEnvelope(block.slot, block.blockRoot);
56
+ if (!envelopeBytes) {
57
+ throw new ResponseError(
58
+ RespStatus.SERVER_ERROR,
59
+ `No envelope for root ${block.blockRoot} slot ${block.slot}, startSlot=${startSlot} endSlot=${endSlot} finalizedSlot=${finalizedSlot}`
60
+ );
61
+ }
62
+
63
+ yield {
64
+ data: envelopeBytes,
65
+ boundary: chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(block.slot)),
66
+ };
67
+ } else if (block.slot >= endSlot) {
68
+ break;
69
+ }
70
+ }
71
+ }
72
+ }
73
+
74
+ export function validateExecutionPayloadEnvelopesByRangeRequest(
75
+ config: ChainConfig,
76
+ request: gloas.ExecutionPayloadEnvelopesByRangeRequest
77
+ ): gloas.ExecutionPayloadEnvelopesByRangeRequest {
78
+ const {startSlot} = request;
79
+ let {count} = request;
80
+
81
+ if (count < 1) {
82
+ throw new ResponseError(RespStatus.INVALID_REQUEST, "count < 1");
83
+ }
84
+ // TODO: validate against MIN_EPOCHS_FOR_BLOCK_REQUESTS
85
+ if (startSlot < GENESIS_SLOT) {
86
+ throw new ResponseError(RespStatus.INVALID_REQUEST, "startSlot < genesis");
87
+ }
88
+
89
+ if (count > config.MAX_REQUEST_BLOCKS_DENEB) {
90
+ count = config.MAX_REQUEST_BLOCKS_DENEB;
91
+ }
92
+
93
+ return {startSlot, count};
94
+ }
@@ -0,0 +1,43 @@
1
+ import {ResponseOutgoing} from "@lodestar/reqresp";
2
+ import {computeEpochAtSlot} from "@lodestar/state-transition";
3
+ import {toRootHex} from "@lodestar/utils";
4
+ import {IBeaconChain} from "../../../chain/index.js";
5
+ import {IBeaconDb} from "../../../db/index.js";
6
+ import {ExecutionPayloadEnvelopesByRootRequest} from "../../../util/types.js";
7
+
8
+ export async function* onExecutionPayloadEnvelopesByRoot(
9
+ requestBody: ExecutionPayloadEnvelopesByRootRequest,
10
+ chain: IBeaconChain,
11
+ db: IBeaconDb
12
+ ): AsyncIterable<ResponseOutgoing> {
13
+ // Spec: [max(GLOAS_FORK_EPOCH, current_epoch - MIN_EPOCHS_FOR_BLOCK_REQUESTS), current_epoch]
14
+ const currentEpoch = chain.clock.currentEpoch;
15
+ const minimumRequestEpoch = Math.max(
16
+ currentEpoch - chain.config.MIN_EPOCHS_FOR_BLOCK_REQUESTS,
17
+ chain.config.GLOAS_FORK_EPOCH
18
+ );
19
+
20
+ for (const root of requestBody) {
21
+ const rootHex = toRootHex(root);
22
+ const block = chain.forkChoice.getBlockHexDefaultStatus(rootHex);
23
+ // If the block is not in fork choice, it may be finalized. Attempt to find its slot in block archive
24
+ const slot = block ? block.slot : await db.blockArchive.getSlotByRoot(root);
25
+
26
+ if (slot === null) {
27
+ continue;
28
+ }
29
+
30
+ const requestedEpoch = computeEpochAtSlot(slot);
31
+ if (requestedEpoch < minimumRequestEpoch) {
32
+ continue;
33
+ }
34
+
35
+ const envelopeBytes = await chain.getSerializedExecutionPayloadEnvelope(slot, rootHex);
36
+ if (envelopeBytes) {
37
+ yield {
38
+ data: envelopeBytes,
39
+ boundary: chain.config.getForkBoundaryAtEpoch(requestedEpoch),
40
+ };
41
+ }
42
+ }
43
+ }
@@ -6,6 +6,7 @@ import {
6
6
  BeaconBlocksByRootRequestType,
7
7
  BlobSidecarsByRootRequestType,
8
8
  DataColumnSidecarsByRootRequestType,
9
+ ExecutionPayloadEnvelopesByRootRequestType,
9
10
  } from "../../../util/types.js";
10
11
  import {GetReqRespHandlerFn, ReqRespMethod} from "../types.js";
11
12
  import {onBeaconBlocksByRange} from "./beaconBlocksByRange.js";
@@ -14,6 +15,8 @@ import {onBlobSidecarsByRange} from "./blobSidecarsByRange.js";
14
15
  import {onBlobSidecarsByRoot} from "./blobSidecarsByRoot.js";
15
16
  import {onDataColumnSidecarsByRange} from "./dataColumnSidecarsByRange.js";
16
17
  import {onDataColumnSidecarsByRoot} from "./dataColumnSidecarsByRoot.js";
18
+ import {onExecutionPayloadEnvelopesByRange} from "./executionPayloadEnvelopesByRange.js";
19
+ import {onExecutionPayloadEnvelopesByRoot} from "./executionPayloadEnvelopesByRoot.js";
17
20
  import {onLightClientBootstrap} from "./lightClientBootstrap.js";
18
21
  import {onLightClientFinalityUpdate} from "./lightClientFinalityUpdate.js";
19
22
  import {onLightClientOptimisticUpdate} from "./lightClientOptimisticUpdate.js";
@@ -62,6 +65,15 @@ export function getReqRespHandlers({db, chain}: {db: IBeaconDb; chain: IBeaconCh
62
65
  return onDataColumnSidecarsByRoot(body, chain, db, peerId, peerClient);
63
66
  },
64
67
 
68
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: (req) => {
69
+ const body = ExecutionPayloadEnvelopesByRootRequestType(chain.config).deserialize(req.data);
70
+ return onExecutionPayloadEnvelopesByRoot(body, chain, db);
71
+ },
72
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: (req) => {
73
+ const body = ssz.gloas.ExecutionPayloadEnvelopesByRangeRequest.deserialize(req.data);
74
+ return onExecutionPayloadEnvelopesByRange(body, chain, db);
75
+ },
76
+
65
77
  [ReqRespMethod.LightClientBootstrap]: (req) => {
66
78
  const body = ssz.Root.deserialize(req.data);
67
79
  return onLightClientBootstrap(body, chain);
@@ -94,6 +94,18 @@ export const DataColumnSidecarsByRoot = toProtocol({
94
94
  contextBytesType: ContextBytesType.ForkDigest,
95
95
  });
96
96
 
97
+ export const ExecutionPayloadEnvelopesByRoot = toProtocol({
98
+ method: ReqRespMethod.ExecutionPayloadEnvelopesByRoot,
99
+ version: Version.V1,
100
+ contextBytesType: ContextBytesType.ForkDigest,
101
+ });
102
+
103
+ export const ExecutionPayloadEnvelopesByRange = toProtocol({
104
+ method: ReqRespMethod.ExecutionPayloadEnvelopesByRange,
105
+ version: Version.V1,
106
+ contextBytesType: ContextBytesType.ForkDigest,
107
+ });
108
+
97
109
  export const LightClientBootstrap = toProtocol({
98
110
  method: ReqRespMethod.LightClientBootstrap,
99
111
  version: Version.V1,
@@ -73,6 +73,24 @@ export const rateLimitQuotas: (fork: ForkName, config: BeaconConfig) => Record<R
73
73
  req.reduce((total, item) => total + item.columns.length, 0)
74
74
  ),
75
75
  },
76
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: {
77
+ byPeer: {quota: config.MAX_REQUEST_PAYLOADS, quotaTimeMs: 10_000},
78
+ getRequestCount: getRequestCountFn(
79
+ fork,
80
+ config,
81
+ ReqRespMethod.ExecutionPayloadEnvelopesByRoot,
82
+ (req) => req.length
83
+ ),
84
+ },
85
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: {
86
+ byPeer: {quota: config.MAX_REQUEST_BLOCKS_DENEB, quotaTimeMs: 10_000},
87
+ getRequestCount: getRequestCountFn(
88
+ fork,
89
+ config,
90
+ ReqRespMethod.ExecutionPayloadEnvelopesByRange,
91
+ (req) => req.count
92
+ ),
93
+ },
76
94
  [ReqRespMethod.LightClientBootstrap]: {
77
95
  // As similar in the nature of `Status` protocol so we use the same rate limits.
78
96
  byPeer: {quota: 5, quotaTimeMs: 15_000},
@@ -46,6 +46,8 @@ export function onOutgoingReqRespError(e: RequestError, method: ReqRespMethod):
46
46
  return PeerAction.LowToleranceError;
47
47
  case ReqRespMethod.BeaconBlocksByRange:
48
48
  case ReqRespMethod.BeaconBlocksByRoot:
49
+ case ReqRespMethod.ExecutionPayloadEnvelopesByRoot:
50
+ case ReqRespMethod.ExecutionPayloadEnvelopesByRange:
49
51
  return PeerAction.MidToleranceError;
50
52
  default:
51
53
  return null;
@@ -14,6 +14,7 @@ import {
14
14
  altair,
15
15
  deneb,
16
16
  fulu,
17
+ gloas,
17
18
  phase0,
18
19
  ssz,
19
20
  sszTypesFor,
@@ -25,6 +26,8 @@ import {
25
26
  BlobSidecarsByRootRequestType,
26
27
  DataColumnSidecarsByRootRequest,
27
28
  DataColumnSidecarsByRootRequestType,
29
+ ExecutionPayloadEnvelopesByRootRequest,
30
+ ExecutionPayloadEnvelopesByRootRequestType,
28
31
  } from "../../util/types.js";
29
32
 
30
33
  export type ProtocolNoHandler = Omit<Protocol, "handler">;
@@ -42,6 +45,8 @@ export enum ReqRespMethod {
42
45
  BlobSidecarsByRoot = "blob_sidecars_by_root",
43
46
  DataColumnSidecarsByRange = "data_column_sidecars_by_range",
44
47
  DataColumnSidecarsByRoot = "data_column_sidecars_by_root",
48
+ ExecutionPayloadEnvelopesByRoot = "execution_payload_envelopes_by_root",
49
+ ExecutionPayloadEnvelopesByRange = "execution_payload_envelopes_by_range",
45
50
  LightClientBootstrap = "light_client_bootstrap",
46
51
  LightClientUpdatesByRange = "light_client_updates_by_range",
47
52
  LightClientFinalityUpdate = "light_client_finality_update",
@@ -60,6 +65,8 @@ export type RequestBodyByMethod = {
60
65
  [ReqRespMethod.BlobSidecarsByRoot]: BlobSidecarsByRootRequest;
61
66
  [ReqRespMethod.DataColumnSidecarsByRange]: fulu.DataColumnSidecarsByRangeRequest;
62
67
  [ReqRespMethod.DataColumnSidecarsByRoot]: DataColumnSidecarsByRootRequest;
68
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: ExecutionPayloadEnvelopesByRootRequest;
69
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: gloas.ExecutionPayloadEnvelopesByRangeRequest;
63
70
  [ReqRespMethod.LightClientBootstrap]: Root;
64
71
  [ReqRespMethod.LightClientUpdatesByRange]: altair.LightClientUpdatesByRange;
65
72
  [ReqRespMethod.LightClientFinalityUpdate]: null;
@@ -78,6 +85,8 @@ type ResponseBodyByMethod = {
78
85
  [ReqRespMethod.BlobSidecarsByRoot]: deneb.BlobSidecar;
79
86
  [ReqRespMethod.DataColumnSidecarsByRange]: fulu.DataColumnSidecar;
80
87
  [ReqRespMethod.DataColumnSidecarsByRoot]: fulu.DataColumnSidecar;
88
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: gloas.SignedExecutionPayloadEnvelope;
89
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: gloas.SignedExecutionPayloadEnvelope;
81
90
 
82
91
  [ReqRespMethod.LightClientBootstrap]: LightClientBootstrap;
83
92
  [ReqRespMethod.LightClientUpdatesByRange]: LightClientUpdate;
@@ -105,6 +114,8 @@ export const requestSszTypeByMethod: (
105
114
  [ReqRespMethod.BlobSidecarsByRoot]: BlobSidecarsByRootRequestType(fork, config),
106
115
  [ReqRespMethod.DataColumnSidecarsByRange]: ssz.fulu.DataColumnSidecarsByRangeRequest,
107
116
  [ReqRespMethod.DataColumnSidecarsByRoot]: DataColumnSidecarsByRootRequestType(config),
117
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: ExecutionPayloadEnvelopesByRootRequestType(config),
118
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: ssz.gloas.ExecutionPayloadEnvelopesByRangeRequest,
108
119
 
109
120
  [ReqRespMethod.LightClientBootstrap]: ssz.Root,
110
121
  [ReqRespMethod.LightClientUpdatesByRange]: ssz.altair.LightClientUpdatesByRange,
@@ -137,6 +148,8 @@ export const responseSszTypeByMethod: {[K in ReqRespMethod]: ResponseTypeGetter<
137
148
  [ReqRespMethod.LightClientFinalityUpdate]: (fork) => sszTypesFor(onlyPostAltairFork(fork)).LightClientFinalityUpdate,
138
149
  [ReqRespMethod.DataColumnSidecarsByRange]: () => ssz.fulu.DataColumnSidecar,
139
150
  [ReqRespMethod.DataColumnSidecarsByRoot]: () => ssz.fulu.DataColumnSidecar,
151
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: () => ssz.gloas.SignedExecutionPayloadEnvelope,
152
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: () => ssz.gloas.SignedExecutionPayloadEnvelope,
140
153
  [ReqRespMethod.LightClientOptimisticUpdate]: (fork) =>
141
154
  sszTypesFor(onlyPostAltairFork(fork)).LightClientOptimisticUpdate,
142
155
  };
@@ -6,7 +6,7 @@ import {BeaconApiMethods} from "@lodestar/api/beacon/server";
6
6
  import {BeaconConfig} from "@lodestar/config";
7
7
  import type {LoggerNode} from "@lodestar/logger/node";
8
8
  import {ZERO_HASH_HEX} from "@lodestar/params";
9
- import {CachedBeaconStateAllForks, PubkeyCache, isExecutionCachedStateType} from "@lodestar/state-transition";
9
+ import {IBeaconStateView, PubkeyCache} from "@lodestar/state-transition";
10
10
  import {phase0} from "@lodestar/types";
11
11
  import {sleep, toRootHex} from "@lodestar/utils";
12
12
  import {ProcessShutdownCallback} from "@lodestar/validator";
@@ -53,7 +53,7 @@ export type BeaconNodeInitModules = {
53
53
  privateKey: PrivateKey;
54
54
  dataDir: string;
55
55
  peerStoreDir?: string;
56
- anchorState: CachedBeaconStateAllForks;
56
+ anchorState: IBeaconStateView;
57
57
  isAnchorStateFinalized: boolean;
58
58
  wsCheckpoint?: phase0.Checkpoint;
59
59
  metricsRegistries?: Registry[];
@@ -221,9 +221,7 @@ export class BeaconNode {
221
221
 
222
222
  let executionEngineOpts = opts.executionEngine;
223
223
  if (opts.executionEngine.mode === "mock") {
224
- const eth1BlockHash = isExecutionCachedStateType(anchorState)
225
- ? toRootHex(anchorState.latestExecutionPayloadHeader.blockHash)
226
- : undefined;
224
+ const eth1BlockHash = anchorState.isExecutionStateType ? toRootHex(anchorState.latestBlockHash) : undefined;
227
225
  executionEngineOpts = {
228
226
  ...opts.executionEngine,
229
227
  genesisBlockHash: ZERO_HASH_HEX,