@lodestar/beacon-node 1.50.0-dev.033e6b7138 → 1.50.0-dev.03c05fa09a

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 (411) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +13 -3
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/beacon/index.d.ts.map +1 -1
  5. package/lib/api/impl/beacon/index.js +13 -0
  6. package/lib/api/impl/beacon/index.js.map +1 -1
  7. package/lib/api/impl/beacon/pool/index.js +4 -4
  8. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  9. package/lib/api/impl/beacon/state/index.d.ts.map +1 -1
  10. package/lib/api/impl/beacon/state/index.js +28 -6
  11. package/lib/api/impl/beacon/state/index.js.map +1 -1
  12. package/lib/api/impl/debug/index.d.ts.map +1 -1
  13. package/lib/api/impl/debug/index.js +26 -18
  14. package/lib/api/impl/debug/index.js.map +1 -1
  15. package/lib/api/impl/validator/index.d.ts +1 -0
  16. package/lib/api/impl/validator/index.d.ts.map +1 -1
  17. package/lib/api/impl/validator/index.js +80 -18
  18. package/lib/api/impl/validator/index.js.map +1 -1
  19. package/lib/chain/ColumnReconstructionTracker.d.ts +0 -2
  20. package/lib/chain/ColumnReconstructionTracker.d.ts.map +1 -1
  21. package/lib/chain/ColumnReconstructionTracker.js +4 -5
  22. package/lib/chain/ColumnReconstructionTracker.js.map +1 -1
  23. package/lib/chain/archiveStore/archiveStore.d.ts +6 -0
  24. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  25. package/lib/chain/archiveStore/archiveStore.js +18 -24
  26. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  27. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts +2 -2
  28. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
  29. package/lib/chain/archiveStore/historicalState/getHistoricalState.js +5 -7
  30. package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
  31. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -1
  32. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
  33. package/lib/chain/archiveStore/historicalState/types.d.ts +2 -2
  34. package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
  35. package/lib/chain/archiveStore/historicalState/worker.js +1 -1
  36. package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
  37. package/lib/chain/archiveStore/interface.d.ts +1 -1
  38. package/lib/chain/archiveStore/interface.d.ts.map +1 -1
  39. package/lib/chain/archiveStore/utils/pruneHistory.d.ts +4 -1
  40. package/lib/chain/archiveStore/utils/pruneHistory.d.ts.map +1 -1
  41. package/lib/chain/archiveStore/utils/pruneHistory.js +5 -3
  42. package/lib/chain/archiveStore/utils/pruneHistory.js.map +1 -1
  43. package/lib/chain/beaconProposerCache.d.ts +6 -0
  44. package/lib/chain/beaconProposerCache.d.ts.map +1 -1
  45. package/lib/chain/beaconProposerCache.js +16 -0
  46. package/lib/chain/beaconProposerCache.js.map +1 -1
  47. package/lib/chain/blocks/blockInput/blockInput.d.ts +1 -1
  48. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  49. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  50. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  51. package/lib/chain/blocks/importBlock.js +25 -12
  52. package/lib/chain/blocks/importBlock.js.map +1 -1
  53. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +2 -1
  54. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
  55. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  56. package/lib/chain/blocks/verifyBlock.js +7 -7
  57. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  58. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts +2 -1
  59. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts.map +1 -1
  60. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js +5 -4
  61. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js.map +1 -1
  62. package/lib/chain/chain.d.ts +10 -5
  63. package/lib/chain/chain.d.ts.map +1 -1
  64. package/lib/chain/chain.js +108 -38
  65. package/lib/chain/chain.js.map +1 -1
  66. package/lib/chain/emitter.d.ts +7 -1
  67. package/lib/chain/emitter.d.ts.map +1 -1
  68. package/lib/chain/emitter.js +5 -0
  69. package/lib/chain/emitter.js.map +1 -1
  70. package/lib/chain/errors/envelopeReconstructionError.d.ts +5 -0
  71. package/lib/chain/errors/envelopeReconstructionError.d.ts.map +1 -1
  72. package/lib/chain/errors/envelopeReconstructionError.js +2 -0
  73. package/lib/chain/errors/envelopeReconstructionError.js.map +1 -1
  74. package/lib/chain/errors/gossipValidation.d.ts +3 -1
  75. package/lib/chain/errors/gossipValidation.d.ts.map +1 -1
  76. package/lib/chain/errors/gossipValidation.js +2 -0
  77. package/lib/chain/errors/gossipValidation.js.map +1 -1
  78. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  79. package/lib/chain/forkChoice/index.js +2 -0
  80. package/lib/chain/forkChoice/index.js.map +1 -1
  81. package/lib/chain/initState.d.ts +2 -9
  82. package/lib/chain/initState.d.ts.map +1 -1
  83. package/lib/chain/initState.js +5 -38
  84. package/lib/chain/initState.js.map +1 -1
  85. package/lib/chain/interface.d.ts +6 -3
  86. package/lib/chain/interface.d.ts.map +1 -1
  87. package/lib/chain/opPools/aggregatedAttestationPool.d.ts +4 -2
  88. package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
  89. package/lib/chain/opPools/aggregatedAttestationPool.js +30 -8
  90. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  91. package/lib/chain/opPools/opPool.d.ts +5 -4
  92. package/lib/chain/opPools/opPool.d.ts.map +1 -1
  93. package/lib/chain/opPools/opPool.js +60 -38
  94. package/lib/chain/opPools/opPool.js.map +1 -1
  95. package/lib/chain/opPools/proposerPreferencesPool.d.ts +8 -4
  96. package/lib/chain/opPools/proposerPreferencesPool.d.ts.map +1 -1
  97. package/lib/chain/opPools/proposerPreferencesPool.js +27 -12
  98. package/lib/chain/opPools/proposerPreferencesPool.js.map +1 -1
  99. package/lib/chain/opPools/utils.d.ts +15 -1
  100. package/lib/chain/opPools/utils.d.ts.map +1 -1
  101. package/lib/chain/opPools/utils.js +33 -1
  102. package/lib/chain/opPools/utils.js.map +1 -1
  103. package/lib/chain/options.d.ts +2 -1
  104. package/lib/chain/options.d.ts.map +1 -1
  105. package/lib/chain/options.js +1 -1
  106. package/lib/chain/options.js.map +1 -1
  107. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  108. package/lib/chain/prepareNextSlot.js +20 -8
  109. package/lib/chain/prepareNextSlot.js.map +1 -1
  110. package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
  111. package/lib/chain/produceBlock/computeNewStateRoot.js +1 -1
  112. package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
  113. package/lib/chain/produceBlock/produceBlockBody.d.ts +11 -1
  114. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  115. package/lib/chain/produceBlock/produceBlockBody.js +54 -36
  116. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  117. package/lib/chain/regen/regen.d.ts +2 -0
  118. package/lib/chain/regen/regen.d.ts.map +1 -1
  119. package/lib/chain/regen/regen.js +10 -4
  120. package/lib/chain/regen/regen.js.map +1 -1
  121. package/lib/chain/reprocess.d.ts +2 -1
  122. package/lib/chain/reprocess.d.ts.map +1 -1
  123. package/lib/chain/reprocess.js +2 -1
  124. package/lib/chain/reprocess.js.map +1 -1
  125. package/lib/chain/seenCache/seenGossipBlockInput.d.ts +7 -0
  126. package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
  127. package/lib/chain/seenCache/seenGossipBlockInput.js +22 -1
  128. package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
  129. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +9 -2
  130. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
  131. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +23 -13
  132. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
  133. package/lib/chain/shufflingCache.d.ts +18 -8
  134. package/lib/chain/shufflingCache.d.ts.map +1 -1
  135. package/lib/chain/shufflingCache.js +72 -18
  136. package/lib/chain/shufflingCache.js.map +1 -1
  137. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  138. package/lib/chain/stateCache/persistentCheckpointsCache.js +1 -1
  139. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  140. package/lib/chain/validation/attesterSlashing.d.ts +4 -4
  141. package/lib/chain/validation/attesterSlashing.d.ts.map +1 -1
  142. package/lib/chain/validation/attesterSlashing.js +3 -0
  143. package/lib/chain/validation/attesterSlashing.js.map +1 -1
  144. package/lib/chain/validation/proposerSlashing.d.ts +3 -3
  145. package/lib/chain/validation/proposerSlashing.d.ts.map +1 -1
  146. package/lib/chain/validation/proposerSlashing.js +3 -0
  147. package/lib/chain/validation/proposerSlashing.js.map +1 -1
  148. package/lib/chain/validatorMonitor.d.ts +5 -1
  149. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  150. package/lib/chain/validatorMonitor.js +70 -58
  151. package/lib/chain/validatorMonitor.js.map +1 -1
  152. package/lib/constants/constants.d.ts +1 -0
  153. package/lib/constants/constants.d.ts.map +1 -1
  154. package/lib/constants/constants.js +1 -0
  155. package/lib/constants/constants.js.map +1 -1
  156. package/lib/db/beacon.d.ts +4 -1
  157. package/lib/db/beacon.d.ts.map +1 -1
  158. package/lib/db/beacon.js +8 -1
  159. package/lib/db/beacon.js.map +1 -1
  160. package/lib/db/buckets.d.ts +3 -1
  161. package/lib/db/buckets.d.ts.map +1 -1
  162. package/lib/db/buckets.js +2 -0
  163. package/lib/db/buckets.js.map +1 -1
  164. package/lib/db/interface.d.ts +4 -1
  165. package/lib/db/interface.d.ts.map +1 -1
  166. package/lib/db/repositories/blockArchive.js +2 -2
  167. package/lib/db/repositories/blockArchive.js.map +1 -1
  168. package/lib/db/repositories/blockArchiveIndex.d.ts +3 -3
  169. package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
  170. package/lib/db/repositories/blockArchiveIndex.js +1 -2
  171. package/lib/db/repositories/blockArchiveIndex.js.map +1 -1
  172. package/lib/db/repositories/earliestAvailableSlot.d.ts +11 -0
  173. package/lib/db/repositories/earliestAvailableSlot.d.ts.map +1 -0
  174. package/lib/db/repositories/earliestAvailableSlot.js +19 -0
  175. package/lib/db/repositories/earliestAvailableSlot.js.map +1 -0
  176. package/lib/db/repositories/index.d.ts +1 -0
  177. package/lib/db/repositories/index.d.ts.map +1 -1
  178. package/lib/db/repositories/index.js +1 -0
  179. package/lib/db/repositories/index.js.map +1 -1
  180. package/lib/db/repositories/proposerPreferences.d.ts +14 -0
  181. package/lib/db/repositories/proposerPreferences.d.ts.map +1 -0
  182. package/lib/db/repositories/proposerPreferences.js +21 -0
  183. package/lib/db/repositories/proposerPreferences.js.map +1 -0
  184. package/lib/db/repositories/proposerSlashing.d.ts +1 -0
  185. package/lib/db/repositories/proposerSlashing.d.ts.map +1 -1
  186. package/lib/db/repositories/proposerSlashing.js +5 -1
  187. package/lib/db/repositories/proposerSlashing.js.map +1 -1
  188. package/lib/execution/engine/blobVersionedHashes.d.ts +9 -0
  189. package/lib/execution/engine/blobVersionedHashes.d.ts.map +1 -0
  190. package/lib/execution/engine/blobVersionedHashes.js +74 -0
  191. package/lib/execution/engine/blobVersionedHashes.js.map +1 -0
  192. package/lib/execution/engine/disabled.d.ts +0 -2
  193. package/lib/execution/engine/disabled.d.ts.map +1 -1
  194. package/lib/execution/engine/disabled.js +0 -6
  195. package/lib/execution/engine/disabled.js.map +1 -1
  196. package/lib/execution/engine/http.d.ts +46 -16
  197. package/lib/execution/engine/http.d.ts.map +1 -1
  198. package/lib/execution/engine/http.js +236 -213
  199. package/lib/execution/engine/http.js.map +1 -1
  200. package/lib/execution/engine/index.d.ts +3 -2
  201. package/lib/execution/engine/index.d.ts.map +1 -1
  202. package/lib/execution/engine/index.js +33 -8
  203. package/lib/execution/engine/index.js.map +1 -1
  204. package/lib/execution/engine/interface.d.ts +2 -4
  205. package/lib/execution/engine/interface.d.ts.map +1 -1
  206. package/lib/execution/engine/jsonRpcTransport.d.ts +25 -0
  207. package/lib/execution/engine/jsonRpcTransport.d.ts.map +1 -0
  208. package/lib/execution/engine/jsonRpcTransport.js +158 -0
  209. package/lib/execution/engine/jsonRpcTransport.js.map +1 -0
  210. package/lib/execution/engine/mock.d.ts +0 -2
  211. package/lib/execution/engine/mock.d.ts.map +1 -1
  212. package/lib/execution/engine/mock.js +0 -8
  213. package/lib/execution/engine/mock.js.map +1 -1
  214. package/lib/execution/engine/restHttpClient.d.ts +71 -0
  215. package/lib/execution/engine/restHttpClient.d.ts.map +1 -0
  216. package/lib/execution/engine/restHttpClient.js +201 -0
  217. package/lib/execution/engine/restHttpClient.js.map +1 -0
  218. package/lib/execution/engine/restTransport.d.ts +46 -0
  219. package/lib/execution/engine/restTransport.d.ts.map +1 -0
  220. package/lib/execution/engine/restTransport.js +399 -0
  221. package/lib/execution/engine/restTransport.js.map +1 -0
  222. package/lib/execution/engine/sszTypes.d.ts +1261 -0
  223. package/lib/execution/engine/sszTypes.d.ts.map +1 -0
  224. package/lib/execution/engine/sszTypes.js +216 -0
  225. package/lib/execution/engine/sszTypes.js.map +1 -0
  226. package/lib/execution/engine/transport.d.ts +39 -0
  227. package/lib/execution/engine/transport.d.ts.map +1 -0
  228. package/lib/execution/engine/transport.js +2 -0
  229. package/lib/execution/engine/transport.js.map +1 -0
  230. package/lib/execution/engine/types.d.ts +2 -8
  231. package/lib/execution/engine/types.d.ts.map +1 -1
  232. package/lib/execution/engine/types.js +31 -63
  233. package/lib/execution/engine/types.js.map +1 -1
  234. package/lib/execution/engine/utils.d.ts.map +1 -1
  235. package/lib/execution/engine/utils.js +9 -2
  236. package/lib/execution/engine/utils.js.map +1 -1
  237. package/lib/index.d.ts +1 -1
  238. package/lib/index.d.ts.map +1 -1
  239. package/lib/index.js +1 -1
  240. package/lib/index.js.map +1 -1
  241. package/lib/metrics/metrics/lodestar.d.ts +10 -0
  242. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  243. package/lib/metrics/metrics/lodestar.js +22 -0
  244. package/lib/metrics/metrics/lodestar.js.map +1 -1
  245. package/lib/metrics/metrics.d.ts +7 -3
  246. package/lib/metrics/metrics.d.ts.map +1 -1
  247. package/lib/metrics/metrics.js +4 -4
  248. package/lib/metrics/metrics.js.map +1 -1
  249. package/lib/network/core/events.d.ts +5 -1
  250. package/lib/network/core/events.d.ts.map +1 -1
  251. package/lib/network/core/events.js +8 -0
  252. package/lib/network/core/events.js.map +1 -1
  253. package/lib/network/gossip/topic.d.ts +0 -14
  254. package/lib/network/gossip/topic.d.ts.map +1 -1
  255. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  256. package/lib/network/processor/gossipHandlers.js +67 -68
  257. package/lib/network/processor/gossipHandlers.js.map +1 -1
  258. package/lib/network/processor/gossipValidatorFn.d.ts +7 -3
  259. package/lib/network/processor/gossipValidatorFn.d.ts.map +1 -1
  260. package/lib/network/processor/gossipValidatorFn.js +7 -3
  261. package/lib/network/processor/gossipValidatorFn.js.map +1 -1
  262. package/lib/network/processor/index.d.ts +9 -0
  263. package/lib/network/processor/index.d.ts.map +1 -1
  264. package/lib/network/processor/index.js +80 -13
  265. package/lib/network/processor/index.js.map +1 -1
  266. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js +1 -1
  267. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js.map +1 -1
  268. package/lib/network/reqresp/rateLimit.js +2 -2
  269. package/lib/network/reqresp/rateLimit.js.map +1 -1
  270. package/lib/network/subnets/attnetsService.d.ts.map +1 -1
  271. package/lib/network/subnets/attnetsService.js +3 -1
  272. package/lib/network/subnets/attnetsService.js.map +1 -1
  273. package/lib/node/nodejs.d.ts +3 -1
  274. package/lib/node/nodejs.d.ts.map +1 -1
  275. package/lib/node/nodejs.js +27 -4
  276. package/lib/node/nodejs.js.map +1 -1
  277. package/lib/node/notifier.d.ts.map +1 -1
  278. package/lib/node/notifier.js +12 -13
  279. package/lib/node/notifier.js.map +1 -1
  280. package/lib/node/options.d.ts +3 -2
  281. package/lib/node/options.d.ts.map +1 -1
  282. package/lib/node/options.js +2 -2
  283. package/lib/node/options.js.map +1 -1
  284. package/lib/sync/range/batch.d.ts +11 -5
  285. package/lib/sync/range/batch.d.ts.map +1 -1
  286. package/lib/sync/range/batch.js +21 -17
  287. package/lib/sync/range/batch.js.map +1 -1
  288. package/lib/sync/range/chain.d.ts +4 -4
  289. package/lib/sync/range/chain.d.ts.map +1 -1
  290. package/lib/sync/range/chain.js +12 -6
  291. package/lib/sync/range/chain.js.map +1 -1
  292. package/lib/sync/range/range.d.ts.map +1 -1
  293. package/lib/sync/range/range.js +75 -29
  294. package/lib/sync/range/range.js.map +1 -1
  295. package/lib/sync/unknownBlock.d.ts +14 -7
  296. package/lib/sync/unknownBlock.d.ts.map +1 -1
  297. package/lib/sync/unknownBlock.js +135 -68
  298. package/lib/sync/unknownBlock.js.map +1 -1
  299. package/lib/sync/utils/downloadByRange.d.ts +38 -14
  300. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  301. package/lib/sync/utils/downloadByRange.js +84 -39
  302. package/lib/sync/utils/downloadByRange.js.map +1 -1
  303. package/lib/util/asyncIterableToEvents.d.ts +10 -2
  304. package/lib/util/asyncIterableToEvents.d.ts.map +1 -1
  305. package/lib/util/asyncIterableToEvents.js +29 -3
  306. package/lib/util/asyncIterableToEvents.js.map +1 -1
  307. package/lib/util/clock.d.ts.map +1 -1
  308. package/lib/util/clock.js +3 -4
  309. package/lib/util/clock.js.map +1 -1
  310. package/lib/util/execution.d.ts +9 -11
  311. package/lib/util/execution.d.ts.map +1 -1
  312. package/lib/util/execution.js +5 -1
  313. package/lib/util/execution.js.map +1 -1
  314. package/lib/util/metadata.d.ts.map +1 -1
  315. package/lib/util/metadata.js +2 -1
  316. package/lib/util/metadata.js.map +1 -1
  317. package/lib/util/sszBytes.d.ts +2 -2
  318. package/lib/util/sszBytes.d.ts.map +1 -1
  319. package/lib/util/sszBytes.js +22 -14
  320. package/lib/util/sszBytes.js.map +1 -1
  321. package/package.json +18 -17
  322. package/src/api/impl/beacon/blocks/index.ts +17 -7
  323. package/src/api/impl/beacon/index.ts +15 -0
  324. package/src/api/impl/beacon/pool/index.ts +4 -4
  325. package/src/api/impl/beacon/state/index.ts +43 -6
  326. package/src/api/impl/debug/index.ts +28 -19
  327. package/src/api/impl/validator/index.ts +102 -21
  328. package/src/chain/ColumnReconstructionTracker.ts +4 -6
  329. package/src/chain/archiveStore/archiveStore.ts +26 -26
  330. package/src/chain/archiveStore/historicalState/getHistoricalState.ts +5 -7
  331. package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +1 -1
  332. package/src/chain/archiveStore/historicalState/types.ts +2 -2
  333. package/src/chain/archiveStore/historicalState/worker.ts +1 -2
  334. package/src/chain/archiveStore/interface.ts +1 -1
  335. package/src/chain/archiveStore/utils/pruneHistory.ts +9 -4
  336. package/src/chain/beaconProposerCache.ts +19 -1
  337. package/src/chain/blocks/blockInput/blockInput.ts +1 -1
  338. package/src/chain/blocks/importBlock.ts +29 -11
  339. package/src/chain/blocks/payloadEnvelopeInput/types.ts +2 -1
  340. package/src/chain/blocks/verifyBlock.ts +8 -6
  341. package/src/chain/blocks/verifyBlocksStateTransitionOnly.ts +6 -3
  342. package/src/chain/chain.ts +138 -40
  343. package/src/chain/emitter.ts +7 -1
  344. package/src/chain/errors/envelopeReconstructionError.ts +3 -0
  345. package/src/chain/errors/gossipValidation.ts +2 -0
  346. package/src/chain/forkChoice/index.ts +2 -0
  347. package/src/chain/initState.ts +8 -60
  348. package/src/chain/interface.ts +7 -3
  349. package/src/chain/opPools/aggregatedAttestationPool.ts +34 -10
  350. package/src/chain/opPools/opPool.ts +89 -46
  351. package/src/chain/opPools/proposerPreferencesPool.ts +34 -11
  352. package/src/chain/opPools/utils.ts +62 -3
  353. package/src/chain/options.ts +3 -3
  354. package/src/chain/prepareNextSlot.ts +28 -9
  355. package/src/chain/produceBlock/computeNewStateRoot.ts +10 -3
  356. package/src/chain/produceBlock/produceBlockBody.ts +86 -40
  357. package/src/chain/regen/regen.ts +12 -4
  358. package/src/chain/reprocess.ts +2 -1
  359. package/src/chain/seenCache/seenGossipBlockInput.ts +25 -1
  360. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +31 -13
  361. package/src/chain/shufflingCache.ts +84 -22
  362. package/src/chain/stateCache/persistentCheckpointsCache.ts +4 -1
  363. package/src/chain/validation/attesterSlashing.ts +7 -4
  364. package/src/chain/validation/proposerSlashing.ts +7 -4
  365. package/src/chain/validatorMonitor.ts +82 -61
  366. package/src/constants/constants.ts +1 -0
  367. package/src/db/beacon.ts +8 -0
  368. package/src/db/buckets.ts +2 -0
  369. package/src/db/interface.ts +4 -0
  370. package/src/db/repositories/blockArchive.ts +2 -2
  371. package/src/db/repositories/blockArchiveIndex.ts +2 -3
  372. package/src/db/repositories/earliestAvailableSlot.ts +19 -0
  373. package/src/db/repositories/index.ts +1 -0
  374. package/src/db/repositories/proposerPreferences.ts +23 -0
  375. package/src/db/repositories/proposerSlashing.ts +6 -1
  376. package/src/execution/engine/blobVersionedHashes.ts +72 -0
  377. package/src/execution/engine/disabled.ts +0 -8
  378. package/src/execution/engine/http.ts +304 -300
  379. package/src/execution/engine/index.ts +41 -7
  380. package/src/execution/engine/interface.ts +2 -6
  381. package/src/execution/engine/jsonRpcTransport.ts +247 -0
  382. package/src/execution/engine/mock.ts +1 -19
  383. package/src/execution/engine/restHttpClient.ts +269 -0
  384. package/src/execution/engine/restTransport.ts +544 -0
  385. package/src/execution/engine/sszTypes.ts +354 -0
  386. package/src/execution/engine/transport.ts +61 -0
  387. package/src/execution/engine/types.ts +42 -90
  388. package/src/execution/engine/utils.ts +12 -2
  389. package/src/index.ts +1 -1
  390. package/src/metrics/metrics/lodestar.ts +23 -0
  391. package/src/metrics/metrics.ts +21 -6
  392. package/src/network/core/events.ts +16 -1
  393. package/src/network/processor/gossipHandlers.ts +98 -81
  394. package/src/network/processor/gossipValidatorFn.ts +13 -3
  395. package/src/network/processor/index.ts +92 -13
  396. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRoot.ts +1 -1
  397. package/src/network/reqresp/rateLimit.ts +2 -2
  398. package/src/network/subnets/attnetsService.ts +8 -3
  399. package/src/node/nodejs.ts +35 -3
  400. package/src/node/notifier.ts +14 -13
  401. package/src/node/options.ts +10 -1
  402. package/src/sync/range/batch.ts +25 -19
  403. package/src/sync/range/chain.ts +15 -8
  404. package/src/sync/range/range.ts +76 -30
  405. package/src/sync/unknownBlock.ts +159 -73
  406. package/src/sync/utils/downloadByRange.ts +123 -58
  407. package/src/util/asyncIterableToEvents.ts +44 -5
  408. package/src/util/clock.ts +3 -4
  409. package/src/util/execution.ts +16 -8
  410. package/src/util/metadata.ts +2 -1
  411. package/src/util/sszBytes.ts +25 -12
