@lodestar/beacon-node 1.43.0-dev.aef3645690 → 1.43.0-dev.b0e1143d06

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 (449) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +17 -9
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
  5. package/lib/api/impl/beacon/pool/index.js +45 -2
  6. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  7. package/lib/api/impl/beacon/state/utils.d.ts +2 -2
  8. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  9. package/lib/api/impl/beacon/state/utils.js.map +1 -1
  10. package/lib/api/impl/debug/index.d.ts.map +1 -1
  11. package/lib/api/impl/debug/index.js +0 -1
  12. package/lib/api/impl/debug/index.js.map +1 -1
  13. package/lib/api/impl/lodestar/index.js +1 -1
  14. package/lib/api/impl/lodestar/index.js.map +1 -1
  15. package/lib/api/impl/validator/index.d.ts.map +1 -1
  16. package/lib/api/impl/validator/index.js +68 -5
  17. package/lib/api/impl/validator/index.js.map +1 -1
  18. package/lib/chain/GetBlobsTracker.d.ts +1 -1
  19. package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
  20. package/lib/chain/GetBlobsTracker.js +1 -2
  21. package/lib/chain/GetBlobsTracker.js.map +1 -1
  22. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  23. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  24. package/lib/chain/archiveStore/interface.d.ts +4 -4
  25. package/lib/chain/archiveStore/interface.d.ts.map +1 -1
  26. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts +4 -4
  27. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts.map +1 -1
  28. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js +2 -4
  29. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js.map +1 -1
  30. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +2 -2
  31. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
  32. package/lib/chain/archiveStore/utils/archiveBlocks.js +110 -58
  33. package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
  34. package/lib/chain/blocks/blockInput/blockInput.d.ts +3 -0
  35. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  36. package/lib/chain/blocks/blockInput/blockInput.js +4 -1
  37. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  38. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  39. package/lib/chain/blocks/importBlock.js +38 -58
  40. package/lib/chain/blocks/importBlock.js.map +1 -1
  41. package/lib/chain/blocks/importExecutionPayload.d.ts +32 -14
  42. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  43. package/lib/chain/blocks/importExecutionPayload.js +101 -90
  44. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  45. package/lib/chain/blocks/index.d.ts +5 -3
  46. package/lib/chain/blocks/index.d.ts.map +1 -1
  47. package/lib/chain/blocks/index.js +58 -26
  48. package/lib/chain/blocks/index.js.map +1 -1
  49. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +15 -1
  50. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
  51. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +48 -2
  52. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
  53. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +17 -0
  54. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
  55. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +5 -0
  56. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -1
  57. package/lib/chain/blocks/payloadEnvelopeProcessor.js +7 -5
  58. package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
  59. package/lib/chain/blocks/types.d.ts +16 -21
  60. package/lib/chain/blocks/types.d.ts.map +1 -1
  61. package/lib/chain/blocks/utils/chainSegment.d.ts +21 -2
  62. package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
  63. package/lib/chain/blocks/utils/chainSegment.js +92 -12
  64. package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
  65. package/lib/chain/blocks/verifyBlock.d.ts +5 -3
  66. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  67. package/lib/chain/blocks/verifyBlock.js +50 -7
  68. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  69. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +0 -4
  70. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  71. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +5 -2
  72. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  73. package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts +2 -1
  74. package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
  75. package/lib/chain/blocks/verifyBlocksSanityChecks.js +25 -5
  76. package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
  77. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +24 -0
  78. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -0
  79. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +80 -0
  80. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -0
  81. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts +14 -0
  82. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -0
  83. package/lib/chain/blocks/verifyPayloadsDataAvailability.js +30 -0
  84. package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -0
  85. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts +1 -1
  86. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts.map +1 -1
  87. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js +2 -11
  88. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js.map +1 -1
  89. package/lib/chain/chain.d.ts +8 -6
  90. package/lib/chain/chain.d.ts.map +1 -1
  91. package/lib/chain/chain.js +59 -49
  92. package/lib/chain/chain.js.map +1 -1
  93. package/lib/chain/emitter.d.ts +16 -15
  94. package/lib/chain/emitter.d.ts.map +1 -1
  95. package/lib/chain/emitter.js +5 -4
  96. package/lib/chain/emitter.js.map +1 -1
  97. package/lib/chain/errors/attestationError.d.ts +8 -1
  98. package/lib/chain/errors/attestationError.d.ts.map +1 -1
  99. package/lib/chain/errors/attestationError.js +4 -0
  100. package/lib/chain/errors/attestationError.js.map +1 -1
  101. package/lib/chain/errors/blockError.d.ts +8 -1
  102. package/lib/chain/errors/blockError.d.ts.map +1 -1
  103. package/lib/chain/errors/blockError.js +2 -0
  104. package/lib/chain/errors/blockError.js.map +1 -1
  105. package/lib/chain/errors/executionPayloadBid.d.ts +5 -0
  106. package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
  107. package/lib/chain/errors/executionPayloadBid.js +1 -0
  108. package/lib/chain/errors/executionPayloadBid.js.map +1 -1
  109. package/lib/chain/errors/executionPayloadEnvelope.d.ts +5 -0
  110. package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
  111. package/lib/chain/errors/executionPayloadEnvelope.js +1 -0
  112. package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
  113. package/lib/chain/errors/index.d.ts +1 -0
  114. package/lib/chain/errors/index.d.ts.map +1 -1
  115. package/lib/chain/errors/index.js +1 -0
  116. package/lib/chain/errors/index.js.map +1 -1
  117. package/lib/chain/errors/proposerPreferences.d.ts +40 -0
  118. package/lib/chain/errors/proposerPreferences.d.ts.map +1 -0
  119. package/lib/chain/errors/proposerPreferences.js +14 -0
  120. package/lib/chain/errors/proposerPreferences.js.map +1 -0
  121. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  122. package/lib/chain/forkChoice/index.js +11 -15
  123. package/lib/chain/forkChoice/index.js.map +1 -1
  124. package/lib/chain/initState.d.ts.map +1 -1
  125. package/lib/chain/initState.js +6 -1
  126. package/lib/chain/initState.js.map +1 -1
  127. package/lib/chain/interface.d.ts +7 -5
  128. package/lib/chain/interface.d.ts.map +1 -1
  129. package/lib/chain/interface.js.map +1 -1
  130. package/lib/chain/opPools/payloadAttestationPool.d.ts +3 -2
  131. package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -1
  132. package/lib/chain/opPools/payloadAttestationPool.js +26 -4
  133. package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
  134. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  135. package/lib/chain/prepareNextSlot.js +47 -23
  136. package/lib/chain/prepareNextSlot.js.map +1 -1
  137. package/lib/chain/produceBlock/computeNewStateRoot.d.ts +3 -9
  138. package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
  139. package/lib/chain/produceBlock/computeNewStateRoot.js +5 -32
  140. package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
  141. package/lib/chain/produceBlock/produceBlockBody.d.ts +13 -8
  142. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  143. package/lib/chain/produceBlock/produceBlockBody.js +68 -25
  144. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  145. package/lib/chain/regen/errors.d.ts +1 -11
  146. package/lib/chain/regen/errors.d.ts.map +1 -1
  147. package/lib/chain/regen/errors.js +0 -2
  148. package/lib/chain/regen/errors.js.map +1 -1
  149. package/lib/chain/regen/interface.d.ts +7 -12
  150. package/lib/chain/regen/interface.d.ts.map +1 -1
  151. package/lib/chain/regen/interface.js +1 -0
  152. package/lib/chain/regen/interface.js.map +1 -1
  153. package/lib/chain/regen/queued.d.ts +6 -11
  154. package/lib/chain/regen/queued.d.ts.map +1 -1
  155. package/lib/chain/regen/queued.js +9 -44
  156. package/lib/chain/regen/queued.js.map +1 -1
  157. package/lib/chain/regen/regen.d.ts +0 -5
  158. package/lib/chain/regen/regen.d.ts.map +1 -1
  159. package/lib/chain/regen/regen.js +8 -38
  160. package/lib/chain/regen/regen.js.map +1 -1
  161. package/lib/chain/seenCache/index.d.ts +1 -0
  162. package/lib/chain/seenCache/index.d.ts.map +1 -1
  163. package/lib/chain/seenCache/index.js +1 -0
  164. package/lib/chain/seenCache/index.js.map +1 -1
  165. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +24 -7
  166. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
  167. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +69 -17
  168. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
  169. package/lib/chain/seenCache/seenProposerPreferences.d.ts +16 -0
  170. package/lib/chain/seenCache/seenProposerPreferences.d.ts.map +1 -0
  171. package/lib/chain/seenCache/seenProposerPreferences.js +26 -0
  172. package/lib/chain/seenCache/seenProposerPreferences.js.map +1 -0
  173. package/lib/chain/stateCache/datastore/db.d.ts +5 -4
  174. package/lib/chain/stateCache/datastore/db.d.ts.map +1 -1
  175. package/lib/chain/stateCache/datastore/db.js +10 -32
  176. package/lib/chain/stateCache/datastore/db.js.map +1 -1
  177. package/lib/chain/stateCache/datastore/file.d.ts +1 -1
  178. package/lib/chain/stateCache/datastore/file.d.ts.map +1 -1
  179. package/lib/chain/stateCache/datastore/file.js +5 -5
  180. package/lib/chain/stateCache/datastore/file.js.map +1 -1
  181. package/lib/chain/stateCache/datastore/types.d.ts +1 -1
  182. package/lib/chain/stateCache/datastore/types.d.ts.map +1 -1
  183. package/lib/chain/stateCache/fifoBlockStateCache.d.ts +1 -7
  184. package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
  185. package/lib/chain/stateCache/fifoBlockStateCache.js +0 -8
  186. package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
  187. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +13 -30
  188. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  189. package/lib/chain/stateCache/persistentCheckpointsCache.js +120 -216
  190. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  191. package/lib/chain/stateCache/types.d.ts +8 -15
  192. package/lib/chain/stateCache/types.d.ts.map +1 -1
  193. package/lib/chain/stateCache/types.js.map +1 -1
  194. package/lib/chain/validation/aggregateAndProof.js +12 -0
  195. package/lib/chain/validation/aggregateAndProof.js.map +1 -1
  196. package/lib/chain/validation/attestation.d.ts.map +1 -1
  197. package/lib/chain/validation/attestation.js +12 -0
  198. package/lib/chain/validation/attestation.js.map +1 -1
  199. package/lib/chain/validation/block.d.ts.map +1 -1
  200. package/lib/chain/validation/block.js +1 -0
  201. package/lib/chain/validation/block.js.map +1 -1
  202. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  203. package/lib/chain/validation/executionPayloadBid.js +24 -9
  204. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  205. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  206. package/lib/chain/validation/executionPayloadEnvelope.js +21 -11
  207. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  208. package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
  209. package/lib/chain/validation/payloadAttestationMessage.js +4 -3
  210. package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
  211. package/lib/chain/validation/proposerPreferences.d.ts +8 -0
  212. package/lib/chain/validation/proposerPreferences.d.ts.map +1 -0
  213. package/lib/chain/validation/proposerPreferences.js +91 -0
  214. package/lib/chain/validation/proposerPreferences.js.map +1 -0
  215. package/lib/db/repositories/executionPayloadEnvelopeArchive.js +1 -1
  216. package/lib/db/repositories/executionPayloadEnvelopeArchive.js.map +1 -1
  217. package/lib/execution/engine/http.d.ts.map +1 -1
  218. package/lib/execution/engine/http.js +21 -14
  219. package/lib/execution/engine/http.js.map +1 -1
  220. package/lib/execution/engine/interface.d.ts +1 -0
  221. package/lib/execution/engine/interface.d.ts.map +1 -1
  222. package/lib/execution/engine/mock.d.ts.map +1 -1
  223. package/lib/execution/engine/mock.js +6 -0
  224. package/lib/execution/engine/mock.js.map +1 -1
  225. package/lib/execution/engine/types.d.ts +20 -0
  226. package/lib/execution/engine/types.d.ts.map +1 -1
  227. package/lib/execution/engine/types.js +18 -0
  228. package/lib/execution/engine/types.js.map +1 -1
  229. package/lib/metrics/metrics/lodestar.d.ts +5 -0
  230. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  231. package/lib/metrics/metrics/lodestar.js +9 -0
  232. package/lib/metrics/metrics/lodestar.js.map +1 -1
  233. package/lib/network/gossip/interface.d.ts +7 -1
  234. package/lib/network/gossip/interface.d.ts.map +1 -1
  235. package/lib/network/gossip/interface.js +1 -0
  236. package/lib/network/gossip/interface.js.map +1 -1
  237. package/lib/network/gossip/scoringParameters.d.ts.map +1 -1
  238. package/lib/network/gossip/scoringParameters.js +12 -1
  239. package/lib/network/gossip/scoringParameters.js.map +1 -1
  240. package/lib/network/gossip/topic.d.ts +33 -2
  241. package/lib/network/gossip/topic.d.ts.map +1 -1
  242. package/lib/network/gossip/topic.js +6 -0
  243. package/lib/network/gossip/topic.js.map +1 -1
  244. package/lib/network/interface.d.ts +2 -0
  245. package/lib/network/interface.d.ts.map +1 -1
  246. package/lib/network/network.d.ts +2 -0
  247. package/lib/network/network.d.ts.map +1 -1
  248. package/lib/network/network.js +9 -1
  249. package/lib/network/network.js.map +1 -1
  250. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  251. package/lib/network/processor/gossipHandlers.js +91 -23
  252. package/lib/network/processor/gossipHandlers.js.map +1 -1
  253. package/lib/network/processor/gossipQueues/index.d.ts.map +1 -1
  254. package/lib/network/processor/gossipQueues/index.js +5 -0
  255. package/lib/network/processor/gossipQueues/index.js.map +1 -1
  256. package/lib/network/processor/index.d.ts.map +1 -1
  257. package/lib/network/processor/index.js +6 -5
  258. package/lib/network/processor/index.js.map +1 -1
  259. package/lib/network/reqresp/ReqRespBeaconNode.d.ts.map +1 -1
  260. package/lib/network/reqresp/ReqRespBeaconNode.js +1 -1
  261. package/lib/network/reqresp/ReqRespBeaconNode.js.map +1 -1
  262. package/lib/network/reqresp/handlers/beaconBlocksByHead.d.ts +9 -0
  263. package/lib/network/reqresp/handlers/beaconBlocksByHead.d.ts.map +1 -0
  264. package/lib/network/reqresp/handlers/beaconBlocksByHead.js +61 -0
  265. package/lib/network/reqresp/handlers/beaconBlocksByHead.js.map +1 -0
  266. package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
  267. package/lib/network/reqresp/handlers/beaconBlocksByRange.js +14 -6
  268. package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
  269. package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts.map +1 -1
  270. package/lib/network/reqresp/handlers/blobSidecarsByRange.js +11 -5
  271. package/lib/network/reqresp/handlers/blobSidecarsByRange.js.map +1 -1
  272. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
  273. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +17 -5
  274. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
  275. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -1
  276. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +7 -4
  277. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
  278. package/lib/network/reqresp/handlers/index.d.ts.map +1 -1
  279. package/lib/network/reqresp/handlers/index.js +5 -0
  280. package/lib/network/reqresp/handlers/index.js.map +1 -1
  281. package/lib/network/reqresp/interface.d.ts +1 -1
  282. package/lib/network/reqresp/interface.js +1 -1
  283. package/lib/network/reqresp/protocols.d.ts +1 -0
  284. package/lib/network/reqresp/protocols.d.ts.map +1 -1
  285. package/lib/network/reqresp/protocols.js +5 -0
  286. package/lib/network/reqresp/protocols.js.map +1 -1
  287. package/lib/network/reqresp/rateLimit.d.ts.map +1 -1
  288. package/lib/network/reqresp/rateLimit.js +4 -0
  289. package/lib/network/reqresp/rateLimit.js.map +1 -1
  290. package/lib/network/reqresp/score.d.ts.map +1 -1
  291. package/lib/network/reqresp/score.js +1 -0
  292. package/lib/network/reqresp/score.js.map +1 -1
  293. package/lib/network/reqresp/types.d.ts +3 -0
  294. package/lib/network/reqresp/types.d.ts.map +1 -1
  295. package/lib/network/reqresp/types.js +3 -0
  296. package/lib/network/reqresp/types.js.map +1 -1
  297. package/lib/node/nodejs.d.ts.map +1 -1
  298. package/lib/node/nodejs.js +6 -4
  299. package/lib/node/nodejs.js.map +1 -1
  300. package/lib/sync/constants.d.ts +7 -1
  301. package/lib/sync/constants.d.ts.map +1 -1
  302. package/lib/sync/constants.js +7 -4
  303. package/lib/sync/constants.js.map +1 -1
  304. package/lib/sync/range/batch.d.ts +55 -8
  305. package/lib/sync/range/batch.d.ts.map +1 -1
  306. package/lib/sync/range/batch.js +291 -66
  307. package/lib/sync/range/batch.js.map +1 -1
  308. package/lib/sync/range/chain.d.ts +22 -4
  309. package/lib/sync/range/chain.d.ts.map +1 -1
  310. package/lib/sync/range/chain.js +103 -11
  311. package/lib/sync/range/chain.js.map +1 -1
  312. package/lib/sync/range/range.d.ts.map +1 -1
  313. package/lib/sync/range/range.js +71 -11
  314. package/lib/sync/range/range.js.map +1 -1
  315. package/lib/sync/range/utils/peerBalancer.d.ts +2 -1
  316. package/lib/sync/range/utils/peerBalancer.d.ts.map +1 -1
  317. package/lib/sync/range/utils/peerBalancer.js +8 -4
  318. package/lib/sync/range/utils/peerBalancer.js.map +1 -1
  319. package/lib/sync/sync.d.ts.map +1 -1
  320. package/lib/sync/sync.js +13 -0
  321. package/lib/sync/sync.js.map +1 -1
  322. package/lib/sync/types.d.ts +34 -0
  323. package/lib/sync/types.d.ts.map +1 -1
  324. package/lib/sync/types.js +34 -0
  325. package/lib/sync/types.js.map +1 -1
  326. package/lib/sync/unknownBlock.d.ts +29 -1
  327. package/lib/sync/unknownBlock.d.ts.map +1 -1
  328. package/lib/sync/unknownBlock.js +727 -61
  329. package/lib/sync/unknownBlock.js.map +1 -1
  330. package/lib/sync/utils/downloadByRange.d.ts +73 -10
  331. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  332. package/lib/sync/utils/downloadByRange.js +213 -26
  333. package/lib/sync/utils/downloadByRange.js.map +1 -1
  334. package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
  335. package/lib/sync/utils/downloadByRoot.js +16 -2
  336. package/lib/sync/utils/downloadByRoot.js.map +1 -1
  337. package/lib/sync/utils/pendingBlocksTree.d.ts +0 -1
  338. package/lib/sync/utils/pendingBlocksTree.d.ts.map +1 -1
  339. package/lib/sync/utils/pendingBlocksTree.js +0 -9
  340. package/lib/sync/utils/pendingBlocksTree.js.map +1 -1
  341. package/lib/sync/utils/rateLimit.d.ts +2 -0
  342. package/lib/sync/utils/rateLimit.d.ts.map +1 -0
  343. package/lib/sync/utils/rateLimit.js +15 -0
  344. package/lib/sync/utils/rateLimit.js.map +1 -0
  345. package/lib/util/sszBytes.d.ts.map +1 -1
  346. package/lib/util/sszBytes.js +20 -5
  347. package/lib/util/sszBytes.js.map +1 -1
  348. package/package.json +18 -17
  349. package/src/api/impl/beacon/blocks/index.ts +22 -9
  350. package/src/api/impl/beacon/pool/index.ts +83 -1
  351. package/src/api/impl/beacon/state/utils.ts +2 -2
  352. package/src/api/impl/debug/index.ts +0 -1
  353. package/src/api/impl/lodestar/index.ts +1 -1
  354. package/src/api/impl/validator/index.ts +84 -6
  355. package/src/chain/GetBlobsTracker.ts +1 -2
  356. package/src/chain/archiveStore/archiveStore.ts +5 -5
  357. package/src/chain/archiveStore/interface.ts +4 -4
  358. package/src/chain/archiveStore/strategies/frequencyStateArchiveStrategy.ts +6 -8
  359. package/src/chain/archiveStore/utils/archiveBlocks.ts +153 -94
  360. package/src/chain/blocks/blockInput/blockInput.ts +4 -1
  361. package/src/chain/blocks/importBlock.ts +38 -83
  362. package/src/chain/blocks/importExecutionPayload.ts +127 -107
  363. package/src/chain/blocks/index.ts +72 -24
  364. package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +64 -3
  365. package/src/chain/blocks/payloadEnvelopeInput/types.ts +18 -0
  366. package/src/chain/blocks/payloadEnvelopeProcessor.ts +7 -6
  367. package/src/chain/blocks/types.ts +16 -26
  368. package/src/chain/blocks/utils/chainSegment.ts +117 -17
  369. package/src/chain/blocks/verifyBlock.ts +70 -9
  370. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +6 -4
  371. package/src/chain/blocks/verifyBlocksSanityChecks.ts +26 -7
  372. package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +137 -0
  373. package/src/chain/blocks/verifyPayloadsDataAvailability.ts +41 -0
  374. package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +9 -18
  375. package/src/chain/chain.ts +79 -71
  376. package/src/chain/emitter.ts +15 -14
  377. package/src/chain/errors/attestationError.ts +6 -1
  378. package/src/chain/errors/blockError.ts +4 -1
  379. package/src/chain/errors/executionPayloadBid.ts +6 -0
  380. package/src/chain/errors/executionPayloadEnvelope.ts +6 -0
  381. package/src/chain/errors/index.ts +1 -0
  382. package/src/chain/errors/proposerPreferences.ts +47 -0
  383. package/src/chain/forkChoice/index.ts +8 -20
  384. package/src/chain/initState.ts +9 -1
  385. package/src/chain/interface.ts +11 -3
  386. package/src/chain/opPools/payloadAttestationPool.ts +29 -8
  387. package/src/chain/prepareNextSlot.ts +55 -24
  388. package/src/chain/produceBlock/computeNewStateRoot.ts +6 -43
  389. package/src/chain/produceBlock/produceBlockBody.ts +91 -27
  390. package/src/chain/regen/errors.ts +1 -6
  391. package/src/chain/regen/interface.ts +7 -12
  392. package/src/chain/regen/queued.ts +14 -55
  393. package/src/chain/regen/regen.ts +10 -43
  394. package/src/chain/seenCache/index.ts +1 -0
  395. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +89 -21
  396. package/src/chain/seenCache/seenProposerPreferences.ts +32 -0
  397. package/src/chain/stateCache/datastore/db.ts +10 -33
  398. package/src/chain/stateCache/datastore/file.ts +5 -6
  399. package/src/chain/stateCache/datastore/types.ts +2 -3
  400. package/src/chain/stateCache/fifoBlockStateCache.ts +1 -10
  401. package/src/chain/stateCache/persistentCheckpointsCache.ts +139 -247
  402. package/src/chain/stateCache/types.ts +8 -14
  403. package/src/chain/validation/aggregateAndProof.ts +13 -0
  404. package/src/chain/validation/attestation.ts +13 -0
  405. package/src/chain/validation/block.ts +1 -0
  406. package/src/chain/validation/executionPayloadBid.ts +25 -8
  407. package/src/chain/validation/executionPayloadEnvelope.ts +22 -12
  408. package/src/chain/validation/payloadAttestationMessage.ts +5 -3
  409. package/src/chain/validation/proposerPreferences.ts +110 -0
  410. package/src/db/repositories/executionPayloadEnvelopeArchive.ts +1 -1
  411. package/src/execution/engine/http.ts +21 -14
  412. package/src/execution/engine/interface.ts +1 -0
  413. package/src/execution/engine/mock.ts +8 -1
  414. package/src/execution/engine/types.ts +41 -0
  415. package/src/metrics/metrics/lodestar.ts +10 -0
  416. package/src/network/gossip/interface.ts +6 -0
  417. package/src/network/gossip/scoringParameters.ts +14 -1
  418. package/src/network/gossip/topic.ts +6 -0
  419. package/src/network/interface.ts +2 -0
  420. package/src/network/network.ts +24 -1
  421. package/src/network/processor/gossipHandlers.ts +114 -28
  422. package/src/network/processor/gossipQueues/index.ts +5 -0
  423. package/src/network/processor/index.ts +6 -5
  424. package/src/network/reqresp/ReqRespBeaconNode.ts +1 -0
  425. package/src/network/reqresp/handlers/beaconBlocksByHead.ts +91 -0
  426. package/src/network/reqresp/handlers/beaconBlocksByRange.ts +14 -6
  427. package/src/network/reqresp/handlers/blobSidecarsByRange.ts +11 -5
  428. package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +17 -5
  429. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +7 -4
  430. package/src/network/reqresp/handlers/index.ts +5 -0
  431. package/src/network/reqresp/interface.ts +1 -1
  432. package/src/network/reqresp/protocols.ts +6 -0
  433. package/src/network/reqresp/rateLimit.ts +4 -0
  434. package/src/network/reqresp/score.ts +1 -0
  435. package/src/network/reqresp/types.ts +5 -0
  436. package/src/node/nodejs.ts +6 -4
  437. package/src/sync/constants.ts +8 -4
  438. package/src/sync/range/batch.ts +388 -75
  439. package/src/sync/range/chain.ts +131 -14
  440. package/src/sync/range/range.ts +86 -11
  441. package/src/sync/range/utils/peerBalancer.ts +9 -3
  442. package/src/sync/sync.ts +13 -1
  443. package/src/sync/types.ts +72 -0
  444. package/src/sync/unknownBlock.ts +915 -65
  445. package/src/sync/utils/downloadByRange.ts +386 -39
  446. package/src/sync/utils/downloadByRoot.ts +24 -2
  447. package/src/sync/utils/pendingBlocksTree.ts +0 -15
  448. package/src/sync/utils/rateLimit.ts +16 -0
  449. package/src/util/sszBytes.ts +25 -5
