@lodestar/beacon-node 1.49.0-dev.07c3496aff → 1.49.0-dev.0a27fd270f

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 (303) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +15 -6
  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 +4 -2
  6. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  7. package/lib/api/impl/beacon/state/index.d.ts.map +1 -1
  8. package/lib/api/impl/beacon/state/index.js +28 -0
  9. package/lib/api/impl/beacon/state/index.js.map +1 -1
  10. package/lib/api/impl/validator/index.d.ts.map +1 -1
  11. package/lib/api/impl/validator/index.js +9 -7
  12. package/lib/api/impl/validator/index.js.map +1 -1
  13. package/lib/chain/archiveStore/archiveStore.d.ts +1 -2
  14. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  15. package/lib/chain/archiveStore/archiveStore.js +23 -7
  16. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  17. package/lib/chain/archiveStore/historicalState/metrics.d.ts.map +1 -1
  18. package/lib/chain/archiveStore/historicalState/metrics.js +5 -6
  19. package/lib/chain/archiveStore/historicalState/metrics.js.map +1 -1
  20. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +11 -2
  21. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
  22. package/lib/chain/archiveStore/utils/archiveBlocks.js +46 -28
  23. package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
  24. package/lib/chain/archiveStore/utils/pruneHistory.d.ts +2 -2
  25. package/lib/chain/archiveStore/utils/pruneHistory.d.ts.map +1 -1
  26. package/lib/chain/archiveStore/utils/pruneHistory.js +15 -3
  27. package/lib/chain/archiveStore/utils/pruneHistory.js.map +1 -1
  28. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  29. package/lib/chain/blocks/importExecutionPayload.js +13 -0
  30. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  31. package/lib/chain/blocks/index.js +2 -2
  32. package/lib/chain/blocks/index.js.map +1 -1
  33. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +1 -1
  34. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
  35. package/lib/chain/chain.d.ts +10 -0
  36. package/lib/chain/chain.d.ts.map +1 -1
  37. package/lib/chain/chain.js +85 -16
  38. package/lib/chain/chain.js.map +1 -1
  39. package/lib/chain/emitter.d.ts +10 -0
  40. package/lib/chain/emitter.d.ts.map +1 -1
  41. package/lib/chain/emitter.js +4 -0
  42. package/lib/chain/emitter.js.map +1 -1
  43. package/lib/chain/errors/attesterSlashingError.d.ts +4 -1
  44. package/lib/chain/errors/attesterSlashingError.d.ts.map +1 -1
  45. package/lib/chain/errors/attesterSlashingError.js +1 -0
  46. package/lib/chain/errors/attesterSlashingError.js.map +1 -1
  47. package/lib/chain/errors/envelopeReconstructionError.d.ts +23 -0
  48. package/lib/chain/errors/envelopeReconstructionError.d.ts.map +1 -0
  49. package/lib/chain/errors/envelopeReconstructionError.js +13 -0
  50. package/lib/chain/errors/envelopeReconstructionError.js.map +1 -0
  51. package/lib/chain/errors/index.d.ts +1 -0
  52. package/lib/chain/errors/index.d.ts.map +1 -1
  53. package/lib/chain/errors/index.js +1 -0
  54. package/lib/chain/errors/index.js.map +1 -1
  55. package/lib/chain/errors/payloadAttestation.d.ts +4 -0
  56. package/lib/chain/errors/payloadAttestation.d.ts.map +1 -1
  57. package/lib/chain/errors/payloadAttestation.js +1 -0
  58. package/lib/chain/errors/payloadAttestation.js.map +1 -1
  59. package/lib/chain/errors/proposerSlashingError.d.ts +4 -1
  60. package/lib/chain/errors/proposerSlashingError.d.ts.map +1 -1
  61. package/lib/chain/errors/proposerSlashingError.js +1 -0
  62. package/lib/chain/errors/proposerSlashingError.js.map +1 -1
  63. package/lib/chain/interface.d.ts +6 -1
  64. package/lib/chain/interface.d.ts.map +1 -1
  65. package/lib/chain/interface.js.map +1 -1
  66. package/lib/chain/options.d.ts +2 -4
  67. package/lib/chain/options.d.ts.map +1 -1
  68. package/lib/chain/options.js +1 -1
  69. package/lib/chain/options.js.map +1 -1
  70. package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
  71. package/lib/chain/produceBlock/computeNewStateRoot.js +4 -2
  72. package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
  73. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  74. package/lib/chain/produceBlock/produceBlockBody.js +6 -6
  75. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  76. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +2 -1
  77. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
  78. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +3 -2
  79. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
  80. package/lib/chain/validation/attesterSlashing.d.ts.map +1 -1
  81. package/lib/chain/validation/attesterSlashing.js +1 -2
  82. package/lib/chain/validation/attesterSlashing.js.map +1 -1
  83. package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
  84. package/lib/chain/validation/payloadAttestationMessage.js +8 -1
  85. package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
  86. package/lib/chain/validation/proposerSlashing.js +1 -2
  87. package/lib/chain/validation/proposerSlashing.js.map +1 -1
  88. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  89. package/lib/chain/validatorMonitor.js +2 -2
  90. package/lib/chain/validatorMonitor.js.map +1 -1
  91. package/lib/db/beacon.d.ts +1 -2
  92. package/lib/db/beacon.d.ts.map +1 -1
  93. package/lib/db/beacon.js +1 -3
  94. package/lib/db/beacon.js.map +1 -1
  95. package/lib/db/buckets.d.ts +0 -1
  96. package/lib/db/buckets.d.ts.map +1 -1
  97. package/lib/db/buckets.js +1 -1
  98. package/lib/db/buckets.js.map +1 -1
  99. package/lib/db/interface.d.ts +1 -2
  100. package/lib/db/interface.d.ts.map +1 -1
  101. package/lib/db/repositories/blockArchive.d.ts +5 -0
  102. package/lib/db/repositories/blockArchive.d.ts.map +1 -1
  103. package/lib/db/repositories/blockArchive.js +36 -1
  104. package/lib/db/repositories/blockArchive.js.map +1 -1
  105. package/lib/db/repositories/blockArchiveIndex.d.ts +2 -2
  106. package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
  107. package/lib/db/repositories/executionPayloadEnvelopeArchive.d.ts +21 -9
  108. package/lib/db/repositories/executionPayloadEnvelopeArchive.d.ts.map +1 -1
  109. package/lib/db/repositories/executionPayloadEnvelopeArchive.js +32 -12
  110. package/lib/db/repositories/executionPayloadEnvelopeArchive.js.map +1 -1
  111. package/lib/db/repositories/index.d.ts +1 -2
  112. package/lib/db/repositories/index.d.ts.map +1 -1
  113. package/lib/db/repositories/index.js +1 -2
  114. package/lib/db/repositories/index.js.map +1 -1
  115. package/lib/execution/engine/disabled.d.ts +1 -0
  116. package/lib/execution/engine/disabled.d.ts.map +1 -1
  117. package/lib/execution/engine/disabled.js +3 -0
  118. package/lib/execution/engine/disabled.js.map +1 -1
  119. package/lib/execution/engine/http.d.ts +2 -1
  120. package/lib/execution/engine/http.d.ts.map +1 -1
  121. package/lib/execution/engine/http.js +7 -1
  122. package/lib/execution/engine/http.js.map +1 -1
  123. package/lib/execution/engine/interface.d.ts +3 -1
  124. package/lib/execution/engine/interface.d.ts.map +1 -1
  125. package/lib/execution/engine/mock.d.ts +1 -0
  126. package/lib/execution/engine/mock.d.ts.map +1 -1
  127. package/lib/execution/engine/mock.js +14 -2
  128. package/lib/execution/engine/mock.js.map +1 -1
  129. package/lib/execution/engine/types.d.ts +11 -0
  130. package/lib/execution/engine/types.d.ts.map +1 -1
  131. package/lib/execution/engine/types.js +10 -0
  132. package/lib/execution/engine/types.js.map +1 -1
  133. package/lib/metrics/metrics/beacon.d.ts +9 -0
  134. package/lib/metrics/metrics/beacon.d.ts.map +1 -1
  135. package/lib/metrics/metrics/beacon.js +16 -0
  136. package/lib/metrics/metrics/beacon.js.map +1 -1
  137. package/lib/metrics/metrics/lodestar.d.ts +35 -14
  138. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  139. package/lib/metrics/metrics/lodestar.js +76 -24
  140. package/lib/metrics/metrics/lodestar.js.map +1 -1
  141. package/lib/metrics/metrics.d.ts +3 -1
  142. package/lib/metrics/metrics.d.ts.map +1 -1
  143. package/lib/metrics/metrics.js +2 -2
  144. package/lib/metrics/metrics.js.map +1 -1
  145. package/lib/network/gossip/encoding.d.ts +1 -2
  146. package/lib/network/gossip/encoding.d.ts.map +1 -1
  147. package/lib/network/gossip/encoding.js +5 -10
  148. package/lib/network/gossip/encoding.js.map +1 -1
  149. package/lib/network/gossip/gossipsub.d.ts.map +1 -1
  150. package/lib/network/gossip/gossipsub.js +16 -1
  151. package/lib/network/gossip/gossipsub.js.map +1 -1
  152. package/lib/network/gossip/topic.d.ts +9 -6
  153. package/lib/network/gossip/topic.d.ts.map +1 -1
  154. package/lib/network/gossip/topic.js +23 -8
  155. package/lib/network/gossip/topic.js.map +1 -1
  156. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  157. package/lib/network/processor/gossipHandlers.js +16 -5
  158. package/lib/network/processor/gossipHandlers.js.map +1 -1
  159. package/lib/network/processor/gossipValidatorFn.d.ts +2 -0
  160. package/lib/network/processor/gossipValidatorFn.d.ts.map +1 -1
  161. package/lib/network/processor/gossipValidatorFn.js +88 -7
  162. package/lib/network/processor/gossipValidatorFn.js.map +1 -1
  163. package/lib/network/processor/index.d.ts +6 -2
  164. package/lib/network/processor/index.d.ts.map +1 -1
  165. package/lib/network/processor/index.js +62 -24
  166. package/lib/network/processor/index.js.map +1 -1
  167. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -1
  168. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +47 -34
  169. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
  170. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.d.ts.map +1 -1
  171. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js +23 -4
  172. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js.map +1 -1
  173. package/lib/network/reqresp/handlers/index.d.ts.map +1 -1
  174. package/lib/network/reqresp/handlers/index.js +20 -4
  175. package/lib/network/reqresp/handlers/index.js.map +1 -1
  176. package/lib/network/reqresp/protocols.d.ts.map +1 -1
  177. package/lib/network/reqresp/protocols.js +19 -5
  178. package/lib/network/reqresp/protocols.js.map +1 -1
  179. package/lib/node/nodejs.d.ts +2 -7
  180. package/lib/node/nodejs.d.ts.map +1 -1
  181. package/lib/node/nodejs.js +2 -22
  182. package/lib/node/nodejs.js.map +1 -1
  183. package/lib/sync/interface.d.ts +1 -2
  184. package/lib/sync/interface.d.ts.map +1 -1
  185. package/lib/sync/options.d.ts +0 -6
  186. package/lib/sync/options.d.ts.map +1 -1
  187. package/lib/sync/options.js +0 -2
  188. package/lib/sync/options.js.map +1 -1
  189. package/lib/sync/types.d.ts +39 -2
  190. package/lib/sync/types.d.ts.map +1 -1
  191. package/lib/sync/types.js +42 -2
  192. package/lib/sync/types.js.map +1 -1
  193. package/lib/sync/unknownBlock.d.ts +20 -0
  194. package/lib/sync/unknownBlock.d.ts.map +1 -1
  195. package/lib/sync/unknownBlock.js +231 -26
  196. package/lib/sync/unknownBlock.js.map +1 -1
  197. package/lib/util/execution.d.ts +42 -0
  198. package/lib/util/execution.d.ts.map +1 -1
  199. package/lib/util/execution.js +123 -2
  200. package/lib/util/execution.js.map +1 -1
  201. package/lib/util/headerEnvelope.d.ts +17 -0
  202. package/lib/util/headerEnvelope.d.ts.map +1 -0
  203. package/lib/util/headerEnvelope.js +43 -0
  204. package/lib/util/headerEnvelope.js.map +1 -0
  205. package/lib/util/shuffle.d.ts +0 -4
  206. package/lib/util/shuffle.d.ts.map +1 -1
  207. package/lib/util/shuffle.js +0 -8
  208. package/lib/util/shuffle.js.map +1 -1
  209. package/lib/util/sszBytes.d.ts +5 -0
  210. package/lib/util/sszBytes.d.ts.map +1 -1
  211. package/lib/util/sszBytes.js +13 -1
  212. package/lib/util/sszBytes.js.map +1 -1
  213. package/package.json +16 -16
  214. package/src/api/impl/beacon/blocks/index.ts +18 -5
  215. package/src/api/impl/beacon/pool/index.ts +6 -2
  216. package/src/api/impl/beacon/state/index.ts +36 -0
  217. package/src/api/impl/validator/index.ts +9 -7
  218. package/src/chain/archiveStore/archiveStore.ts +24 -8
  219. package/src/chain/archiveStore/historicalState/metrics.ts +5 -7
  220. package/src/chain/archiveStore/utils/archiveBlocks.ts +54 -32
  221. package/src/chain/archiveStore/utils/pruneHistory.ts +18 -6
  222. package/src/chain/blocks/importExecutionPayload.ts +14 -0
  223. package/src/chain/blocks/index.ts +2 -2
  224. package/src/chain/blocks/payloadEnvelopeInput/types.ts +1 -1
  225. package/src/chain/chain.ts +96 -20
  226. package/src/chain/emitter.ts +7 -2
  227. package/src/chain/errors/attesterSlashingError.ts +3 -1
  228. package/src/chain/errors/envelopeReconstructionError.ts +22 -0
  229. package/src/chain/errors/index.ts +1 -0
  230. package/src/chain/errors/payloadAttestation.ts +2 -0
  231. package/src/chain/errors/proposerSlashingError.ts +3 -1
  232. package/src/chain/interface.ts +6 -1
  233. package/src/chain/options.ts +3 -5
  234. package/src/chain/produceBlock/computeNewStateRoot.ts +9 -2
  235. package/src/chain/produceBlock/produceBlockBody.ts +17 -6
  236. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +3 -2
  237. package/src/chain/validation/attesterSlashing.ts +1 -2
  238. package/src/chain/validation/payloadAttestationMessage.ts +9 -0
  239. package/src/chain/validation/proposerSlashing.ts +1 -2
  240. package/src/chain/validatorMonitor.ts +12 -2
  241. package/src/db/beacon.ts +0 -5
  242. package/src/db/buckets.ts +2 -2
  243. package/src/db/interface.ts +0 -3
  244. package/src/db/repositories/blockArchive.ts +38 -1
  245. package/src/db/repositories/executionPayloadEnvelopeArchive.ts +43 -13
  246. package/src/db/repositories/index.ts +6 -2
  247. package/src/execution/engine/disabled.ts +4 -0
  248. package/src/execution/engine/http.ts +12 -0
  249. package/src/execution/engine/interface.ts +4 -1
  250. package/src/execution/engine/mock.ts +22 -2
  251. package/src/execution/engine/types.ts +25 -0
  252. package/src/metrics/metrics/beacon.ts +16 -0
  253. package/src/metrics/metrics/lodestar.ts +87 -28
  254. package/src/metrics/metrics.ts +7 -2
  255. package/src/network/gossip/encoding.ts +5 -8
  256. package/src/network/gossip/gossipsub.ts +19 -2
  257. package/src/network/gossip/topic.ts +25 -7
  258. package/src/network/processor/gossipHandlers.ts +18 -5
  259. package/src/network/processor/gossipValidatorFn.ts +111 -7
  260. package/src/network/processor/index.ts +81 -24
  261. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +57 -39
  262. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRoot.ts +27 -5
  263. package/src/network/reqresp/handlers/index.ts +49 -5
  264. package/src/network/reqresp/protocols.ts +31 -6
  265. package/src/node/nodejs.ts +0 -27
  266. package/src/sync/interface.ts +1 -2
  267. package/src/sync/options.ts +0 -8
  268. package/src/sync/types.ts +44 -5
  269. package/src/sync/unknownBlock.ts +254 -26
  270. package/src/util/execution.ts +175 -2
  271. package/src/util/headerEnvelope.ts +76 -0
  272. package/src/util/shuffle.ts +0 -9
  273. package/src/util/sszBytes.ts +18 -0
  274. package/lib/chain/archiveStore/utils/updateBackfillRange.d.ts +0 -20
  275. package/lib/chain/archiveStore/utils/updateBackfillRange.d.ts.map +0 -1
  276. package/lib/chain/archiveStore/utils/updateBackfillRange.js +0 -40
  277. package/lib/chain/archiveStore/utils/updateBackfillRange.js.map +0 -1
  278. package/lib/db/repositories/backfilledRanges.d.ts +0 -18
  279. package/lib/db/repositories/backfilledRanges.d.ts.map +0 -1
  280. package/lib/db/repositories/backfilledRanges.js +0 -26
  281. package/lib/db/repositories/backfilledRanges.js.map +0 -1
  282. package/lib/sync/backfill/backfill.d.ts +0 -169
  283. package/lib/sync/backfill/backfill.d.ts.map +0 -1
  284. package/lib/sync/backfill/backfill.js +0 -686
  285. package/lib/sync/backfill/backfill.js.map +0 -1
  286. package/lib/sync/backfill/errors.d.ts +0 -30
  287. package/lib/sync/backfill/errors.d.ts.map +0 -1
  288. package/lib/sync/backfill/errors.js +0 -15
  289. package/lib/sync/backfill/errors.js.map +0 -1
  290. package/lib/sync/backfill/index.d.ts +0 -2
  291. package/lib/sync/backfill/index.d.ts.map +0 -1
  292. package/lib/sync/backfill/index.js +0 -2
  293. package/lib/sync/backfill/index.js.map +0 -1
  294. package/lib/sync/backfill/verify.d.ts +0 -18
  295. package/lib/sync/backfill/verify.d.ts.map +0 -1
  296. package/lib/sync/backfill/verify.js +0 -36
  297. package/lib/sync/backfill/verify.js.map +0 -1
  298. package/src/chain/archiveStore/utils/updateBackfillRange.ts +0 -50
  299. package/src/db/repositories/backfilledRanges.ts +0 -29
  300. package/src/sync/backfill/backfill.ts +0 -916
  301. package/src/sync/backfill/errors.ts +0 -23
  302. package/src/sync/backfill/index.ts +0 -1
  303. package/src/sync/backfill/verify.ts +0 -58