@@ -11,7 +11,7 @@ import { BlockError, BlockErrorCode } from "../chain/errors/index.js";
11
11
  import { ChainEvent } from "../chain/index.js";
12
12
  import { validateGloasBlockDataColumnSidecars } from "../chain/validation/dataColumnSidecar.js";
13
13
  import { validateGossipExecutionPayloadEnvelope } from "../chain/validation/executionPayloadEnvelope.js";
14
- import { NetworkEvent, prettyPrintPeerIdStr } from "../network/index.js";
14
+ import { NetworkEvent, PeerAction, prettyPrintPeerIdStr } from "../network/index.js";
15
15
  import { MAX_PEERS_PER_ROOT } from "../network/processor/constants.js";
16
16
  import { ClockEvent } from "../util/clock.js";
17
17
  import { shuffle } from "../util/shuffle.js";
@@ -34,8 +34,12 @@ const PRUNE_UNRESOLVED_SLOT_EPOCHS = 2;
34
34
  */
35
35
  export const PAYLOAD_POLL_INTERVAL_MS = 1_000;
36
36
  class UnknownBlockRateLimitedError extends Error {
37
- constructor(message) {
37
+ retryAt;
38
+ constructor(message,
39
+ /** Earliest backoff expiry seen when the download was deferred, it is retried once that has passed */
40
+ retryAt) {
38
41
  super(message);
42
+ this.retryAt = retryAt;
39
43
  this.name = "UnknownBlockRateLimitedError";
40
44
  }
41
45
  }
@@ -378,6 +382,10 @@ export class BlockInputSync {
378
382
  });