@@ -1,9 +1,10 @@
1
1
  import {ChainForkConfig} from "@lodestar/config";
2
- import {Epoch, Root, Slot} from "@lodestar/types";
3
- import {ErrorAborted, LodestarError, Logger, toRootHex} from "@lodestar/utils";
2
+ import {Epoch, Root, Slot, gloas} from "@lodestar/types";
3
+ import {ErrorAborted, LodestarError, Logger, prettyPrintIndices, toRootHex} from "@lodestar/utils";
4
4
  import {isBlockInputBlobs, isBlockInputColumns} from "../../chain/blocks/blockInput/blockInput.js";
5
5
  import {BlockInputErrorCode} from "../../chain/blocks/blockInput/errors.js";
6
6
  import {IBlockInput} from "../../chain/blocks/blockInput/types.js";
7
+ import {PayloadEnvelopeInput} from "../../chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js";
7
8
  import {BlobSidecarErrorCode} from "../../chain/errors/blobSidecarError.js";
8
9
  import {DataColumnSidecarErrorCode} from "../../chain/errors/dataColumnSidecarError.js";
9
10
  import {Metrics} from "../../metrics/metrics.js";
@@ -16,6 +17,7 @@ import {PeerIdStr} from "../../util/peerId.js";
16
17
  import {WarnResult, wrapError} from "../../util/wrapError.js";