@@ -1 +1 @@
1
- {"version":3,"file":"unknownBlock.d.ts","sourceRoot":"","sources":["../../src/sync/unknownBlock.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"unknownBlock.d.ts","sourceRoot":"","sources":["../../src/sync/unknownBlock.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import { routes } from "@lodestar/api";
2
2
  import { ForkSeq, SLOTS_PER_EPOCH, isForkPostGloas } from "@lodestar/params";
3
3
  import { RequestError, RequestErrorCode } from "@lodestar/reqresp";
4
4
  import { computeTimeAtSlot } from "@lodestar/state-transition";
5
- import { fromHex, prettyPrintIndices, pruneSetToMax, sleep, toRootHex } from "@lodestar/utils";
5
+ import { fromHex, isErrorAborted, prettyPrintIndices, pruneSetToMax, sleep, toRootHex } from "@lodestar/utils";
6
6
  import { isBlockInputBlobs, isBlockInputColumns } from "../chain/blocks/blockInput/blockInput.js";
7
7
  import { BlockInputSource } from "../chain/blocks/blockInput/types.js";
8
8
  import { PayloadError, PayloadErrorCode } from "../chain/blocks/importExecutionPayload.js";
@@ -13,11 +13,12 @@ import { validateGloasBlockDataColumnSidecars } from "../chain/validation/dataCo
13
13
  import { validateGossipExecutionPayloadEnvelope } from "../chain/validation/executionPayloadEnvelope.js";
14
14
  import { NetworkEvent, prettyPrintPeerIdStr } from "../network/index.js";
15
15
  import { MAX_PEERS_PER_ROOT } from "../network/processor/constants.js";
16
+ import { ClockEvent } from "../util/clock.js";
16
17
  import { shuffle } from "../util/shuffle.js";
17
18
  import { sortBy } from "../util/sortBy.js";
18
19
  import { wrapError } from "../util/wrapError.js";
19
20
  import { MAX_CONCURRENT_REQUESTS } from "./constants.js";
20
- import { DroppedItemReason, PendingBlockInputStatus, PendingBlockType, PendingPayloadInputStatus, getBlockInputSyncCacheItemRootHex, getBlockInputSyncCacheItemSlot, getPayloadSyncCacheItemRootHex, getPayloadSyncCacheItemSlot, isPendingBlockInput, isPendingPayloadEnvelope, isPendingPayloadInput, } from "./types.js";
21
+ import { DeferredPayloadResult, DownloadResult, DroppedItemReason, FetchResult, PendingBlockInputStatus, PendingBlockType, PendingPayloadInputStatus, getBlockInputSyncCacheItemRootHex, getBlockInputSyncCacheItemSlot, getPayloadSyncCacheItemRootHex, getPayloadSyncCacheItemSlot, isPendingBlockInput, isPendingPayloadEnvelope, isPendingPayloadInput, } from "./types.js";
21
22
  import { DownloadByRootError, downloadByRoot } from "./utils/downloadByRoot.js";
22
23
  import { getAllDescendantBlocks, getUnknownAndAncestorBlocks } from "./utils/pendingBlocksTree.js";
23
24
  import { getRateLimitedUntilMs } from "./utils/rateLimit.js";
@@ -28,14 +29,10 @@ const MAX_PENDING_BLOCKS = 100;
28
29
  * A pending payload without slot can only stay at most 2 epochs.
29
30
  */
30
31
  const PRUNE_UNRESOLVED_SLOT_EPOCHS = 2;
31
- var FetchResult;
32
- (function (FetchResult) {
33
- FetchResult["SuccessResolved"] = "success_resolved";
34
- FetchResult["SuccessMissingParent"] = "success_missing_parent";
35
- FetchResult["SuccessLate"] = "success_late";
36
- FetchResult["FailureTriedAllPeers"] = "failure_tried_all_peers";
37
- FetchResult["FailureMaxAttempts"] = "failure_max_attempts";
38
- })(FetchResult || (FetchResult = {}));
32
+ /**
33
+ * Poll pending payloads of the current slot this often, between PAYLOAD_DUE and the end of the slot.
34
+ */
35
+ export const PAYLOAD_POLL_INTERVAL_MS = 1_000;
39
36
  class UnknownBlockRateLimitedError extends Error {
40
37
  constructor(message) {
41
38
  super(message);
@@ -92,6 +89,11 @@ export class BlockInputSync {
92
89
  subscribedToNetworkEvents = false;
93
90
  peerBalancer;
94
91
  rateLimitBackoffTimeout;
92
+ /**
93
+ * Search unknown payload starting at PAYLOAD_DUE_BPS.
94
+ */
95
+ deferredPayloadRoots = new Map();
96
+ payloadPollAbortController;
95
97
  constructor(config, network, chain, logger, metrics, opts) {
96
98
  this.config = config;
97
99
  this.network = network;
@@ -117,6 +119,7 @@ export class BlockInputSync {
117
119
  this.logger.verbose("BlockInputSync enabled.");
118
120
  this.chain.emitter.on(ChainEvent.unknownBlockRoot, this.onUnknownBlockRoot);
119
121
  this.chain.emitter.on(ChainEvent.unknownEnvelopeBlockRoot, this.onUnknownEnvelopeBlockRoot);
122
+ this.chain.emitter.on(ChainEvent.unknownEnvelopeBlockRootSlot, this.onUnknownEnvelopeBlockRootSlot);
120
123
  this.chain.emitter.on(ChainEvent.incompleteBlockInput, this.onIncompleteBlockInput);
121
124
  this.chain.emitter.on(ChainEvent.incompletePayloadEnvelope, this.onIncompletePayloadEnvelope);
122
125
  this.chain.emitter.on(ChainEvent.blockUnknownParent, this.onUnknownParent);
@@ -125,6 +128,7 @@ export class BlockInputSync {
125
128
  this.chain.emitter.on(routes.events.EventType.executionPayload, this.onPayloadImported);
126
129
  this.network.events.on(NetworkEvent.peerConnected, this.onPeerConnected);
127
130
  this.network.events.on(NetworkEvent.peerDisconnected, this.onPeerDisconnected);
131
+ this.chain.clock.on(ClockEvent.slot, this.startPayloadPollAtSlot);
128
132
  // Seed the balancer with peers that connected before we subscribed
129
133
  for (const peerId of this.network.getConnectedPeers()) {
130
134
  try {
@@ -135,13 +139,21 @@ export class BlockInputSync {
135
139
  }
136
140
  }
137
141
  this.subscribedToNetworkEvents = true;
142
+ // we subscribe mid-slot, and a root can be deferred at any point in the slot, so start this
143
+ // slot's loop now instead of waiting for the next ClockEvent.slot
144
+ this.startPayloadPollAtSlot(this.chain.clock.currentSlot);
138
145
  }
139
146
  }
140
147
  unsubscribeFromNetwork() {
141
148
  this.logger.verbose("BlockInputSync disabled.");
142
149
  this.clearRateLimitBackoffTimer();
150
+ this.chain.clock.off(ClockEvent.slot, this.startPayloadPollAtSlot);
151
+ this.payloadPollAbortController?.abort();
152
+ this.payloadPollAbortController = undefined;
153
+ this.deferredPayloadRoots.clear();
143
154
  this.chain.emitter.off(ChainEvent.unknownBlockRoot, this.onUnknownBlockRoot);
144
155
  this.chain.emitter.off(ChainEvent.unknownEnvelopeBlockRoot, this.onUnknownEnvelopeBlockRoot);
156
+ this.chain.emitter.off(ChainEvent.unknownEnvelopeBlockRootSlot, this.onUnknownEnvelopeBlockRootSlot);
145
157
  this.chain.emitter.off(ChainEvent.incompleteBlockInput, this.onIncompleteBlockInput);
146
158
  this.chain.emitter.off(ChainEvent.incompletePayloadEnvelope, this.onIncompletePayloadEnvelope);
147
159
  this.chain.emitter.off(ChainEvent.blockUnknownParent, this.onUnknownParent);
@@ -165,8 +177,11 @@ export class BlockInputSync {
165
177
  onUnknownBlockRoot = (data) => {
166
178
  try {
167
179
  const isNewRoot = this.addByRootHex(data.rootHex, data.peer);
168
- if (isNewRoot) {
180
+ // A retained entry (an earlier download failed, #10018) is not new but still needs a retry pass.
181
+ if (this.pendingBlocks.get(data.rootHex)?.status === PendingBlockInputStatus.pending) {
169
182
  this.triggerUnknownBlockSearch();
183
+ }
184
+ if (isNewRoot) {
170
185
  this.metrics?.blockInputSync.requests.inc({ type: PendingBlockType.UNKNOWN_BLOCK_ROOT });
171
186
  this.metrics?.blockInputSync.source.inc({ source: data.source });
172
187
  }
@@ -202,6 +217,33 @@ export class BlockInputSync {
202
217
  this.logger.debug("Error handling unknownEnvelopeBlockRoot event", {}, e);
203
218
  }
204
219
  };
220
+ onUnknownEnvelopeBlockRootSlot = (data) => {
221
+ try {
222
+ if (data.slot === this.chain.clock.currentSlot) {
223
+ // we receive the optimistic search, the poll loop searches it at PAYLOAD_DUE or on its next
224
+ // tick. If that loop already returned - every root it watched was imported - this root waits
225
+ // for the next slot, where startPayloadPollAtSlot moves it to pendingPayloads. That is not the normal
226
+ // scenario, and in a forking condition it only delays the search of the extra root
227
+ const deferred = this.deferredPayloadRoots.get(data.rootHex);
228
+ if (deferred === undefined) {
229
+ this.deferredPayloadRoots.set(data.rootHex, { slot: data.slot, source: data.source, peer: data.peer });
230
+ }
231
+ else if (deferred.peer === undefined) {
232
+ deferred.peer = data.peer;
233
+ }
234
+ return;
235
+ }
236
+ const isNewRoot = this.addByPayloadRootHex(data.rootHex, data.peer, data.slot);
237
+ if (isNewRoot) {
238
+ this.triggerUnknownBlockSearch();
239
+ this.metrics?.blockInputSync.requests.inc({ type: PendingBlockType.UNKNOWN_PAYLOAD_BLOCK_ROOT_SLOT });
240
+ this.metrics?.blockInputSync.payloadSource.inc({ source: data.source });
241
+ }
242
+ }
243
+ catch (e) {
244
+ this.logger.debug("Error handling unknownEnvelopeBlockRootSlot event", {}, e);
245
+ }
246
+ };
205
247
  onIncompletePayloadEnvelope = (data) => {
206
248
  try {
207
249
  this.addByPayloadInput(data.payloadInput, data.peer);
@@ -296,12 +338,21 @@ export class BlockInputSync {
296
338
  belowFinalizedPayloads++;
297
339
  }
298
340
  }
299
- let deletedBlocks = 0;
341
+ let belowFinalizedBlocks = 0;
342
+ let agedOutBlocks = 0;
300
343
  for (const [rootHex, block] of this.pendingBlocks) {
301
344
  const slot = getBlockInputSyncCacheItemSlot(block);
302
- if (typeof slot === "number" && slot < finalizedSlot) {
345
+ if (typeof slot !== "number") {
346
+ // we may not be able to download a root, hence there is no slot for it
347
+ if (nowSec - block.timeAddedSec > maxSecInCache) {
348
+ this.pendingBlocks.delete(rootHex);
349
+ agedOutBlocks++;
350
+ }
351
+ continue;
352
+ }
353
+ if (slot < finalizedSlot) {
303
354
  this.pendingBlocks.delete(rootHex);
304
- deletedBlocks++;
355
+ belowFinalizedBlocks++;
305
356
  }
306
357
  }
307
358
  if (belowFinalizedPayloads > 0) {
@@ -310,15 +361,19 @@ export class BlockInputSync {
310
361
  if (agedOutPayloads > 0) {
311
362
  this.metrics?.blockInputSync.removedPayloads.inc({ reason: DroppedItemReason.agedOut }, agedOutPayloads);
312
363
  }
313
- if (deletedBlocks > 0) {
314
- this.metrics?.blockInputSync.removedBlocks.inc({ reason: DroppedItemReason.belowFinalized }, deletedBlocks);
364
+ if (belowFinalizedBlocks > 0) {
365
+ this.metrics?.blockInputSync.removedBlocks.inc({ reason: DroppedItemReason.belowFinalized }, belowFinalizedBlocks);
315
366
  }
316
- this.logger.debug("BlockInputSync.pruneFinalized dropped pre-finalized pending items", {
367
+ if (agedOutBlocks > 0) {
368
+ this.metrics?.blockInputSync.removedBlocks.inc({ reason: DroppedItemReason.agedOut }, agedOutBlocks);
369
+ }
370
+ this.logger.debug("BlockInputSync.pruneFinalized dropped stale pending items", {
317
371
  finalizedSlot,
318
372
  finalizedRoot: checkpoint.rootHex,
319
373
  belowFinalizedPayloads,
320
374
  agedOutPayloads,
321
- deletedBlocks,
375
+ belowFinalizedBlocks,
376
+ agedOutBlocks,
322
377
  unresolvedSlotPayloads,
323
378
  });
324
379
  };
@@ -660,6 +715,115 @@ export class BlockInputSync {
660
715
  this.rateLimitBackoffTimeout = undefined;
661
716
  }
662
717
  }
718
+ /**
719
+ * Start this slot's payload poll: end the previous slot's loop, move roots it never got to
720
+ * into pendingPayloads, then poll from PAYLOAD_DUE to the end of the slot.
721
+ */
722
+ startPayloadPollAtSlot = (slot) => {
723
+ if (!isForkPostGloas(this.config.getForkName(slot))) {
724
+ return;
725
+ }
726
+ // end the previous slot's loop, wherever it is: its sleep is bound to this same controller
727
+ this.payloadPollAbortController?.abort();
728
+ this.payloadPollAbortController = new AbortController();
729
+ // entries from an earlier slot is not polled
730
+ for (const [rootHex, { slot: deferredSlot, source, peer }] of this.deferredPayloadRoots) {
731
+ if (deferredSlot < slot) {
732
+ if (!this.chain.forkChoice.hasPayloadHexUnsafe(rootHex)) {
733
+ this.addDeferredPayloadRoot(rootHex, deferredSlot, source, peer);
734
+ }
735
+ this.deferredPayloadRoots.delete(rootHex);
736
+ }
737
+ }
738
+ this.pollPayloadsAtSlot(slot, this.payloadPollAbortController.signal).catch((e) => {
739
+ if (!isErrorAborted(e)) {
740
+ this.logger.debug("Error polling payloads", { slot }, e);
741
+ }
742
+ });
743
+ };
744
+ /**
745
+ * Poll unknown payloads of the current slot.
746
+ */
747
+ async pollPayloadsAtSlot(slot, signal) {
748
+ // 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);
750
+ // a root still missing on several ticks is searched on each of them, recorded once
751
+ const searchedRoots = new Set();
752
+ let polls = 0;
753
+ try {
754
+ await sleep(Math.max(0, this.config.getPayloadDueMs() - this.chain.clock.msFromSlot(slot)), signal);
755
+ for (polls = 0; polls < tickCount; polls++) {
756
+ let importedCount = 0;
757
+ for (const [rootHex, { slot: deferredSlot, source, peer }] of this.deferredPayloadRoots) {
758
+ if (this.chain.forkChoice.hasPayloadHexUnsafe(rootHex)) {
759
+ importedCount++;
760
+ continue;
761
+ }
762
+ // copy to the regular pendingPayloads so that we can search
763
+ this.addDeferredPayloadRoot(rootHex, deferredSlot, source, peer);
764
+ searchedRoots.add(rootHex);
765
+ }
766
+ // an empty deferredPayloadRoots means there is no optimistic search comes before PAYLOAD_DUE
767
+ // we have to poll until the payload of current slot is imported or slot end
768
+ if (this.deferredPayloadRoots.size > 0 && importedCount === this.deferredPayloadRoots.size) {
769
+ if (searchedRoots.size > 0) {
770
+ // the backup search was needed
771
+ this.metrics?.blockInputSync.deferredPayloadResult.inc({
772
+ result: DeferredPayloadResult.ImportedAfterSearch,
773
+ });
774
+ this.metrics?.blockInputSync.deferredPayloadPolls.observe(polls);
775
+ this.logger.verbose("Payload imported after unknown sync search", {
776
+ slot,
777
+ roots: Array.from(searchedRoots).join(","),
778
+ polls,
779
+ });
780
+ }
781
+ else {
782
+ // this happens most of the time on devnet
783
+ // gossip delivered everything before PAYLOAD_DUE
784
+ this.metrics?.blockInputSync.deferredPayloadResult.inc({
785
+ result: DeferredPayloadResult.ImportedBeforeSearch,
786
+ });
787
+ }
788
+ return;
789
+ }
790
+ this.triggerUnknownBlockSearch();
791
+ if (polls < tickCount - 1) {
792
+ // no sleep after the last tick: the loop would otherwise end right at the slot boundary,
793
+ // where startPayloadPollAtSlot aborts it
794
+ await sleep(PAYLOAD_POLL_INTERVAL_MS, signal);
795
+ }
796
+ }
797
+ // reaching here means the early return never fired
798
+ if (this.deferredPayloadRoots.size > 0) {
799
+ this.metrics?.blockInputSync.deferredPayloadResult.inc({ result: DeferredPayloadResult.Unresolved });
800
+ this.logger.debug("Deferred payloads still missing at end of slot", {
801
+ slot,
802
+ roots: Array.from(this.deferredPayloadRoots.keys()).join(","),
803
+ });
804
+ }
805
+ else {
806
+ // no optimistic search and no payload import ended the loop, eg a skipped slot
807
+ this.metrics?.blockInputSync.deferredPayloadResult.inc({ result: DeferredPayloadResult.ResolvedNoRoot });
808
+ this.logger.debug("No deferred payloads at slot", {
809
+ slot,
810
+ });
811
+ }
812
+ }
813
+ catch (e) {
814
+ if (!isErrorAborted(e)) {
815
+ throw e;
816
+ }
817
+ this.logger.verbose("Payload poll aborted", { slot, polls, msIntoSlot: this.chain.clock.msFromSlot(slot) });
818
+ }
819
+ }
820
+ addDeferredPayloadRoot(rootHex, slot, source, peer) {
821
+ const isNewRoot = this.addByPayloadRootHex(rootHex, peer, slot);
822
+ if (isNewRoot) {
823
+ this.metrics?.blockInputSync.requests.inc({ type: PendingBlockType.DEFERRED_PAYLOAD_BLOCK_ROOT });
824
+ this.metrics?.blockInputSync.payloadSource.inc({ source });
825
+ }
826
+ }
663
827
  async downloadBlock(block) {
664
828
  if (block.status !== PendingBlockInputStatus.pending) {
665
829
  return;
@@ -678,7 +842,12 @@ export class BlockInputSync {
678
842
  if (!res.err) {
679
843
  this.metrics?.blockInputSync.downloadedBlocksSuccess.inc();
680
844
  const pending = res.result;
681
- this.pendingBlocks.set(pending.blockInput.blockRootHex, pending);
845
+ // pruning may have deleted this entry while we were awaiting the network, do not resurrect it via the set below
846
+ if (!this.pendingBlocks.has(rootHex)) {
847
+ this.logger.verbose("Dropping downloaded block, entry pruned during fetch", logCtx);
848
+ return;
849
+ }
850
+ this.pendingBlocks.set(rootHex, pending);
682
851
  const blockSlot = pending.blockInput.slot;
683
852
  const finalizedSlot = this.chain.forkChoice.getFinalizedBlock().slot;
684
853
  const delaySec = Date.now() / 1000 - computeTimeAtSlot(this.config, blockSlot, this.chain.genesisTime);
@@ -738,8 +907,11 @@ export class BlockInputSync {
738
907
  return;
739
908
  }
740
909
  this.metrics?.blockInputSync.downloadedBlocksError.inc();
741
- this.logger.debug("Ignoring unknown block root after many failed downloads", logCtx, res.err);
742
- this.removeAndDownScoreAllDescendants(block, DroppedItemReason.unavailable);
910
+ this.logger.debug("Failed to download unknown block root, retained for retry", logCtx, res.err);
911
+ const pendingBlock = this.pendingBlocks.get(rootHex);
912
+ if (pendingBlock && pendingBlock.status === PendingBlockInputStatus.fetching) {
913
+ pendingBlock.status = PendingBlockInputStatus.pending;
914
+ }
743
915
  }
744
916
  }
745
917
  /**
@@ -946,15 +1118,23 @@ export class BlockInputSync {
946
1118
  return;
947
1119
  }
948
1120
  this.pendingPayloads.set(resultRootHex, pendingPayload);
1121
+ const result = isPendingPayloadEnvelope(pendingPayload)
1122
+ ? DownloadResult.WaitingForBlock
1123
+ : this.chain.forkChoice.hasPayloadHexUnsafe(resultRootHex)
1124
+ ? DownloadResult.Late
1125
+ : DownloadResult.Resolved;
1126
+ this.metrics?.blockInputSync.downloadedPayloadsResult.inc({ result });
949
1127
  if (isPendingPayloadEnvelope(pendingPayload)) {
950
1128
  await this.reconcilePayloadEnvelope(pendingPayload);
951
1129
  }
952
1130
  else if (pendingPayload.status === PendingPayloadInputStatus.downloaded) {
1131
+ this.metrics?.blockInputSync.elapsedTimeTillPayloadReceived.observe(Date.now() / 1000 - computeTimeAtSlot(this.config, pendingPayload.payloadInput.slot, this.chain.genesisTime));
953
1132
  await this.processPayload(pendingPayload);
954
1133
  }
955
1134
  return;
956
1135
  }
957
- this.logger.debug("Ignoring unknown payload root after failed download", logCtx, res.err);
1136
+ this.metrics?.blockInputSync.downloadedPayloadsResult.inc({ result: DownloadResult.Failed });
1137
+ this.logger.debug("Failed to download unknown payload root, retained for retry", logCtx, res.err);
958
1138
  if (!isPendingPayloadEnvelope(payload)) {
959
1139
  payload.status = PendingPayloadInputStatus.pending;
960
1140
  }
@@ -1050,6 +1230,10 @@ export class BlockInputSync {
1050
1230
  ? cacheItem.payloadInput
1051
1231
  : await this.chain.seenPayloadEnvelopeInputCache.getOrReload(rootHex);
1052
1232
  let envelope = payloadInput?.hasPayloadEnvelope() ? payloadInput.getPayloadEnvelope() : undefined;
1233
+ const fetchStartSec = Date.now() / 1000;
1234
+ if (typeof slot === "number") {
1235
+ this.metrics?.blockInputSync.payloadFetchBegin.observe(this.chain.clock.secFromSlot(slot, fetchStartSec));
1236
+ }
1053
1237
  let i = 0;
1054
1238
  let deferredByRateLimit = false;
1055
1239
  while (i++ < this.getMaxDownloadAttempts()) {
@@ -1065,6 +1249,8 @@ export class BlockInputSync {
1065
1249
  const reason = pendingColumns.size > 0
1066
1250
  ? `cannot find peer with needed columns=${prettyPrintIndices(Array.from(pendingColumns))}`
1067
1251
  : "no peer available to download pending payload";
1252
+ this.metrics?.blockInputSync.payloadFetchTime.observe({ result: FetchResult.FailureTriedAllPeers }, Date.now() / 1000 - fetchStartSec);
1253
+ this.metrics?.blockInputSync.payloadFetchPeers.set({ result: FetchResult.FailureTriedAllPeers }, i);
1068
1254
  throw Error(`Error fetching payload by root slot=${slot} root=${rootHex} after ${i}: ${reason}`);
1069
1255
  }
1070
1256
  const { peerId, client: peerClient } = peerMeta;
@@ -1072,7 +1258,12 @@ export class BlockInputSync {
1072
1258
  try {
1073
1259
  if (!envelope) {
1074
1260
  envelope = await this.fetchExecutionPayloadEnvelope(peerId, blockRoot, rootHex);
1261
+ const slotWasUnknown = typeof slot !== "number";
1075
1262
  slot = envelope.message.payload.slotNumber;
1263
+ if (slotWasUnknown) {
1264
+ // we were not able to observe the time into slot when starting the fetch, do it now
1265
+ this.metrics?.blockInputSync.payloadFetchBegin.observe(this.chain.clock.secFromSlot(slot, fetchStartSec));
1266
+ }
1076
1267
  }
1077
1268
  payloadInput ??= await this.chain.seenPayloadEnvelopeInputCache.getOrReload(rootHex);
1078
1269
  if (!this.chain.forkChoice.hasBlockHex(rootHex)) {
@@ -1080,6 +1271,8 @@ export class BlockInputSync {
1080
1271
  // envelope and wait for the block body; reconcilePayloadEnvelope validates once the block lands.
1081
1272
  // payloadInput may be seeded from the block body during download, so a non-null payloadInput does not
1082
1273
  // imply the block is imported.
1274
+ this.metrics?.blockInputSync.payloadFetchTime.observe({ result: FetchResult.SuccessWaitingForBlock }, Date.now() / 1000 - fetchStartSec);
1275
+ this.metrics?.blockInputSync.payloadFetchPeers.set({ result: FetchResult.SuccessWaitingForBlock }, i);
1083
1276
  return {
1084
1277
  status: PendingPayloadInputStatus.waitingForBlock,
1085
1278
  envelope,
@@ -1124,6 +1317,12 @@ export class BlockInputSync {
1124
1317
  hasAllData: pendingPayload.payloadInput.hasAllData(),
1125
1318
  });
1126
1319
  if (pendingPayload.status === PendingPayloadInputStatus.downloaded) {
1320
+ // late = the payload got imported (via gossip) while we were downloading, same as the block path
1321
+ const result = this.chain.forkChoice.hasPayloadHexUnsafe(rootHex)
1322
+ ? FetchResult.SuccessLate
1323
+ : FetchResult.SuccessResolved;
1324
+ this.metrics?.blockInputSync.payloadFetchTime.observe({ result }, Date.now() / 1000 - fetchStartSec);
1325
+ this.metrics?.blockInputSync.payloadFetchPeers.set({ result }, i);
1127
1326
  return pendingPayload;
1128
1327
  }
1129
1328
  cacheItem = pendingPayload;
@@ -1155,6 +1354,8 @@ export class BlockInputSync {
1155
1354
  this.peerBalancer.onRequestCompleted(peerId);
1156
1355
  }
1157
1356
  }
1357
+ this.metrics?.blockInputSync.payloadFetchTime.observe({ result: FetchResult.FailureMaxAttempts }, Date.now() / 1000 - fetchStartSec);
1358
+ this.metrics?.blockInputSync.payloadFetchPeers.set({ result: FetchResult.FailureMaxAttempts }, i - 1);
1158
1359
  if (deferredByRateLimit && this.peerBalancer.getNextRateLimitRetryAt() !== null) {
1159
1360
  throw new UnknownBlockRateLimitedError(`Error fetching payload with slot=${slot} root=${rootHex} after ${i - 1} attempts: peers are rate-limited`);
1160
1361
  }
@@ -1227,7 +1428,7 @@ export class BlockInputSync {
1227
1428
  }
1228
1429
  // no more peer with needed columns to try, throw error
1229
1430
  const message = `Error fetching UnknownBlockRoot slot=${slot} root=${rootHex} after ${i}: cannot find peer with needed columns=${prettyPrintIndices(Array.from(pendingColumns))}`;
1230
- this.metrics?.blockInputSync.fetchTimeSec.observe({ result: FetchResult.FailureTriedAllPeers }, Date.now() / 1000 - fetchStartSec);
1431
+ this.metrics?.blockInputSync.fetchTime.observe({ result: FetchResult.FailureTriedAllPeers }, Date.now() / 1000 - fetchStartSec);
1231
1432
  this.metrics?.blockInputSync.fetchPeers.set({ result: FetchResult.FailureTriedAllPeers }, i);
1232
1433
  throw Error(message);
1233
1434
  }
@@ -1301,7 +1502,11 @@ export class BlockInputSync {
1301
1502
  finally {
1302
1503
  this.peerBalancer.onRequestCompleted(peerId);
1303
1504
  }
1304
- this.pendingBlocks.set(getBlockInputSyncCacheItemRootHex(cacheItem), cacheItem);
1505
+ const cacheItemRootHex = getBlockInputSyncCacheItemRootHex(cacheItem);
1506
+ // pruning may have dropped it mid-fetch
1507
+ if (this.pendingBlocks.has(cacheItemRootHex)) {
1508
+ this.pendingBlocks.set(cacheItemRootHex, cacheItem);
1509
+ }
1305
1510
  if (cacheItem.status === PendingBlockInputStatus.downloaded) {
1306
1511
  // download was successful, no need to go with another peer, return
1307
1512
  const result = this.chain.forkChoice.hasBlockHex(cacheItem.blockInput.blockRootHex)
@@ -1309,7 +1514,7 @@ export class BlockInputSync {
1309
1514
  : this.chain.forkChoice.hasBlockHex(cacheItem.blockInput.parentRootHex)
1310
1515
  ? FetchResult.SuccessResolved
1311
1516
  : FetchResult.SuccessMissingParent;
1312
- this.metrics?.blockInputSync.fetchTimeSec.observe({ result }, Date.now() / 1000 - fetchStartSec);
1517
+ this.metrics?.blockInputSync.fetchTime.observe({ result }, Date.now() / 1000 - fetchStartSec);
1313
1518
  this.metrics?.blockInputSync.fetchPeers.set({ result }, i);
1314
1519
  return cacheItem;
1315
1520
  }
@@ -1336,7 +1541,7 @@ export class BlockInputSync {
1336
1541
  throw new Error(`${message} Missing column indices=${prettyPrintIndices(missing)}.`);
1337
1542
  }
1338
1543
  }
1339
- this.metrics?.blockInputSync.fetchTimeSec.observe({ result: FetchResult.FailureMaxAttempts }, Date.now() / 1000 - fetchStartSec);
1544
+ this.metrics?.blockInputSync.fetchTime.observe({ result: FetchResult.FailureMaxAttempts }, Date.now() / 1000 - fetchStartSec);
1340
1545
  this.metrics?.blockInputSync.fetchPeers.set({ result: FetchResult.FailureMaxAttempts }, i - 1);
1341
1546
  throw Error(message);
1342
1547
  }