379
383
  };
380
384
  addByRootHex = (rootHex, peerIdStr) => {
385
+ if (this.knownBadBlocks.has(rootHex)) {
386
+ this.logger.debug("Ignoring known bad block root", { root: rootHex, peerIdStr: peerIdStr ?? "unknown peer" });
387
+ return false;
388
+ }
381
389
  let pendingBlock = this.pendingBlocks.get(rootHex);
382
390
  let added = false;
383
391
  if (!pendingBlock) {
@@ -409,6 +417,10 @@ export class BlockInputSync {
409
417
  return added;
410
418
  };
411
419
  addByBlockInput = (blockInput, peerIdStr) => {
420
+ if (this.knownBadBlocks.has(blockInput.blockRootHex)) {
421
+ this.logger.debug("Ignoring known bad block", { slot: blockInput.slot, root: blockInput.blockRootHex, peerIdStr });
422
+ return;
423
+ }
412
424
  let pendingBlock = this.pendingBlocks.get(blockInput.blockRootHex);
413
425
  // if entry is missing or was added via rootHex and now we have more complete information overwrite
414
426
  // the existing information with the more complete cache entry
@@ -441,6 +453,14 @@ export class BlockInputSync {
441
453
  }
442
454
  };
443
455
  addByPayloadRootHex = (rootHex, peerIdStr, slot) => {
456
+ if (this.knownBadBlocks.has(rootHex)) {
457
+ this.logger.debug("Ignoring payload for known bad block root", {
458
+ slot: slot ?? "unknown",
459
+ root: rootHex,
460
+ peerIdStr,
461
+ });
462
+ return false;
463
+ }
444
464
  let pendingPayload = this.pendingPayloads.get(rootHex);
445
465
  let added = false;
446
466
  if (!pendingPayload) {
@@ -499,6 +519,14 @@ export class BlockInputSync {
499
519
  return this.chain.seenPayloadEnvelopeInputCache.get(rootHex)?.slot;
500
520
  }
501
521
  addByPayloadInput = (payloadInput, peerIdStr, envelope) => {
522
+ if (this.knownBadBlocks.has(payloadInput.blockRootHex)) {
523
+ this.logger.debug("Ignoring payload input for known bad block root", {
524
+ slot: payloadInput.slot,
525
+ root: payloadInput.blockRootHex,
526
+ peerIdStr,
527
+ });
528
+ return;
529
+ }
502
530
  const pendingPayload = this.toPendingPayloadInput(payloadInput, this.pendingPayloads.get(payloadInput.blockRootHex), envelope);
503
531
  if (peerIdStr && pendingPayload.peerIdStrings.size < MAX_PEERS_PER_ROOT) {
504
532
  pendingPayload.peerIdStrings.add(peerIdStr);
@@ -552,6 +580,7 @@ export class BlockInputSync {
552
580
  if (this.chain.forkChoice.getBlockHexAndBlockHash(parentRootHex, parentBlockHashHex) !== null) {
553
581
  return { kind: "ready" };
554
582
  }
583
+ // The parent's payload is known but does not match `parentBlockHashHex`
555
584
  if (this.chain.forkChoice.hasPayloadHexUnsafe(parentRootHex)) {
556
585
  return { kind: "invalidParentPayload", parentRootHex, parentBlockHashHex };
557
586
  }
@@ -693,21 +722,25 @@ export class BlockInputSync {
693
722
  this.triggerUnknownBlockSearch();
694
723
  }
695
724
  };
725
+ /**
726
+ * Returns false if there is no backoff left to wait for, in which case no retry is scheduled.
727
+ */
696
728
  scheduleRateLimitBackoffRetry() {
697
729
  this.clearRateLimitBackoffTimer();
698
730
  if (!this.subscribedToNetworkEvents || (this.pendingBlocks.size === 0 && this.pendingPayloads.size === 0)) {
699
- return;
731
+ return false;
700
732
  }
701
733
  const now = Date.now();
702
734
  const retryAt = this.peerBalancer.getNextRateLimitRetryAt();
703
735
  if (retryAt === null) {
704
- return;
736
+ return false;
705
737
  }
706
738
  this.rateLimitBackoffTimeout = setTimeout(() => {
707
739
  this.rateLimitBackoffTimeout = undefined;
708
740
  this.triggerUnknownBlockSearch();
709
741
  this.scheduleRateLimitBackoffRetry();
710
742
  }, Math.max(0, retryAt - now));
743
+ return true;
711
744
  }
712
745
  clearRateLimitBackoffTimer() {
713
746
  if (this.rateLimitBackoffTimeout !== undefined) {
@@ -745,13 +778,14 @@ export class BlockInputSync {
745
778
  * Poll unknown payloads of the current slot.
746
779
  */
747
780
  async pollPayloadsAtSlot(slot, signal) {
781
+ const fork = this.config.getForkName(slot);
748
782
  // fixed tick count so the loop cannot outlive its slot: for mainnet, it's 6 ticks
749
- const tickCount = Math.floor((this.config.SLOT_DURATION_MS - this.config.getPayloadDueMs()) / PAYLOAD_POLL_INTERVAL_MS);
783
+ const tickCount = Math.floor((this.config.getSlotDurationMs(fork) - this.config.getPayloadDueMs(fork)) / PAYLOAD_POLL_INTERVAL_MS);
750
784
  // a root still missing on several ticks is searched on each of them, recorded once
751
785
  const searchedRoots = new Set();
752
786
  let polls = 0;
753
787
  try {
754
- await sleep(Math.max(0, this.config.getPayloadDueMs() - this.chain.clock.msFromSlot(slot)), signal);
788
+ await sleep(Math.max(0, this.config.getPayloadDueMs(fork) - this.chain.clock.msFromSlot(slot)), signal);
755
789
  for (polls = 0; polls < tickCount; polls++) {
756
790
  let importedCount = 0;
757
791
  for (const [rootHex, { slot: deferredSlot, source, peer }] of this.deferredPayloadRoots) {
@@ -882,7 +916,8 @@ export class BlockInputSync {
882
916
  }
883
917
  else if (blockSlot <= finalizedSlot) {
884
918
  // the common ancestor of the downloading chain and canonical chain should be at least the finalized slot and
885
- // we should found it through forkchoice. If not, we should penalize all peers sending us this block chain
919
+ // we should found it through forkchoice. If not, drop the chain without penalizing peers because pending entries are
920
+ // block retained on failed download, so finalization can pass the block while it is still pending
886
921
  // 0 - 1 - ... - n - finalizedSlot
887
922
  // \
888
923
  // parent 1 - parent 2 - ... - unknownParent block
@@ -890,7 +925,7 @@ export class BlockInputSync {
890
925
  ...logCtx2,
891
926
  finalizedSlot,
892
927
  });
893
- this.removeAndDownScoreAllDescendants(block, DroppedItemReason.belowFinalized);
928
+ this.removeAllDescendants(block, DroppedItemReason.belowFinalized);
894
929
  }
895
930
  else {
896
931
  this.onUnknownBlockRoot({ rootHex: pending.blockInput.parentRootHex, source: BlockInputSource.byRoot });
@@ -903,7 +938,11 @@ export class BlockInputSync {
903
938
  pendingBlock.status = PendingBlockInputStatus.pending;
904
939
  }
905
940
  this.logger.debug("Deferring unknown block download due to peer rate limit", logCtx, res.err);
906
- this.scheduleRateLimitBackoffRetry();
941
+ if (!this.scheduleRateLimitBackoffRetry() || res.err.retryAt <= Date.now()) {
942
+ // The backoff this download waited for expired in the meantime, a timer is only armed if another
943
+ // peer is still in backoff and would retry it later than needed
944
+ this.triggerUnknownBlockSearch();
945
+ }
907
946
  return;
908
947
  }
909
948
  this.metrics?.blockInputSync.downloadedBlocksError.inc();
@@ -1009,14 +1048,17 @@ export class BlockInputSync {
1009
1048
  this.removeAllDescendants(pendingBlock, DroppedItemReason.elError, DroppedItemReason.elError);
1010
1049
  break;
1011
1050
  case BlockErrorCode.EXECUTION_ENGINE_INVALID:
1012
- // the peer served a bad block
1051
+ // Ban but do not downscore: optimistic-sync peers may forward and serve blocks whose payload is later
1052
+ // rejected by the execution engine. Per the spec, an INVALID execution payload SHOULD NOT cause a peer
1053
+ // to be down-scored or disconnected, only consensus-layer invalidity MAY.
1054
+ // https://github.com/ethereum/consensus-specs/blob/master/specs/bellatrix/p2p-interface.md#the-reqresp-domain
1013
1055
  this.logger.debug("Execution engine rejected block from unknown parent sync", errorData, res.err);
1014
- this.removeAndDownScoreAllDescendants(pendingBlock, DroppedItemReason.elInvalid);
1056
+ this.removeAndBanAllDescendants(pendingBlock, DroppedItemReason.elInvalid);
1015
1057
  break;
1016
1058
  default:
1017
1059
  // Block is not correct with respect to our chain. Log error loudly
1018
1060
  this.logger.debug("Error processing block from unknown parent sync", errorData, res.err);
1019
- this.removeAndDownScoreAllDescendants(pendingBlock, DroppedItemReason.invalidBlock);
1061
+ this.removeAllDescendants(pendingBlock, DroppedItemReason.invalidBlock);
1020
1062
  }
1021
1063
  }
1022
1064
  // Probably a queue error or something unwanted happened, mark as pending to try again latter
@@ -1138,6 +1180,12 @@ export class BlockInputSync {
1138
1180
  if (!isPendingPayloadEnvelope(payload)) {
1139
1181
  payload.status = PendingPayloadInputStatus.pending;
1140
1182
  }
1183
+ if (res.err instanceof UnknownBlockRateLimitedError &&
1184
+ (!this.scheduleRateLimitBackoffRetry() || res.err.retryAt <= Date.now())) {
1185
+ // The backoff this download waited for expired in the meantime, a timer is only armed if another
1186
+ // peer is still in backoff and would retry it later than needed
1187
+ this.triggerUnknownBlockSearch();
1188
+ }
1141
1189
  }
1142
1190
  async processPayload(pendingPayload) {
1143
1191
  const rootHex = pendingPayload.payloadInput.blockRootHex;
@@ -1191,18 +1239,21 @@ export class BlockInputSync {
1191
1239
  this.logger.debug("Execution engine error while processing payload from unknown sync", logCtx, res.err);
1192
1240
  pendingPayload.status = PendingPayloadInputStatus.downloaded;
1193
1241
  break;
1242
+ // The invalid envelope is evicted from the seen cache in the cases below, otherwise the next
1243
+ // attempt would reuse it instead of fetching another envelope from peers
1194
1244
  case PayloadErrorCode.EXECUTION_ENGINE_INVALID:
1195
1245
  this.logger.debug("Error processing payload from unknown sync", logCtx, res.err);
1246
+ this.chain.seenPayloadEnvelopeInputCache.removeInvalid(pendingPayload.payloadInput);
1196
1247
  this.removePendingPayloadAndDescendants(rootHex, DroppedItemReason.elInvalid);
1197
1248
  break;
1198
1249
  case PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR:
1199
1250
  this.logger.debug("Error processing payload from unknown sync", logCtx, res.err);
1251
+ this.chain.seenPayloadEnvelopeInputCache.removeInvalid(pendingPayload.payloadInput);
1200
1252
  this.removePendingPayloadAndDescendants(rootHex, DroppedItemReason.invalidEnvelope);
1201
1253
  break;
1202
1254
  case PayloadErrorCode.INVALID_SIGNATURE:
1203
- // TODO GLOAS: Decide how invalid payload inputs should eventually leave memory without
1204
- // reintroducing envelope replacement / recreation flows.
1205
1255
  this.logger.debug("Error processing payload from unknown sync", logCtx, res.err);
1256
+ this.chain.seenPayloadEnvelopeInputCache.removeInvalid(pendingPayload.payloadInput);
1206
1257
  this.removePendingPayloadAndDescendants(rootHex, DroppedItemReason.invalidSignature);
1207
1258
  break;
1208
1259
  default:
@@ -1240,11 +1291,14 @@ export class BlockInputSync {
1240
1291
  const pendingColumns = payloadInput?.hasAllData()
1241
1292
  ? new Set()
1242
1293
  : new Set(payloadInput?.getMissingSampledColumnMeta().missing ?? []);
1294
+ // Same `now` for both calls, a backoff expiring in between would be reported as no peer available
1295
+ const now = Date.now();
1243
1296
  // prefer peers that gossiped this payload root to us (#9923)
1244
- const peerMeta = this.peerBalancer.bestPeerForPendingColumns(pendingColumns, excludedPeers, cacheItem.peerIdStrings);
1297
+ const peerMeta = this.peerBalancer.bestPeerForPendingColumns(pendingColumns, excludedPeers, cacheItem.peerIdStrings, now);
1245
1298
  if (peerMeta === null) {
1246
- if (this.peerBalancer.getNextRateLimitRetryAt(pendingColumns, excludedPeers) !== null) {
1247
- throw new UnknownBlockRateLimitedError(`Error fetching payload by root slot=${slot} root=${rootHex} after ${i}: peers with needed columns are rate-limited`);
1299
+ const retryAt = this.peerBalancer.getNextRateLimitRetryAt(pendingColumns, excludedPeers, now);
1300
+ if (retryAt !== null) {
1301
+ throw new UnknownBlockRateLimitedError(`Error fetching payload by root slot=${slot} root=${rootHex} after ${i}: peers with needed columns are rate-limited`, retryAt);
1248
1302
  }
1249
1303
  const reason = pendingColumns.size > 0
1250
1304
  ? `cannot find peer with needed columns=${prettyPrintIndices(Array.from(pendingColumns))}`
@@ -1254,10 +1308,10 @@ export class BlockInputSync {
1254
1308
  throw Error(`Error fetching payload by root slot=${slot} root=${rootHex} after ${i}: ${reason}`);
1255
1309
  }
1256
1310
  const { peerId, client: peerClient } = peerMeta;
1257
- cacheItem.peerIdStrings.add(peerId);
1258
1311
  try {
1259
1312
  if (!envelope) {
1260
1313
  envelope = await this.fetchExecutionPayloadEnvelope(peerId, blockRoot, rootHex);
1314
+ cacheItem.peerIdStrings.add(peerId);
1261
1315
  const slotWasUnknown = typeof slot !== "number";
1262
1316
  slot = envelope.message.payload.slotNumber;
1263
1317
  if (slotWasUnknown) {
@@ -1292,6 +1346,8 @@ export class BlockInputSync {
1292
1346
  const missing = pendingPayload.payloadInput.getMissingSampledColumnMeta().missing;
1293
1347
  if (missing.length > 0) {
1294
1348
  const columnSidecars = await this.fetchPayloadColumns(peerMeta, pendingPayload.payloadInput, missing);
1349
+ // toPendingPayloadInput copied cacheItem's set, so add to the object that is carried forward
1350
+ pendingPayload.peerIdStrings.add(peerId);
1295
1351
  const seenTimestampSec = Date.now() / 1000;
1296
1352
  for (const columnSidecar of columnSidecars) {
1297
1353
  if (pendingPayload.payloadInput.hasColumn(columnSidecar.index)) {
@@ -1356,8 +1412,9 @@ export class BlockInputSync {
1356
1412
  }
1357
1413
  this.metrics?.blockInputSync.payloadFetchTime.observe({ result: FetchResult.FailureMaxAttempts }, Date.now() / 1000 - fetchStartSec);
1358
1414
  this.metrics?.blockInputSync.payloadFetchPeers.set({ result: FetchResult.FailureMaxAttempts }, i - 1);
1359
- if (deferredByRateLimit && this.peerBalancer.getNextRateLimitRetryAt() !== null) {
1360
- throw new UnknownBlockRateLimitedError(`Error fetching payload with slot=${slot} root=${rootHex} after ${i - 1} attempts: peers are rate-limited`);
1415
+ const retryAt = deferredByRateLimit ? this.peerBalancer.getNextRateLimitRetryAt() : null;
1416
+ if (retryAt !== null) {
1417
+ throw new UnknownBlockRateLimitedError(`Error fetching payload with slot=${slot} root=${rootHex} after ${i - 1} attempts: peers are rate-limited`, retryAt);
1361
1418
  }
1362
1419
  throw Error(`Error fetching payload with slot=${slot} root=${rootHex} after ${i - 1} attempts.`);
1363
1420
  }
@@ -1420,11 +1477,14 @@ export class BlockInputSync {
1420
1477
  const pendingColumns = isPendingBlockInput(cacheItem) && isBlockInputColumns(cacheItem.blockInput)
1421
1478
  ? new Set(cacheItem.blockInput.getMissingSampledColumnMeta().missing)
1422
1479
  : defaultPendingColumns;
1480
+ // Same `now` for both calls, a backoff expiring in between would be reported as no peer available
1481
+ const now = Date.now();
1423
1482
  // prefer peers that gossiped this block root to us (#9923)
1424
- const peerMeta = this.peerBalancer.bestPeerForPendingColumns(pendingColumns, excludedPeers, cacheItem.peerIdStrings);
1483
+ const peerMeta = this.peerBalancer.bestPeerForPendingColumns(pendingColumns, excludedPeers, cacheItem.peerIdStrings, now);
1425
1484
  if (peerMeta === null) {
1426
- if (this.peerBalancer.getNextRateLimitRetryAt(pendingColumns, excludedPeers) !== null) {
1427
- throw new UnknownBlockRateLimitedError(`Error fetching UnknownBlockRoot slot=${slot} root=${rootHex} after ${i}: peers with needed columns are rate-limited`);
1485
+ const retryAt = this.peerBalancer.getNextRateLimitRetryAt(pendingColumns, excludedPeers, now);
1486
+ if (retryAt !== null) {
1487
+ throw new UnknownBlockRateLimitedError(`Error fetching UnknownBlockRoot slot=${slot} root=${rootHex} after ${i}: peers with needed columns are rate-limited`, retryAt);
1428
1488
  }
1429
1489
  // no more peer with needed columns to try, throw error
1430
1490
  const message = `Error fetching UnknownBlockRoot slot=${slot} root=${rootHex} after ${i}: cannot find peer with needed columns=${prettyPrintIndices(Array.from(pendingColumns))}`;
@@ -1433,7 +1493,6 @@ export class BlockInputSync {
1433
1493
  throw Error(message);
1434
1494
  }
1435
1495
  const { peerId, client: peerClient } = peerMeta;
1436
- cacheItem.peerIdStrings.add(peerId);
1437
1496
  try {
1438
1497
  const downloadResult = await downloadByRoot({
1439
1498
  config: this.config,
@@ -1444,6 +1503,7 @@ export class BlockInputSync {
1444
1503
  cacheItem,
1445
1504
  });
1446
1505
  cacheItem = downloadResult.result;
1506
+ cacheItem.peerIdStrings.add(peerId);
1447
1507
  if (slot === undefined) {
1448
1508
  slot = cacheItem.blockInput.slot;
1449
1509
  // we were not able to observe the time into slot when starting the fetch, do it now
@@ -1520,8 +1580,9 @@ export class BlockInputSync {
1520
1580
  }
1521
1581
  } // end while loop over peers
1522
1582
  const message = `Error fetching BlockInput with slot=${slot} root=${rootHex} after ${i - 1} attempts.`;
1523
- if (deferredByRateLimit && this.peerBalancer.getNextRateLimitRetryAt() !== null) {
1524
- throw new UnknownBlockRateLimitedError(`${message} Peers are rate-limited.`);
1583
+ const retryAt = deferredByRateLimit ? this.peerBalancer.getNextRateLimitRetryAt() : null;
1584
+ if (retryAt !== null) {
1585
+ throw new UnknownBlockRateLimitedError(`${message} Peers are rate-limited.`, retryAt);
1525
1586
  }
1526
1587
  if (!isPendingBlockInput(cacheItem)) {
1527
1588
  throw Error(`${message} No block and no data was found.`);
@@ -1545,41 +1606,8 @@ export class BlockInputSync {
1545
1606
  this.metrics?.blockInputSync.fetchPeers.set({ result: FetchResult.FailureMaxAttempts }, i - 1);
1546
1607
  throw Error(message);
1547
1608
  }
1548
- /**
1549
- * Gets all descendant blocks of `block` recursively from `pendingBlocks`.
1550
- * Assumes that if a parent block does not exist or is not processable, all descendant blocks are bad too.
1551
- * Downscore all peers that have referenced any of this bad blocks. May report peers multiple times if they have
1552
- * referenced more than one bad block.
1553
- */
1554
- removeAndDownScoreAllDescendants(block, headReason) {
1555
- // Get all blocks that are a descendant of this one
1556
- const badPendingBlocks = this.removeAllDescendants(block, headReason, DroppedItemReason.invalidParent);
1557
- // just console log and do not penalize on pending/bad blocks for debugging
1558
- // console.log("removeAndDownscoreAllDescendants", {block});
1559
- for (const block of badPendingBlocks) {
1560
- //
1561
- // TODO(fulu): why is this commented out here?
1562
- //
1563
- // this.knownBadBlocks.add(block.blockRootHex);
1564
- // for (const peerIdStr of block.peerIdStrings) {
1565
- // // TODO: Refactor peerRpcScores to work with peerIdStr only
1566
- // this.network.reportPeer(peerIdStr, PeerAction.LowToleranceError, "BadBlockByRoot");
1567
- // }
1568
- this.logger.debug("ignored Banning unknown block", {
1569
- slot: getBlockInputSyncCacheItemSlot(block),
1570
- root: getBlockInputSyncCacheItemRootHex(block),
1571
- peerIdStrings: Array.from(block.peerIdStrings)
1572
- .map((id) => prettyPrintPeerIdStr(id))
1573
- .join(","),
1574
- });
1575
- }
1576
- // Prune knownBadBlocks
1577
- pruneSetToMax(this.knownBadBlocks, MAX_KNOWN_BAD_BLOCKS);
1578
- }
1579
1609
  // Once a parent payload is invalid, every descendant waiting on that payload lineage becomes unrecoverable too.
1580
1610
  removePendingPayloadAndDescendants(rootHex, headReason) {
1581
- // Keep PayloadEnvelopeInput resident in the seen cache. importBlock() owns that object and
1582
- // later validation/finalization logic decides when it can leave memory.
1583
1611
  if (this.pendingPayloads.delete(rootHex)) {
1584
1612
  this.metrics?.blockInputSync.removedPayloads.inc({ reason: headReason }, 1);
1585
1613
  }
@@ -1600,9 +1628,50 @@ export class BlockInputSync {
1600
1628
  });
1601
1629
  }
1602
1630
  }
1631
+ /**
1632
+ * Same as `removeAndBanAllDescendants`, and downscores every peer that referenced or served a banned item, once per
1633
+ * peer. Only call for consensus-layer invalidity, never for an INVALID execution payload:
1634
+ * https://github.com/ethereum/consensus-specs/blob/master/specs/bellatrix/p2p-interface.md#the-reqresp-domain
1635
+ */
1636
+ removeAndDownScoreAllDescendants(block, headReason) {
1637
+ const peersToReport = new Set();
1638
+ for (const bannedBlock of this.removeAndBanAllDescendants(block, headReason)) {
1639
+ for (const peerIdStr of bannedBlock.peerIdStrings) {
1640
+ peersToReport.add(peerIdStr);
1641
+ }
1642
+ }
1643
+ for (const peerIdStr of peersToReport) {
1644
+ this.network.reportPeer(peerIdStr, PeerAction.LowToleranceError, headReason);
1645
+ }
1646
+ }
1647
+ /**
1648
+ * Removes `block` and all its pending descendants and bans their roots in `knownBadBlocks`. Only call when the chain
1649
+ * is provably bad: a banned root is never searched for again. Returns the banned items.
1650
+ */
1651
+ removeAndBanAllDescendants(block, headReason) {
1652
+ const bannedBlocks = [];
1653
+ for (const badBlock of this.removeAllDescendants(block, headReason, DroppedItemReason.invalidParent)) {
1654
+ const rootHex = getBlockInputSyncCacheItemRootHex(badBlock);
1655
+ // a gossip import may race a failing sync path, never ban a root fork choice has imported
1656
+ if (this.chain.forkChoice.hasBlockHex(rootHex)) {
1657
+ continue;
1658
+ }
1659
+ this.knownBadBlocks.add(rootHex);
1660
+ bannedBlocks.push(badBlock);
1661
+ this.logger.debug("Banning unknown block", {
1662
+ slot: getBlockInputSyncCacheItemSlot(badBlock),
1663
+ root: rootHex,
1664
+ reason: headReason,
1665
+ peerIdStrings: Array.from(badBlock.peerIdStrings)
1666
+ .map((id) => prettyPrintPeerIdStr(id))
1667
+ .join(","),
1668
+ });
1669
+ }
1670
+ pruneSetToMax(this.knownBadBlocks, MAX_KNOWN_BAD_BLOCKS);
1671
+ return bannedBlocks;
1672
+ }
1603
1673
  removeAllDescendants(block, headReason, descendantReason = DroppedItemReason.invalidParent) {
1604
1674
  const rootHex = getBlockInputSyncCacheItemRootHex(block);
1605
- const slot = getBlockInputSyncCacheItemSlot(block);
1606
1675
  // Get all blocks that are a descendant of this one (index 0 is the head item itself)
1607
1676
  const badPendingBlocks = [block, ...getAllDescendantBlocks(rootHex, this.pendingBlocks)];
1608
1677
  for (const [i, block] of badPendingBlocks.entries()) {
@@ -1618,8 +1687,8 @@ export class BlockInputSync {
1618
1687
  // Keep PayloadEnvelopeInput resident in the seen cache for consistency with the
1619
1688
  // importBlock()-owned lifecycle.
1620
1689
  this.logger.debug("Removing bad/unknown/incomplete BlockInputSyncCacheItem", {
1621
- slot,
1622
- blockRoot: rootHex,
1690
+ slot: getBlockInputSyncCacheItemSlot(block),
1691
+ root: rootHex,
1623
1692
  });
1624
1693
  }
1625
1694
  return badPendingBlocks;
@@ -1666,8 +1735,7 @@ export class UnknownBlockPeerBalancer {
1666
1735
  onRateLimited(peerId, rateLimitedUntilMs) {
1667
1736
  this.rateLimitedUntilByPeer.set(peerId, rateLimitedUntilMs);
1668
1737
  }
1669
- getNextRateLimitRetryAt(pendingColumns, excludedPeers) {
1670
- const now = Date.now();
1738
+ getNextRateLimitRetryAt(pendingColumns, excludedPeers, now = Date.now()) {
1671
1739
  let retryAt = null;
1672
1740
  for (const [peerId, rateLimitedUntil] of this.rateLimitedUntilByPeer.entries()) {
1673
1741
  if (rateLimitedUntil <= now) {
@@ -1696,8 +1764,8 @@ export class UnknownBlockPeerBalancer {
1696
1764
  * preferredPeers are the peers NetworkProcessor told us gossiped this root (from
1697
1765
  * pendingBlock/cacheItem.peerIdStrings). They are preferred but not required.
1698
1766
  */
1699
- bestPeerForPendingColumns(pendingColumns, excludedPeers, preferredPeers) {
1700
- const eligiblePeers = this.filterPeers(pendingColumns, excludedPeers);
1767
+ bestPeerForPendingColumns(pendingColumns, excludedPeers, preferredPeers, now = Date.now()) {
1768
+ const eligiblePeers = this.filterPeers(pendingColumns, excludedPeers, now);
1701
1769
  if (eligiblePeers.length === 0) {
1702
1770
  return null;
1703
1771
  }
@@ -1730,8 +1798,7 @@ export class UnknownBlockPeerBalancer {
1730
1798
  }
1731
1799
  return totalActiveRequests;
1732
1800
  }
1733
- filterPeers(pendingDataColumns, excludedPeers) {
1734
- const now = Date.now();
1801
+ filterPeers(pendingDataColumns, excludedPeers, now) {
1735
1802
  let maxColumnCount = 0;
1736
1803
  const considerPeers = [];
1737
1804
  for (const [peerId, syncMeta] of this.peersMeta.entries()) {