17
18
  import {BATCH_BUFFER_SIZE, EPOCHS_PER_BATCH, MAX_LOOK_AHEAD_EPOCHS} from "../constants.js";
18
19
  import {DownloadByRangeError, DownloadByRangeErrorCode} from "../utils/downloadByRange.js";
20
+ import {getRateLimitedUntilMs} from "../utils/rateLimit.js";
19
21
  import {RangeSyncType} from "../utils/remoteSyncType.js";
20
22
  import {Batch, BatchError, BatchErrorCode, BatchMetadata, BatchStatus} from "./batch.js";
21
23
  import {
@@ -44,13 +46,19 @@ export type SyncChainFns = {
44
46
  * Must return if ALL blocks are processed successfully
45
47
  * If SOME blocks are processed must throw BlockProcessorError()
46
48
  */
47
- processChainSegment: (blocks: IBlockInput[], syncType: RangeSyncType) => Promise<void>;
49
+ processChainSegment: (
50
+ blocks: IBlockInput[],
51
+ payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
52
+ syncType: RangeSyncType
53
+ ) => Promise<void>;
48
54
  /** Must download blocks, and validate their range */
49
55
  downloadByRange: (
50
56
  peer: PeerSyncMeta,
51
57
  batch: Batch,
52
58
  syncType: RangeSyncType
53
- ) => Promise<WarnResult<IBlockInput[], DownloadByRangeError>>;
59
+ ) => Promise<
60
+ WarnResult<{blocks: IBlockInput[]; payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null}, DownloadByRangeError>
61
+ >;
54
62
  /** Report peer for negative actions. Decouples from the full network instance */
55
63
  reportPeer: (peer: PeerIdStr, action: PeerAction, actionName: string) => void;
56
64
  /** Gets current peer custodyColumns and earliestAvailableSlot */
@@ -132,20 +140,33 @@ export class SyncChain {
132
140
  private readonly batchProcessor = new ItTrigger();
133
141
  /** Sorted map of batches undergoing some kind of processing. */
134
142
  private readonly batches = new Map<Epoch, Batch>();
143
+ /**
144
+ * `true` until the first `Batch` is constructed via `includeNextBatch`
145
+ */
146
+ private isFirstBatch = true;
135
147
  private readonly peerset = new Map<PeerIdStr, ChainTarget>();
148
+ /**
149
+ * Tracks peers that have rate-limited us, mapped to the timestamp (ms) until which we should avoid them.
150
+ * This is a sync-layer optimization to avoid assigning batches to backed-off peers.
151
+ * The reqresp SelfRateLimiter independently enforces backoff at the protocol level as a safety net.
152
+ */
153
+ private readonly rateLimitedPeers = new Map<PeerIdStr, number>();
154
+ private rateLimitBackoffTimeout: NodeJS.Timeout | undefined;
136
155
 
137
156
  private readonly logger: Logger;
138
157
  private readonly config: ChainForkConfig;
139
158
  private readonly clock: IClock;
140
159
  private readonly metrics: Metrics | null;
141
160
  private readonly custodyConfig: CustodyConfig;
161
+ private readonly latestBid: gloas.ExecutionPayloadBid | undefined;
142
162
 
143
163
  constructor(
144
164
  initialBatchEpoch: Epoch,
145
165
  initialTarget: ChainTarget,
146
166
  syncType: RangeSyncType,
147
167
  fns: SyncChainFns,
148
- modules: SyncChainModules
168
+ modules: SyncChainModules,
169
+ latestBid: gloas.ExecutionPayloadBid | undefined
149
170
  ) {
150
171
  const {config, clock, custodyConfig, logger, metrics} = modules;
151
172
  this.firstBatchEpoch = initialBatchEpoch;
@@ -161,6 +182,7 @@ export class SyncChain {
161
182
  this.clock = clock;
162
183
  this.metrics = metrics;
163
184
  this.custodyConfig = custodyConfig;
185
+ this.latestBid = latestBid;
164
186
  this.logger = logger;
165
187
  this.logId = `${syncType}-${nextChainId++}`;
166
188
 
@@ -215,12 +237,16 @@ export class SyncChain {
215
237
  */
216
238
  stopSyncing(): void {
217
239
  this.status = SyncChainStatus.Stopped;
240
+ this.clearRateLimitBackoffTimer();
241
+ this.logger.debug("SyncChain stopSyncing", {id: this.logId});
218
242
  }
219
243
 
220
244
  /**
221
245
  * Permanently remove this chain. Throws the main AsyncIterable
222
246
  */
223
247
  remove(): void {
248
+ this.logger.debug("SyncChain remove", {id: this.logId});
249
+ this.clearRateLimitBackoffTimer();
224
250
  this.batchProcessor.end(new ErrorAborted("SyncChain"));
225
251
  }
226
252
 
@@ -239,6 +265,7 @@ export class SyncChain {
239
265
  */
240
266
  removePeer(peerId: PeerIdStr): boolean {
241
267
  const deleted = this.peerset.delete(peerId);
268
+ this.rateLimitedPeers.delete(peerId);
242
269
  this.computeTarget();
243
270
  return deleted;
244
271
  }
@@ -342,6 +369,8 @@ export class SyncChain {
342
369
  }
343
370
 
344
371
  throw e;
372
+ } finally {
373
+ this.clearRateLimitBackoffTimer();
345
374
  }
346
375
  }
347
376
 
@@ -365,6 +394,44 @@ export class SyncChain {
365
394
  }
366
395
  }
367
396
 
397
+ private scheduleRateLimitBackoffRetry(): void {
398
+ this.clearRateLimitBackoffTimer();
399
+
400
+ if (this.status !== SyncChainStatus.Syncing || this.rateLimitedPeers.size === 0) {
401
+ return;
402
+ }
403
+
404
+ const now = Date.now();
405
+ let retryAt: number | null = null;
406
+ for (const [peerId, rateLimitedUntil] of this.rateLimitedPeers.entries()) {
407
+ if (rateLimitedUntil <= now) {
408
+ this.rateLimitedPeers.delete(peerId);
409
+ continue;
410
+ }
411
+ retryAt = Math.min(retryAt ?? rateLimitedUntil, rateLimitedUntil);
412
+ }
413
+
414
+ if (retryAt === null) {
415
+ return;
416
+ }
417
+
418
+ this.rateLimitBackoffTimeout = setTimeout(
419
+ () => {
420
+ this.rateLimitBackoffTimeout = undefined;
421
+ this.triggerBatchDownloader();
422
+ this.scheduleRateLimitBackoffRetry();
423
+ },
424
+ Math.max(0, retryAt - now)
425
+ );
426
+ }
427
+
428
+ private clearRateLimitBackoffTimer(): void {
429
+ if (this.rateLimitBackoffTimeout !== undefined) {
430
+ clearTimeout(this.rateLimitBackoffTimeout);
431
+ this.rateLimitBackoffTimeout = undefined;
432
+ }
433
+ }
434
+
368
435
  /**
369
436
  * Attempts to request the next required batches from the peer pool if the chain is syncing.
370
437
  * It will exhaust the peer pool and left over batches until the batch buffer is reached.
@@ -374,8 +441,18 @@ export class SyncChain {
374
441
  return;
375
442
  }
376
443
 
444
+ const now = Date.now();
377
445
  const peersSyncInfo: PeerSyncInfo[] = [];
378
446
  for (const [peerId, target] of this.peerset.entries()) {
447
+ // Skip peers that are currently in rate-limit backoff
448
+ const rateLimitedUntil = this.rateLimitedPeers.get(peerId);
449
+ if (rateLimitedUntil !== undefined) {
450
+ if (now < rateLimitedUntil) {
451
+ continue;
452
+ }
453
+ this.rateLimitedPeers.delete(peerId);
454
+ }
455
+
379
456
  try {
380
457
  peersSyncInfo.push({...this.getConnectedPeerSyncMeta(peerId), target});
381
458
  } catch (e) {
@@ -449,7 +526,17 @@ export class SyncChain {
449
526
  return null;
450
527
  }
451
528
 
452
- const batch = new Batch(startEpoch, this.config, this.clock, this.custodyConfig);
529
+ const batch = new Batch(
530
+ startEpoch,
531
+ this.config,
532
+ this.clock,
533
+ this.custodyConfig,
534
+ this.isFirstBatch,
535
+ // `latestBid` is only meaningful for the first batch's parent-payload check
536
+ this.isFirstBatch ? this.latestBid : undefined,
537
+ this.target.slot
538
+ );
539
+ this.isFirstBatch = false;
453
540
  this.batches.set(startEpoch, batch);
454
541
  return batch;
455
542
  }
@@ -464,7 +551,7 @@ export class SyncChain {
464
551
  peer: prettyPrintPeerIdStr(peer.peerId),
465
552
  });
466
553
  try {
467
- batch.startDownloading(peer.peerId);
554
+ batch.startDownloading(peer);
468
555
 
469
556
  // wrapError ensures to never call both batch success() and batch error()
470
557
  const res = await wrapError(this.downloadByRange(peer, batch, this.syncType));
@@ -494,6 +581,8 @@ export class SyncChain {
494
581
  case DownloadByRangeErrorCode.OUT_OF_ORDER_BLOCKS:
495
582
  case DownloadByRangeErrorCode.OUT_OF_RANGE_BLOCKS:
496
583
  case DownloadByRangeErrorCode.PARENT_ROOT_MISMATCH:
584
+ case DownloadByRangeErrorCode.INVALID_ENVELOPE_BEACON_BLOCK_ROOT:
585
+ case DownloadByRangeErrorCode.INVALID_CHAIN_SEGMENT:
497
586
  case BlobSidecarErrorCode.INCLUSION_PROOF_INVALID:
498
587
  case BlobSidecarErrorCode.INVALID_KZG_PROOF_BATCH:
499
588
  case DataColumnSidecarErrorCode.INCORRECT_KZG_COMMITMENTS_COUNT:
@@ -507,7 +596,16 @@ export class SyncChain {
507
596
  {id: this.logId, ...batch.getMetadata(), peer: prettyPrintPeerIdStr(peer.peerId)},
508
597
  res.err
509
598
  );
510
- batch.downloadingError(peer.peerId); // Throws after MAX_DOWNLOAD_ATTEMPTS
599
+ const rateLimitedUntilMs = getRateLimitedUntilMs(res.err);
600
+ if (rateLimitedUntilMs !== null) {
601
+ // Peer rate-limited us — don't count as a failed download attempt and mark peer for backoff
602
+ this.rateLimitedPeers.set(peer.peerId, rateLimitedUntilMs);
603
+ this.scheduleRateLimitBackoffRetry();
604
+ batch.downloadingRateLimited();
605
+ this.triggerBatchDownloader();
606
+ } else {
607
+ batch.downloadingError(peer.peerId); // Throws after MAX_DOWNLOAD_ATTEMPTS
608
+ }
511
609
  } else {
512
610
  this.logger.verbose("Batch download success", {
513
611
  id: this.logId,
@@ -516,7 +614,8 @@ export class SyncChain {
516
614
  });
517
615
  this.metrics?.syncRange.downloadByRange.success.inc();
518
616
  const {warnings, result} = res.result;
519
- const downloadSuccessOutput = batch.downloadingSuccess(peer.peerId, result);
617
+ const {blocks: downloadedBlocks, payloadEnvelopes} = result;
618
+ const downloadSuccessOutput = batch.downloadingSuccess(peer.peerId, downloadedBlocks, payloadEnvelopes);
520
619
  const logMeta: Record<string, number> = {
521
620
  blockCount: downloadSuccessOutput.blocks.length,
522
621
  };
@@ -526,7 +625,7 @@ export class SyncChain {
526
625
  this.metrics?.syncRange.downloadByRange.warn.inc({client: peer.client, code: warning.type.code});
527
626
  this.logger.debug(
528
627
  "Batch downloaded with warning",
529
- {id: this.logId, epoch: batch.startEpoch, ...logMeta, peer: prettyPrintPeerIdStr(peer.peerId)},
628
+ {id: this.logId, ...batch.getMetadata(), ...logMeta, peer: prettyPrintPeerIdStr(peer.peerId)},
530
629
  warning
531
630
  );
532
631
  }
@@ -552,10 +651,17 @@ export class SyncChain {
552
651
  // the flow will continue to call triggerBatchDownloader() below
553
652
  }
554
653
 
654
+ const blockSlots = downloadSuccessOutput.blocks.map((b) => b.slot);
655
+ const envelopeSlots = downloadSuccessOutput.payloadEnvelopes
656
+ ? Array.from(downloadSuccessOutput.payloadEnvelopes.keys())
657
+ : null;
658
+
555
659
  this.logger.debug(logMessage, {
556
660
  id: this.logId,
557
- epoch: batch.startEpoch,
661
+ ...batch.getMetadata(),
558
662
  ...logMeta,
663
+ blockSlots: prettyPrintIndices(blockSlots),
664
+ ...(envelopeSlots ? {envelopeSlots: prettyPrintIndices(envelopeSlots)} : {}),
559
665
  peer: prettyPrintPeerIdStr(peer.peerId),
560
666
  });
561
667
  }
@@ -578,13 +684,24 @@ export class SyncChain {
578
684
  * Sends `batch` to the processor. Note: batch may be empty
579
685
  */
580
686
  private async processBatch(batch: Batch): Promise<void> {
581
- const blocks = batch.startProcessing();
687
+ const {blocks, payloadEnvelopes, peers} = batch.startProcessing();
688
+
689
+ const logCtx = {
690
+ id: this.logId,
691
+ ...batch.getMetadata(),
692
+ blockCount: blocks.length,
693
+ blockSlots: prettyPrintIndices(blocks.map((b) => b.slot)),
694
+ ...(payloadEnvelopes ? {envelopeSlots: prettyPrintIndices(Array.from(payloadEnvelopes.keys()))} : {}),
695
+ peers: peers.map(prettyPrintPeerIdStr).join(","),
696
+ };
697
+ this.logger.verbose("Processing batch", logCtx);
582
698
 
583
699
  // wrapError ensures to never call both batch success() and batch error()
584
- const res = await wrapError(this.processChainSegment(blocks, this.syncType));
700
+ const res = await wrapError(this.processChainSegment(blocks, payloadEnvelopes, this.syncType));
585
701
 
586
702
  if (!res.err) {
587
703
  batch.processingSuccess();
704
+ this.logger.verbose("Processed batch", {...logCtx, ...batch.getMetadata()});
588
705
 
589
706
  // If the processed batch is not empty, validate previous AwaitingValidation blocks.
590
707
  if (blocks.length > 0) {
@@ -594,7 +711,7 @@ export class SyncChain {
594
711
  // Potentially process next AwaitingProcessing batch
595
712
  this.triggerBatchProcessor();
596
713
  } else {
597
- this.logger.verbose("Batch process error", {id: this.logId, ...batch.getMetadata()}, res.err);
714
+ this.logger.verbose("Batch process error", logCtx, res.err);
598
715
  batch.processingError(res.err); // Throws after MAX_BATCH_PROCESSING_ATTEMPTS
599
716
 
600
717
  // At least one block was successfully verified and imported, so we can be sure all
@@ -1,16 +1,23 @@
1
1
  import {EventEmitter} from "node:events";
2
2
  import {StrictEventEmitter} from "strict-event-emitter-types";
3
3
  import {BeaconConfig} from "@lodestar/config";
4
- import {computeStartSlotAtEpoch} from "@lodestar/state-transition";
4
+ import {IBeaconStateViewGloas, computeStartSlotAtEpoch, isStatePostGloas} from "@lodestar/state-transition";
5
5
  import {Epoch, Status, fulu} from "@lodestar/types";
6
- import {Logger, toRootHex} from "@lodestar/utils";
6
+ import {Logger, prettyPrintIndices, toRootHex} from "@lodestar/utils";
7
7
  import {IBlockInput} from "../../chain/blocks/blockInput/types.js";
8
8
  import {AttestationImportOpt, ImportBlockOpts} from "../../chain/blocks/index.js";
9
+ import {assertLinearChainSegment} from "../../chain/blocks/utils/chainSegment.js";
10
+ import {BlockError} from "../../chain/errors/index.js";
9
11
  import {IBeaconChain} from "../../chain/index.js";
10
12
  import {Metrics} from "../../metrics/index.js";
11
13
  import {INetwork} from "../../network/index.js";
12
14
  import {PeerIdStr} from "../../util/peerId.js";
13
- import {cacheByRangeResponses, downloadByRange} from "../utils/downloadByRange.js";
15
+ import {
16
+ DownloadByRangeError,
17
+ DownloadByRangeErrorCode,
18
+ cacheByRangeResponses,
19
+ downloadByRange,
20
+ } from "../utils/downloadByRange.js";
14
21
  import {RangeSyncType, getRangeSyncTarget, rangeSyncTypes} from "../utils/remoteSyncType.js";
15
22
  import {ChainTarget, SyncChain, SyncChainDebugState, SyncChainFns} from "./chain.js";
16
23
  import {updateChains} from "./utils/index.js";
@@ -172,7 +179,7 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
172
179
  }
173
180
 
174
181
  /** Convenience method for `SyncChain` */
175
- private processChainSegment: SyncChainFns["processChainSegment"] = async (blocks, syncType) => {
182
+ private processChainSegment: SyncChainFns["processChainSegment"] = async (blocks, payloadEnvelopes, syncType) => {
176
183
  // Not trusted, verify signatures
177
184
  const flags: ImportBlockOpts = {
178
185
  // Only skip importing attestations for finalized sync. For head sync attestation are valuable.
@@ -192,30 +199,89 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
192
199
 
193
200
  if (this.opts?.disableProcessAsChainSegment) {
194
201
  // Should only be used for debugging or testing
195
- for (const block of blocks) await this.chain.processBlock(block, flags);
202
+ for (const block of blocks) {
203
+ await this.chain.processBlock(block, flags);
204
+ const payloadEnvelope = payloadEnvelopes?.get(block.slot);
205
+ if (payloadEnvelope) {
206
+ await this.chain.processExecutionPayload(payloadEnvelope);
207
+ }
208
+ }
196
209
  } else {
197
- await this.chain.processChainSegment(blocks, flags);
210
+ await this.chain.processChainSegment(blocks, payloadEnvelopes, flags);
198
211
  }
199
212
  };
200
213
 
201
214
  private downloadByRange: SyncChainFns["downloadByRange"] = async (peer, batch) => {
202
215
  const batchBlocks = batch.getBlocks();
216
+ const requests = batch.getRequestsForPeer(peer);
217
+ const parentRoot = requests.parentPayloadRequest?.envelopeBlockRoot ?? requests.parentPayloadRequest?.blockRoot;
218
+ const parentPayloadCommitments = parentRoot ? batch.getParentPayloadCommitments(parentRoot) : undefined;
203
219
  const {result, warnings} = await downloadByRange({
204
220
  config: this.config,
205
221
  network: this.network,
206
222
  logger: this.logger,
207
223
  peerIdStr: peer.peerId,
208
224
  batchBlocks,
225
+ parentPayloadCommitments,
209
226
  peerDasMetrics: this.chain.metrics?.peerDas,
210
- ...batch.getRequestsForPeer(peer),
227
+ ...requests,
211
228
  });
212
- const cached = cacheByRangeResponses({
229
+ const {responses, payloadEnvelopes: downloadedPayloadEnvelopes} = result;
230
+ const {blocks, payloadEnvelopes} = cacheByRangeResponses({
213
231
  cache: this.chain.seenBlockInputCache,
232
+ seenPayloadEnvelopeInputCache: this.chain.seenPayloadEnvelopeInputCache,
214
233
  peerIdStr: peer.peerId,
215
- responses: result,
234
+ responses,
216
235
  batchBlocks,
236
+ downloadedPayloadEnvelopes,
237
+ existingPayloadEnvelopes: batch.getPayloadEnvelopes(),
238
+ custodyConfig: this.chain.custodyConfig,
239
+ seenTimestampSec: Date.now() / 1000,
240
+ });
241
+
242
+ const segmentBlocks = blocks.filter((b) => b.hasBlock()).sort((a, b) => a.slot - b.slot);
243
+ const envelopeSlots = payloadEnvelopes
244
+ ? Array.from(payloadEnvelopes.entries())
245
+ .filter(([, pi]) => pi.hasPayloadEnvelope())
246
+ .map(([slot]) => slot)
247
+ .sort((a, b) => a - b)
248
+ : [];
249
+ this.logger.verbose("downloadByRange batch ready", {
250
+ peer: peer.peerId,
251
+ blockSlots: prettyPrintIndices(segmentBlocks.map((b) => b.slot)),
252
+ envelopeSlots: prettyPrintIndices(envelopeSlots),
253
+ ...batch.getMetadata(),
217
254
  });
218
- return {result: cached, warnings};
255
+
256
+ if (segmentBlocks.length > 1) {
257
+ try {
258
+ assertLinearChainSegment(this.config, segmentBlocks, payloadEnvelopes, null);
259
+ } catch (err) {
260
+ if (err instanceof BlockError) {
261
+ this.logger.debug(
262
+ "downloadByRange segment validation failed",
263
+ {
264
+ peer: peer.peerId,
265
+ reason: err.type.code,
266
+ slot: err.signedBlock.message.slot,
267
+ detail: JSON.stringify(err.type),
268
+ ...batch.getMetadata(),
269
+ },
270
+ err
271
+ );
272
+ // with this error, the peer will be penalized inside SyncChain
273
+ throw new DownloadByRangeError({
274
+ code: DownloadByRangeErrorCode.INVALID_CHAIN_SEGMENT,
275
+ slot: err.signedBlock.message.slot,
276
+ reason: err.type.code,
277
+ });
278
+ }
279
+
280
+ throw err;
281
+ }
282
+ }
283
+
284
+ return {result: {blocks, payloadEnvelopes}, warnings};
219
285
  };
220
286
 
221
287
  private pruneBlockInputs: SyncChainFns["pruneBlockInputs"] = (blocks: IBlockInput[]) => {
@@ -246,6 +312,14 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
246
312
  private addPeerOrCreateChain(startEpoch: Epoch, target: ChainTarget, peer: PeerIdStr, syncType: RangeSyncType): void {
247
313
  let syncChain = this.chains.get(syncType);
248
314
  if (!syncChain) {
315
+ // The first batch of a new sync chain may need to detect whether the parent block was an
316
+ // gloas "empty" block (no envelope produced). It does so by comparing the first
317
+ // downloaded block's `bid.parentBlockHash` against the head state's `latestExecutionPayloadBid.blockHash`.
318
+ const headState = this.chain.getHeadState();
319
+ const latestBid = isStatePostGloas(headState)
320
+ ? (headState as IBeaconStateViewGloas).latestExecutionPayloadBid
321
+ : undefined;
322
+
249
323
  syncChain = new SyncChain(
250
324
  startEpoch,
251
325
  target,
@@ -264,7 +338,8 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
264
338
  logger: this.logger,
265
339
  custodyConfig: this.chain.custodyConfig,
266
340
  metrics: this.metrics,
267
- }
341
+ },
342
+ latestBid
268
343
  );
269
344
  this.chains.set(syncType, syncChain);
270
345
 
@@ -52,7 +52,8 @@ export class ChainPeersBalancer {
52
52
 
53
53
  /**
54
54
  * Return the most suitable peer to retry
55
- * Sort peers by (1) no failed request (2) less active requests, then pick first
55
+ * Sort peers by (1) less active requests (2) most columns we need.
56
+ * Peers that failed this batch or already succeeded for the same request are excluded inside `filterPeers`.
56
57
  */
57
58
  bestPeerToRetryBatch(batch: Batch): PeerSyncMeta | undefined {
58
59
  if (batch.state.status !== BatchStatus.AwaitingDownload) {
@@ -63,10 +64,8 @@ export class ChainPeersBalancer {
63
64
  const pendingDataColumns = columnsRequest?.columns ?? this.custodyConfig.sampledColumns;
64
65
  const eligiblePeers = this.filterPeers(batch, pendingDataColumns, false);
65
66
 
66
- const failedPeers = new Set(batch.getFailedPeers());
67
67
  const sortedBestPeers = sortBy(
68
68
  eligiblePeers,
69
- ({syncInfo}) => (failedPeers.has(syncInfo.peerId) ? 1 : 0), // prefer peers without failed requests
70
69
  ({syncInfo}) => this.activeRequestsByPeer.get(syncInfo.peerId) ?? 0, // prefer peers with least active req
71
70
  ({columns}) => -1 * columns // prefer peers with the most columns
72
71
  );
@@ -117,9 +116,16 @@ export class ChainPeersBalancer {
117
116
  return eligiblePeers;
118
117
  }
119
118
 
119
+ // Skip peers that failed this batch, or that already returned the exact current request shape.
120
+ const failedPeers = new Set<PeerIdStr>(batch.getFailedPeers());
121
+
120
122
  for (const peer of this.peers) {
121
123
  const {earliestAvailableSlot, target, peerId} = peer;
122
124
 
125
+ if (failedPeers.has(peerId) || batch.hasPeerSucceededCurrentRequest(peer)) {
126
+ continue;
127
+ }
128
+
123
129
  const activeRequest = this.activeRequestsByPeer.get(peerId) ?? 0;
124
130
  if (noActiveRequest && activeRequest > 0) {
125
131
  // consumer wants to find peer with no active request, but this peer has active request
package/src/sync/sync.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import {SLOTS_PER_EPOCH} from "@lodestar/params";
2
2
  import {Slot} from "@lodestar/types";
3
- import {Logger} from "@lodestar/utils";
3
+ import {Logger, toRootHex} from "@lodestar/utils";
4
4
  import {IBeaconChain} from "../chain/index.js";
5
5
  import {GENESIS_SLOT} from "../constants/constants.js";
6
6
  import {ExecutionEngineState} from "../execution/index.js";
@@ -188,6 +188,18 @@ export class BeaconSync implements IBeaconSync {
188
188
  private addPeer = (data: NetworkEventData[NetworkEvent.peerConnected]): void => {
189
189
  const localStatus = this.chain.getStatus();
190
190
  const syncType = getPeerSyncType(localStatus, data.status, this.chain.forkChoice, this.slotImportTolerance);
191
+ this.logger.verbose("Peer sync type classified", {
192
+ peer: data.peer,
193
+ syncType,
194
+ localFinalizedEpoch: localStatus.finalizedEpoch,
195
+ localFinalizedRoot: toRootHex(localStatus.finalizedRoot),
196
+ localHeadSlot: localStatus.headSlot,
197
+ localHeadRoot: toRootHex(localStatus.headRoot),
198
+ remoteFinalizedEpoch: data.status.finalizedEpoch,
199
+ remoteFinalizedRoot: toRootHex(data.status.finalizedRoot),
200
+ remoteHeadSlot: data.status.headSlot,
201
+ remoteHeadRoot: toRootHex(data.status.headRoot),
202
+ });
191
203
 
192
204
  // For metrics only
193
205
  this.peerSyncType.set(data.peer, syncType);
package/src/sync/types.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  import {RootHex, Slot} from "@lodestar/types";
2
+ import {SignedExecutionPayloadEnvelope} from "@lodestar/types/gloas";
3
+ import {toRootHex} from "@lodestar/utils";
2
4
  import {IBlockInput} from "../chain/blocks/blockInput/index.js";
5
+ import {PayloadEnvelopeInput} from "../chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js";
3
6
 
4
7
  export enum PendingBlockType {
5
8
  /**
@@ -26,6 +29,14 @@ export enum PendingBlockInputStatus {
26
29
  processing = "processing",
27
30
  }
28
31
 
32
+ export enum PendingPayloadInputStatus {
33
+ pending = "pending",
34
+ fetching = "fetching",
35
+ waitingForBlock = "waiting_for_block",
36
+ downloaded = "downloaded",
37
+ processing = "processing",
38
+ }
39
+
29
40
  export type PendingBlockInput = {
30
41
  status: PendingBlockInputStatus;
31
42
  blockInput: IBlockInput;
@@ -44,10 +55,47 @@ export type PendingRootHex = {
44
55
 
45
56
  export type BlockInputSyncCacheItem = PendingBlockInput | PendingRootHex;
46
57
 
58
+ export type PendingPayloadInput = {
59
+ status:
60
+ | PendingPayloadInputStatus.pending
61
+ | PendingPayloadInputStatus.fetching
62
+ | PendingPayloadInputStatus.downloaded
63
+ | PendingPayloadInputStatus.processing;
64
+ payloadInput: PayloadEnvelopeInput;
65
+ timeAddedSec: number;
66
+ timeSyncedSec?: number;
67
+ peerIdStrings: Set<string>;
68
+ };
69
+
70
+ export type PendingPayloadRootHex = {
71
+ status: PendingPayloadInputStatus.pending | PendingPayloadInputStatus.fetching;
72
+ rootHex: RootHex;
73
+ timeAddedSec: number;
74
+ timeSyncedSec?: number;
75
+ peerIdStrings: Set<string>;
76
+ };
77
+
78
+ export type PendingPayloadEnvelope = {
79
+ status: PendingPayloadInputStatus.waitingForBlock;
80
+ envelope: SignedExecutionPayloadEnvelope;
81
+ timeAddedSec: number;
82
+ peerIdStrings: Set<string>;
83
+ };
84
+
85
+ export type PayloadSyncCacheItem = PendingPayloadInput | PendingPayloadRootHex | PendingPayloadEnvelope;
86
+
47
87
  export function isPendingBlockInput(pending: BlockInputSyncCacheItem): pending is PendingBlockInput {
48
88
  return "blockInput" in pending;
49
89
  }
50
90
 
91
+ export function isPendingPayloadInput(pending: PayloadSyncCacheItem): pending is PendingPayloadInput {
92
+ return "payloadInput" in pending;
93
+ }
94
+
95
+ export function isPendingPayloadEnvelope(pending: PayloadSyncCacheItem): pending is PendingPayloadEnvelope {
96
+ return "envelope" in pending;
97
+ }
98
+
51
99
  export function getBlockInputSyncCacheItemRootHex(block: BlockInputSyncCacheItem): RootHex {
52
100
  return isPendingBlockInput(block) ? block.blockInput.blockRootHex : block.rootHex;
53
101
  }
@@ -55,3 +103,27 @@ export function getBlockInputSyncCacheItemRootHex(block: BlockInputSyncCacheItem
55
103
  export function getBlockInputSyncCacheItemSlot(block: BlockInputSyncCacheItem): Slot | string {
56
104
  return isPendingBlockInput(block) ? block.blockInput.slot : "unknown";
57
105
  }
106
+
107
+ export function getPayloadSyncCacheItemRootHex(payload: PayloadSyncCacheItem): RootHex {
108
+ if (isPendingPayloadInput(payload)) {
109
+ return payload.payloadInput.blockRootHex;
110
+ }
111
+
112
+ if (isPendingPayloadEnvelope(payload)) {
113
+ return toRootHex(payload.envelope.message.beaconBlockRoot);
114
+ }
115
+
116
+ return payload.rootHex;
117
+ }
118
+
119
+ export function getPayloadSyncCacheItemSlot(payload: PayloadSyncCacheItem): Slot | string {
120
+ if (isPendingPayloadInput(payload)) {
121
+ return payload.payloadInput.slot;
122
+ }
123
+
124
+ if (isPendingPayloadEnvelope(payload)) {
125
+ return payload.envelope.message.payload.slotNumber;
126
+ }
127
+
128
+ return "unknown";
129
+ }