@lodestar/beacon-node 1.43.0-dev.6b7eebbf6d → 1.43.0-dev.6f485b1b61

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 (288) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +16 -5
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
  5. package/lib/api/impl/beacon/pool/index.js +45 -2
  6. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  7. package/lib/api/impl/debug/index.d.ts.map +1 -1
  8. package/lib/api/impl/debug/index.js +0 -1
  9. package/lib/api/impl/debug/index.js.map +1 -1
  10. package/lib/api/impl/lodestar/index.js +1 -1
  11. package/lib/api/impl/lodestar/index.js.map +1 -1
  12. package/lib/api/impl/validator/index.d.ts.map +1 -1
  13. package/lib/api/impl/validator/index.js +68 -2
  14. package/lib/api/impl/validator/index.js.map +1 -1
  15. package/lib/chain/blocks/blockInput/blockInput.d.ts +3 -0
  16. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  17. package/lib/chain/blocks/blockInput/blockInput.js +4 -1
  18. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  19. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  20. package/lib/chain/blocks/importBlock.js +16 -28
  21. package/lib/chain/blocks/importBlock.js.map +1 -1
  22. package/lib/chain/blocks/importExecutionPayload.d.ts +23 -6
  23. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  24. package/lib/chain/blocks/importExecutionPayload.js +57 -24
  25. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  26. package/lib/chain/blocks/index.d.ts +5 -3
  27. package/lib/chain/blocks/index.d.ts.map +1 -1
  28. package/lib/chain/blocks/index.js +58 -25
  29. package/lib/chain/blocks/index.js.map +1 -1
  30. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +12 -1
  31. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
  32. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +28 -2
  33. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
  34. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +17 -0
  35. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
  36. package/lib/chain/blocks/payloadEnvelopeProcessor.js +2 -2
  37. package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
  38. package/lib/chain/blocks/types.d.ts +4 -3
  39. package/lib/chain/blocks/types.d.ts.map +1 -1
  40. package/lib/chain/blocks/utils/chainSegment.d.ts +23 -2
  41. package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
  42. package/lib/chain/blocks/utils/chainSegment.js +89 -12
  43. package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
  44. package/lib/chain/blocks/verifyBlock.d.ts +5 -3
  45. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  46. package/lib/chain/blocks/verifyBlock.js +50 -7
  47. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  48. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +0 -4
  49. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  50. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +5 -2
  51. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  52. package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts +2 -1
  53. package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
  54. package/lib/chain/blocks/verifyBlocksSanityChecks.js +25 -5
  55. package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
  56. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +2 -2
  57. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -1
  58. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +12 -8
  59. package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -1
  60. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -1
  61. package/lib/chain/blocks/verifyPayloadsDataAvailability.js +8 -3
  62. package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -1
  63. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts.map +1 -1
  64. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js +1 -10
  65. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js.map +1 -1
  66. package/lib/chain/chain.d.ts +5 -3
  67. package/lib/chain/chain.d.ts.map +1 -1
  68. package/lib/chain/chain.js +42 -12
  69. package/lib/chain/chain.js.map +1 -1
  70. package/lib/chain/emitter.d.ts +0 -11
  71. package/lib/chain/emitter.d.ts.map +1 -1
  72. package/lib/chain/emitter.js +0 -4
  73. package/lib/chain/emitter.js.map +1 -1
  74. package/lib/chain/errors/blockError.d.ts +8 -1
  75. package/lib/chain/errors/blockError.d.ts.map +1 -1
  76. package/lib/chain/errors/blockError.js +2 -0
  77. package/lib/chain/errors/blockError.js.map +1 -1
  78. package/lib/chain/errors/executionPayloadBid.d.ts +5 -0
  79. package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
  80. package/lib/chain/errors/executionPayloadBid.js +1 -0
  81. package/lib/chain/errors/executionPayloadBid.js.map +1 -1
  82. package/lib/chain/errors/index.d.ts +1 -0
  83. package/lib/chain/errors/index.d.ts.map +1 -1
  84. package/lib/chain/errors/index.js +1 -0
  85. package/lib/chain/errors/index.js.map +1 -1
  86. package/lib/chain/errors/proposerPreferences.d.ts +40 -0
  87. package/lib/chain/errors/proposerPreferences.d.ts.map +1 -0
  88. package/lib/chain/errors/proposerPreferences.js +14 -0
  89. package/lib/chain/errors/proposerPreferences.js.map +1 -0
  90. package/lib/chain/initState.d.ts.map +1 -1
  91. package/lib/chain/initState.js +6 -1
  92. package/lib/chain/initState.js.map +1 -1
  93. package/lib/chain/interface.d.ts +5 -3
  94. package/lib/chain/interface.d.ts.map +1 -1
  95. package/lib/chain/interface.js.map +1 -1
  96. package/lib/chain/opPools/payloadAttestationPool.d.ts +3 -2
  97. package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -1
  98. package/lib/chain/opPools/payloadAttestationPool.js +26 -4
  99. package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
  100. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  101. package/lib/chain/prepareNextSlot.js +31 -13
  102. package/lib/chain/prepareNextSlot.js.map +1 -1
  103. package/lib/chain/produceBlock/produceBlockBody.d.ts +11 -1
  104. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  105. package/lib/chain/produceBlock/produceBlockBody.js +47 -15
  106. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  107. package/lib/chain/regen/interface.d.ts +1 -0
  108. package/lib/chain/regen/interface.d.ts.map +1 -1
  109. package/lib/chain/regen/interface.js +1 -0
  110. package/lib/chain/regen/interface.js.map +1 -1
  111. package/lib/chain/regen/queued.d.ts.map +1 -1
  112. package/lib/chain/regen/queued.js +1 -4
  113. package/lib/chain/regen/queued.js.map +1 -1
  114. package/lib/chain/regen/regen.d.ts.map +1 -1
  115. package/lib/chain/regen/regen.js +1 -4
  116. package/lib/chain/regen/regen.js.map +1 -1
  117. package/lib/chain/seenCache/index.d.ts +1 -0
  118. package/lib/chain/seenCache/index.d.ts.map +1 -1
  119. package/lib/chain/seenCache/index.js +1 -0
  120. package/lib/chain/seenCache/index.js.map +1 -1
  121. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +24 -7
  122. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
  123. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +69 -17
  124. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
  125. package/lib/chain/seenCache/seenProposerPreferences.d.ts +16 -0
  126. package/lib/chain/seenCache/seenProposerPreferences.d.ts.map +1 -0
  127. package/lib/chain/seenCache/seenProposerPreferences.js +26 -0
  128. package/lib/chain/seenCache/seenProposerPreferences.js.map +1 -0
  129. package/lib/chain/validation/block.d.ts.map +1 -1
  130. package/lib/chain/validation/block.js +1 -0
  131. package/lib/chain/validation/block.js.map +1 -1
  132. package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
  133. package/lib/chain/validation/executionPayloadBid.js +24 -9
  134. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  135. package/lib/chain/validation/proposerPreferences.d.ts +8 -0
  136. package/lib/chain/validation/proposerPreferences.d.ts.map +1 -0
  137. package/lib/chain/validation/proposerPreferences.js +91 -0
  138. package/lib/chain/validation/proposerPreferences.js.map +1 -0
  139. package/lib/metrics/metrics/lodestar.d.ts +1 -0
  140. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  141. package/lib/metrics/metrics/lodestar.js +4 -0
  142. package/lib/metrics/metrics/lodestar.js.map +1 -1
  143. package/lib/network/gossip/interface.d.ts +7 -1
  144. package/lib/network/gossip/interface.d.ts.map +1 -1
  145. package/lib/network/gossip/interface.js +1 -0
  146. package/lib/network/gossip/interface.js.map +1 -1
  147. package/lib/network/gossip/scoringParameters.d.ts.map +1 -1
  148. package/lib/network/gossip/scoringParameters.js +12 -1
  149. package/lib/network/gossip/scoringParameters.js.map +1 -1
  150. package/lib/network/gossip/topic.d.ts +10 -0
  151. package/lib/network/gossip/topic.d.ts.map +1 -1
  152. package/lib/network/gossip/topic.js +6 -0
  153. package/lib/network/gossip/topic.js.map +1 -1
  154. package/lib/network/interface.d.ts +1 -0
  155. package/lib/network/interface.d.ts.map +1 -1
  156. package/lib/network/network.d.ts +1 -0
  157. package/lib/network/network.d.ts.map +1 -1
  158. package/lib/network/network.js +5 -0
  159. package/lib/network/network.js.map +1 -1
  160. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  161. package/lib/network/processor/gossipHandlers.js +38 -16
  162. package/lib/network/processor/gossipHandlers.js.map +1 -1
  163. package/lib/network/processor/gossipQueues/index.d.ts.map +1 -1
  164. package/lib/network/processor/gossipQueues/index.js +5 -0
  165. package/lib/network/processor/gossipQueues/index.js.map +1 -1
  166. package/lib/network/processor/index.d.ts.map +1 -1
  167. package/lib/network/processor/index.js +6 -5
  168. package/lib/network/processor/index.js.map +1 -1
  169. package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
  170. package/lib/network/reqresp/handlers/beaconBlocksByRange.js +14 -6
  171. package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
  172. package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts.map +1 -1
  173. package/lib/network/reqresp/handlers/blobSidecarsByRange.js +11 -5
  174. package/lib/network/reqresp/handlers/blobSidecarsByRange.js.map +1 -1
  175. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
  176. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +17 -5
  177. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
  178. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -1
  179. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +7 -4
  180. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
  181. package/lib/node/nodejs.js +2 -2
  182. package/lib/node/nodejs.js.map +1 -1
  183. package/lib/sync/constants.d.ts +3 -1
  184. package/lib/sync/constants.d.ts.map +1 -1
  185. package/lib/sync/constants.js +3 -4
  186. package/lib/sync/constants.js.map +1 -1
  187. package/lib/sync/range/batch.d.ts +35 -5
  188. package/lib/sync/range/batch.d.ts.map +1 -1
  189. package/lib/sync/range/batch.js +240 -59
  190. package/lib/sync/range/batch.js.map +1 -1
  191. package/lib/sync/range/chain.d.ts +19 -4
  192. package/lib/sync/range/chain.d.ts.map +1 -1
  193. package/lib/sync/range/chain.js +64 -11
  194. package/lib/sync/range/chain.js.map +1 -1
  195. package/lib/sync/range/range.d.ts.map +1 -1
  196. package/lib/sync/range/range.js +31 -9
  197. package/lib/sync/range/range.js.map +1 -1
  198. package/lib/sync/sync.d.ts.map +1 -1
  199. package/lib/sync/sync.js +13 -0
  200. package/lib/sync/sync.js.map +1 -1
  201. package/lib/sync/types.d.ts +34 -0
  202. package/lib/sync/types.d.ts.map +1 -1
  203. package/lib/sync/types.js +34 -0
  204. package/lib/sync/types.js.map +1 -1
  205. package/lib/sync/unknownBlock.d.ts +29 -1
  206. package/lib/sync/unknownBlock.d.ts.map +1 -1
  207. package/lib/sync/unknownBlock.js +738 -61
  208. package/lib/sync/unknownBlock.js.map +1 -1
  209. package/lib/sync/utils/downloadByRange.d.ts +67 -10
  210. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  211. package/lib/sync/utils/downloadByRange.js +211 -26
  212. package/lib/sync/utils/downloadByRange.js.map +1 -1
  213. package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
  214. package/lib/sync/utils/downloadByRoot.js +16 -2
  215. package/lib/sync/utils/downloadByRoot.js.map +1 -1
  216. package/lib/sync/utils/pendingBlocksTree.d.ts +0 -1
  217. package/lib/sync/utils/pendingBlocksTree.d.ts.map +1 -1
  218. package/lib/sync/utils/pendingBlocksTree.js +0 -9
  219. package/lib/sync/utils/pendingBlocksTree.js.map +1 -1
  220. package/lib/util/sszBytes.d.ts.map +1 -1
  221. package/lib/util/sszBytes.js +8 -6
  222. package/lib/util/sszBytes.js.map +1 -1
  223. package/package.json +16 -15
  224. package/src/api/impl/beacon/blocks/index.ts +21 -5
  225. package/src/api/impl/beacon/pool/index.ts +83 -1
  226. package/src/api/impl/debug/index.ts +0 -1
  227. package/src/api/impl/lodestar/index.ts +1 -1
  228. package/src/api/impl/validator/index.ts +82 -1
  229. package/src/chain/blocks/blockInput/blockInput.ts +4 -1
  230. package/src/chain/blocks/importBlock.ts +16 -48
  231. package/src/chain/blocks/importExecutionPayload.ts +76 -30
  232. package/src/chain/blocks/index.ts +71 -22
  233. package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +37 -3
  234. package/src/chain/blocks/payloadEnvelopeInput/types.ts +18 -0
  235. package/src/chain/blocks/payloadEnvelopeProcessor.ts +2 -2
  236. package/src/chain/blocks/types.ts +4 -3
  237. package/src/chain/blocks/utils/chainSegment.ts +114 -17
  238. package/src/chain/blocks/verifyBlock.ts +70 -9
  239. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +6 -4
  240. package/src/chain/blocks/verifyBlocksSanityChecks.ts +26 -7
  241. package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +16 -8
  242. package/src/chain/blocks/verifyPayloadsDataAvailability.ts +7 -4
  243. package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +8 -17
  244. package/src/chain/chain.ts +55 -10
  245. package/src/chain/emitter.ts +0 -11
  246. package/src/chain/errors/blockError.ts +4 -1
  247. package/src/chain/errors/executionPayloadBid.ts +6 -0
  248. package/src/chain/errors/index.ts +1 -0
  249. package/src/chain/errors/proposerPreferences.ts +47 -0
  250. package/src/chain/initState.ts +9 -1
  251. package/src/chain/interface.ts +9 -1
  252. package/src/chain/opPools/payloadAttestationPool.ts +29 -8
  253. package/src/chain/prepareNextSlot.ts +36 -14
  254. package/src/chain/produceBlock/produceBlockBody.ts +57 -14
  255. package/src/chain/regen/interface.ts +1 -0
  256. package/src/chain/regen/queued.ts +2 -7
  257. package/src/chain/regen/regen.ts +2 -7
  258. package/src/chain/seenCache/index.ts +1 -0
  259. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +89 -21
  260. package/src/chain/seenCache/seenProposerPreferences.ts +32 -0
  261. package/src/chain/validation/block.ts +1 -0
  262. package/src/chain/validation/executionPayloadBid.ts +25 -8
  263. package/src/chain/validation/proposerPreferences.ts +110 -0
  264. package/src/metrics/metrics/lodestar.ts +4 -0
  265. package/src/network/gossip/interface.ts +6 -0
  266. package/src/network/gossip/scoringParameters.ts +14 -1
  267. package/src/network/gossip/topic.ts +6 -0
  268. package/src/network/interface.ts +1 -0
  269. package/src/network/network.ts +11 -0
  270. package/src/network/processor/gossipHandlers.ts +53 -17
  271. package/src/network/processor/gossipQueues/index.ts +5 -0
  272. package/src/network/processor/index.ts +6 -5
  273. package/src/network/reqresp/handlers/beaconBlocksByRange.ts +14 -6
  274. package/src/network/reqresp/handlers/blobSidecarsByRange.ts +11 -5
  275. package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +17 -5
  276. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +7 -4
  277. package/src/node/nodejs.ts +2 -2
  278. package/src/sync/constants.ts +4 -4
  279. package/src/sync/range/batch.ts +320 -67
  280. package/src/sync/range/chain.ts +89 -14
  281. package/src/sync/range/range.ts +34 -9
  282. package/src/sync/sync.ts +13 -1
  283. package/src/sync/types.ts +72 -0
  284. package/src/sync/unknownBlock.ts +928 -65
  285. package/src/sync/utils/downloadByRange.ts +378 -39
  286. package/src/sync/utils/downloadByRoot.ts +24 -2
  287. package/src/sync/utils/pendingBlocksTree.ts +0 -15
  288. package/src/util/sszBytes.ts +8 -6
@@ -1,9 +1,11 @@
1
1
  import {ChainForkConfig} from "@lodestar/config";
2
- import {Epoch, Root, Slot} from "@lodestar/types";
3
- import {ErrorAborted, LodestarError, Logger, toRootHex} from "@lodestar/utils";
2
+ import {RequestErrorCode} from "@lodestar/reqresp";
3
+ import {Epoch, Root, Slot, gloas} from "@lodestar/types";
4
+ import {ErrorAborted, LodestarError, Logger, prettyPrintIndices, toRootHex} from "@lodestar/utils";
4
5
  import {isBlockInputBlobs, isBlockInputColumns} from "../../chain/blocks/blockInput/blockInput.js";
5
6
  import {BlockInputErrorCode} from "../../chain/blocks/blockInput/errors.js";
6
7
  import {IBlockInput} from "../../chain/blocks/blockInput/types.js";
8
+ import {PayloadEnvelopeInput} from "../../chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js";
7
9
  import {BlobSidecarErrorCode} from "../../chain/errors/blobSidecarError.js";
8
10
  import {DataColumnSidecarErrorCode} from "../../chain/errors/dataColumnSidecarError.js";
9
11
  import {Metrics} from "../../metrics/metrics.js";
@@ -14,7 +16,12 @@ import {CustodyConfig} from "../../util/dataColumns.js";
14
16
  import {ItTrigger} from "../../util/itTrigger.js";
15
17
  import {PeerIdStr} from "../../util/peerId.js";
16
18
  import {WarnResult, wrapError} from "../../util/wrapError.js";
17
- import {BATCH_BUFFER_SIZE, EPOCHS_PER_BATCH, MAX_LOOK_AHEAD_EPOCHS} from "../constants.js";
19
+ import {
20
+ BATCH_BUFFER_SIZE,
21
+ EPOCHS_PER_BATCH,
22
+ MAX_LOOK_AHEAD_EPOCHS,
23
+ RATE_LIMITED_PEER_BACKOFF_MS,
24
+ } from "../constants.js";
18
25
  import {DownloadByRangeError, DownloadByRangeErrorCode} from "../utils/downloadByRange.js";
19
26
  import {RangeSyncType} from "../utils/remoteSyncType.js";
20
27
  import {Batch, BatchError, BatchErrorCode, BatchMetadata, BatchStatus} from "./batch.js";
@@ -44,13 +51,19 @@ export type SyncChainFns = {
44
51
  * Must return if ALL blocks are processed successfully
45
52
  * If SOME blocks are processed must throw BlockProcessorError()
46
53
  */
47
- processChainSegment: (blocks: IBlockInput[], syncType: RangeSyncType) => Promise<void>;
54
+ processChainSegment: (
55
+ blocks: IBlockInput[],
56
+ payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
57
+ syncType: RangeSyncType
58
+ ) => Promise<void>;
48
59
  /** Must download blocks, and validate their range */
49
60
  downloadByRange: (
50
61
  peer: PeerSyncMeta,
51
62
  batch: Batch,
52
63
  syncType: RangeSyncType
53
- ) => Promise<WarnResult<IBlockInput[], DownloadByRangeError>>;
64
+ ) => Promise<
65
+ WarnResult<{blocks: IBlockInput[]; payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null}, DownloadByRangeError>
66
+ >;
54
67
  /** Report peer for negative actions. Decouples from the full network instance */
55
68
  reportPeer: (peer: PeerIdStr, action: PeerAction, actionName: string) => void;
56
69
  /** Gets current peer custodyColumns and earliestAvailableSlot */
@@ -132,20 +145,32 @@ export class SyncChain {
132
145
  private readonly batchProcessor = new ItTrigger();
133
146
  /** Sorted map of batches undergoing some kind of processing. */
134
147
  private readonly batches = new Map<Epoch, Batch>();
148
+ /**
149
+ * `true` until the first `Batch` is constructed via `includeNextBatch`
150
+ */
151
+ private isFirstBatch = true;
135
152
  private readonly peerset = new Map<PeerIdStr, ChainTarget>();
153
+ /**
154
+ * Tracks peers that have rate-limited us, mapped to the timestamp (ms) until which we should avoid them.
155
+ * This is a sync-layer optimization to avoid assigning batches to backed-off peers.
156
+ * The reqresp SelfRateLimiter independently enforces backoff at the protocol level as a safety net.
157
+ */
158
+ private readonly rateLimitedPeers = new Map<PeerIdStr, number>();
136
159
 
137
160
  private readonly logger: Logger;
138
161
  private readonly config: ChainForkConfig;
139
162
  private readonly clock: IClock;
140
163
  private readonly metrics: Metrics | null;
141
164
  private readonly custodyConfig: CustodyConfig;
165
+ private readonly latestBid: gloas.ExecutionPayloadBid | undefined;
142
166
 
143
167
  constructor(
144
168
  initialBatchEpoch: Epoch,
145
169
  initialTarget: ChainTarget,
146
170
  syncType: RangeSyncType,
147
171
  fns: SyncChainFns,
148
- modules: SyncChainModules
172
+ modules: SyncChainModules,
173
+ latestBid: gloas.ExecutionPayloadBid | undefined
149
174
  ) {
150
175
  const {config, clock, custodyConfig, logger, metrics} = modules;
151
176
  this.firstBatchEpoch = initialBatchEpoch;
@@ -161,6 +186,7 @@ export class SyncChain {
161
186
  this.clock = clock;
162
187
  this.metrics = metrics;
163
188
  this.custodyConfig = custodyConfig;
189
+ this.latestBid = latestBid;
164
190
  this.logger = logger;
165
191
  this.logId = `${syncType}-${nextChainId++}`;
166
192
 
@@ -215,12 +241,14 @@ export class SyncChain {
215
241
  */
216
242
  stopSyncing(): void {
217
243
  this.status = SyncChainStatus.Stopped;
244
+ this.logger.debug("SyncChain stopSyncing", {id: this.logId});
218
245
  }
219
246
 
220
247
  /**
221
248
  * Permanently remove this chain. Throws the main AsyncIterable
222
249
  */
223
250
  remove(): void {
251
+ this.logger.debug("SyncChain remove", {id: this.logId});
224
252
  this.batchProcessor.end(new ErrorAborted("SyncChain"));
225
253
  }
226
254
 
@@ -239,6 +267,7 @@ export class SyncChain {
239
267
  */
240
268
  removePeer(peerId: PeerIdStr): boolean {
241
269
  const deleted = this.peerset.delete(peerId);
270
+ this.rateLimitedPeers.delete(peerId);
242
271
  this.computeTarget();
243
272
  return deleted;
244
273
  }
@@ -374,8 +403,18 @@ export class SyncChain {
374
403
  return;
375
404
  }
376
405
 
406
+ const now = Date.now();
377
407
  const peersSyncInfo: PeerSyncInfo[] = [];
378
408
  for (const [peerId, target] of this.peerset.entries()) {
409
+ // Skip peers that are currently in rate-limit backoff
410
+ const rateLimitedUntil = this.rateLimitedPeers.get(peerId);
411
+ if (rateLimitedUntil !== undefined) {
412
+ if (now < rateLimitedUntil) {
413
+ continue;
414
+ }
415
+ this.rateLimitedPeers.delete(peerId);
416
+ }
417
+
379
418
  try {
380
419
  peersSyncInfo.push({...this.getConnectedPeerSyncMeta(peerId), target});
381
420
  } catch (e) {
@@ -449,7 +488,17 @@ export class SyncChain {
449
488
  return null;
450
489
  }
451
490
 
452
- const batch = new Batch(startEpoch, this.config, this.clock, this.custodyConfig);
491
+ const batch = new Batch(
492
+ startEpoch,
493
+ this.config,
494
+ this.clock,
495
+ this.custodyConfig,
496
+ this.isFirstBatch,
497
+ // `latestBid` is only meaningful for the first batch's parent-payload check
498
+ this.isFirstBatch ? this.latestBid : undefined,
499
+ this.target.slot
500
+ );
501
+ this.isFirstBatch = false;
453
502
  this.batches.set(startEpoch, batch);
454
503
  return batch;
455
504
  }
@@ -507,7 +556,14 @@ export class SyncChain {
507
556
  {id: this.logId, ...batch.getMetadata(), peer: prettyPrintPeerIdStr(peer.peerId)},
508
557
  res.err
509
558
  );
510
- batch.downloadingError(peer.peerId); // Throws after MAX_DOWNLOAD_ATTEMPTS
559
+ if (errCode === RequestErrorCode.RESP_RATE_LIMITED || errCode === RequestErrorCode.REQUEST_SELF_RATE_LIMITED) {
560
+ // Peer rate-limited us — don't count as a failed download attempt and mark peer for backoff
561
+ this.rateLimitedPeers.set(peer.peerId, Date.now() + RATE_LIMITED_PEER_BACKOFF_MS);
562
+ batch.downloadingRateLimited();
563
+ this.triggerBatchDownloader();
564
+ } else {
565
+ batch.downloadingError(peer.peerId); // Throws after MAX_DOWNLOAD_ATTEMPTS
566
+ }
511
567
  } else {
512
568
  this.logger.verbose("Batch download success", {
513
569
  id: this.logId,
@@ -516,7 +572,8 @@ export class SyncChain {
516
572
  });
517
573
  this.metrics?.syncRange.downloadByRange.success.inc();
518
574
  const {warnings, result} = res.result;
519
- const downloadSuccessOutput = batch.downloadingSuccess(peer.peerId, result);
575
+ const {blocks: downloadedBlocks, payloadEnvelopes} = result;
576
+ const downloadSuccessOutput = batch.downloadingSuccess(peer.peerId, downloadedBlocks, payloadEnvelopes);
520
577
  const logMeta: Record<string, number> = {
521
578
  blockCount: downloadSuccessOutput.blocks.length,
522
579
  };
@@ -526,7 +583,7 @@ export class SyncChain {
526
583
  this.metrics?.syncRange.downloadByRange.warn.inc({client: peer.client, code: warning.type.code});
527
584
  this.logger.debug(
528
585
  "Batch downloaded with warning",
529
- {id: this.logId, epoch: batch.startEpoch, ...logMeta, peer: prettyPrintPeerIdStr(peer.peerId)},
586
+ {id: this.logId, ...batch.getMetadata(), ...logMeta, peer: prettyPrintPeerIdStr(peer.peerId)},
530
587
  warning
531
588
  );
532
589
  }
@@ -552,10 +609,17 @@ export class SyncChain {
552
609
  // the flow will continue to call triggerBatchDownloader() below
553
610
  }
554
611
 
612
+ const blockSlots = downloadSuccessOutput.blocks.map((b) => b.slot);
613
+ const envelopeSlots = downloadSuccessOutput.payloadEnvelopes
614
+ ? Array.from(downloadSuccessOutput.payloadEnvelopes.keys())
615
+ : null;
616
+
555
617
  this.logger.debug(logMessage, {
556
618
  id: this.logId,
557
- epoch: batch.startEpoch,
619
+ ...batch.getMetadata(),
558
620
  ...logMeta,
621
+ blockSlots: prettyPrintIndices(blockSlots),
622
+ ...(envelopeSlots ? {envelopeSlots: prettyPrintIndices(envelopeSlots)} : {}),
559
623
  peer: prettyPrintPeerIdStr(peer.peerId),
560
624
  });
561
625
  }
@@ -578,13 +642,24 @@ export class SyncChain {
578
642
  * Sends `batch` to the processor. Note: batch may be empty
579
643
  */
580
644
  private async processBatch(batch: Batch): Promise<void> {
581
- const blocks = batch.startProcessing();
645
+ const {blocks, payloadEnvelopes, peers} = batch.startProcessing();
646
+
647
+ const logCtx = {
648
+ id: this.logId,
649
+ ...batch.getMetadata(),
650
+ blockCount: blocks.length,
651
+ blockSlots: prettyPrintIndices(blocks.map((b) => b.slot)),
652
+ ...(payloadEnvelopes ? {envelopeSlots: prettyPrintIndices(Array.from(payloadEnvelopes.keys()))} : {}),
653
+ peers: peers.map(prettyPrintPeerIdStr).join(","),
654
+ };
655
+ this.logger.verbose("Processing batch", logCtx);
582
656
 
583
657
  // wrapError ensures to never call both batch success() and batch error()
584
- const res = await wrapError(this.processChainSegment(blocks, this.syncType));
658
+ const res = await wrapError(this.processChainSegment(blocks, payloadEnvelopes, this.syncType));
585
659
 
586
660
  if (!res.err) {
587
661
  batch.processingSuccess();
662
+ this.logger.verbose("Processed batch", {...logCtx, ...batch.getMetadata()});
588
663
 
589
664
  // If the processed batch is not empty, validate previous AwaitingValidation blocks.
590
665
  if (blocks.length > 0) {
@@ -594,7 +669,7 @@ export class SyncChain {
594
669
  // Potentially process next AwaitingProcessing batch
595
670
  this.triggerBatchProcessor();
596
671
  } else {
597
- this.logger.verbose("Batch process error", {id: this.logId, ...batch.getMetadata()}, res.err);
672
+ this.logger.verbose("Batch process error", logCtx, res.err);
598
673
  batch.processingError(res.err); // Throws after MAX_BATCH_PROCESSING_ATTEMPTS
599
674
 
600
675
  // At least one block was successfully verified and imported, so we can be sure all
@@ -1,7 +1,7 @@
1
1
  import {EventEmitter} from "node:events";
2
2
  import {StrictEventEmitter} from "strict-event-emitter-types";
3
3
  import {BeaconConfig} from "@lodestar/config";
4
- import {computeStartSlotAtEpoch} from "@lodestar/state-transition";
4
+ import {IBeaconStateViewGloas, computeStartSlotAtEpoch, isStatePostGloas} from "@lodestar/state-transition";
5
5
  import {Epoch, Status, fulu} from "@lodestar/types";
6
6
  import {Logger, toRootHex} from "@lodestar/utils";
7
7
  import {IBlockInput} from "../../chain/blocks/blockInput/types.js";
@@ -172,7 +172,7 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
172
172
  }
173
173
 
174
174
  /** Convenience method for `SyncChain` */
175
- private processChainSegment: SyncChainFns["processChainSegment"] = async (blocks, syncType) => {
175
+ private processChainSegment: SyncChainFns["processChainSegment"] = async (blocks, payloadEnvelopes, syncType) => {
176
176
  // Not trusted, verify signatures
177
177
  const flags: ImportBlockOpts = {
178
178
  // Only skip importing attestations for finalized sync. For head sync attestation are valuable.
@@ -192,30 +192,46 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
192
192
 
193
193
  if (this.opts?.disableProcessAsChainSegment) {
194
194
  // Should only be used for debugging or testing
195
- for (const block of blocks) await this.chain.processBlock(block, flags);
195
+ for (const block of blocks) {
196
+ await this.chain.processBlock(block, flags);
197
+ const payloadEnvelope = payloadEnvelopes?.get(block.slot);
198
+ if (payloadEnvelope) {
199
+ await this.chain.processExecutionPayload(payloadEnvelope);
200
+ }
201
+ }
196
202
  } else {
197
- await this.chain.processChainSegment(blocks, flags);
203
+ await this.chain.processChainSegment(blocks, payloadEnvelopes, flags);
198
204
  }
199
205
  };
200
206
 
201
207
  private downloadByRange: SyncChainFns["downloadByRange"] = async (peer, batch) => {
202
208
  const batchBlocks = batch.getBlocks();
209
+ const requests = batch.getRequestsForPeer(peer);
210
+ const parentRoot = requests.parentPayloadRequest?.envelopeBlockRoot ?? requests.parentPayloadRequest?.blockRoot;
211
+ const parentPayloadCommitments = parentRoot ? batch.getParentPayloadCommitments(parentRoot) : undefined;
203
212
  const {result, warnings} = await downloadByRange({
204
213
  config: this.config,
205
214
  network: this.network,
206
215
  logger: this.logger,
207
216
  peerIdStr: peer.peerId,
208
217
  batchBlocks,
218
+ parentPayloadCommitments,
209
219
  peerDasMetrics: this.chain.metrics?.peerDas,
210
- ...batch.getRequestsForPeer(peer),
220
+ ...requests,
211
221
  });
212
- const cached = cacheByRangeResponses({
222
+ const {responses, payloadEnvelopes: downloadedPayloadEnvelopes} = result;
223
+ const {blocks, payloadEnvelopes} = cacheByRangeResponses({
213
224
  cache: this.chain.seenBlockInputCache,
225
+ seenPayloadEnvelopeInputCache: this.chain.seenPayloadEnvelopeInputCache,
214
226
  peerIdStr: peer.peerId,
215
- responses: result,
227
+ responses,
216
228
  batchBlocks,
229
+ downloadedPayloadEnvelopes,
230
+ existingPayloadEnvelopes: batch.getPayloadEnvelopes(),
231
+ custodyConfig: this.chain.custodyConfig,
232
+ seenTimestampSec: Date.now() / 1000,
217
233
  });
218
- return {result: cached, warnings};
234
+ return {result: {blocks, payloadEnvelopes}, warnings};
219
235
  };
220
236
 
221
237
  private pruneBlockInputs: SyncChainFns["pruneBlockInputs"] = (blocks: IBlockInput[]) => {
@@ -246,6 +262,14 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
246
262
  private addPeerOrCreateChain(startEpoch: Epoch, target: ChainTarget, peer: PeerIdStr, syncType: RangeSyncType): void {
247
263
  let syncChain = this.chains.get(syncType);
248
264
  if (!syncChain) {
265
+ // The first batch of a new sync chain may need to detect whether the parent block was an
266
+ // gloas "empty" block (no envelope produced). It does so by comparing the first
267
+ // downloaded block's `bid.parentBlockHash` against the head state's `latestExecutionPayloadBid.blockHash`.
268
+ const headState = this.chain.getHeadState();
269
+ const latestBid = isStatePostGloas(headState)
270
+ ? (headState as IBeaconStateViewGloas).latestExecutionPayloadBid
271
+ : undefined;
272
+
249
273
  syncChain = new SyncChain(
250
274
  startEpoch,
251
275
  target,
@@ -264,7 +288,8 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
264
288
  logger: this.logger,
265
289
  custodyConfig: this.chain.custodyConfig,
266
290
  metrics: this.metrics,
267
- }
291
+ },
292
+ latestBid
268
293
  );
269
294
  this.chains.set(syncType, syncChain);
270
295
 
package/src/sync/sync.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import {SLOTS_PER_EPOCH} from "@lodestar/params";
2
2
  import {Slot} from "@lodestar/types";
3
- import {Logger} from "@lodestar/utils";
3
+ import {Logger, toRootHex} from "@lodestar/utils";
4
4
  import {IBeaconChain} from "../chain/index.js";
5
5
  import {GENESIS_SLOT} from "../constants/constants.js";
6
6
  import {ExecutionEngineState} from "../execution/index.js";
@@ -188,6 +188,18 @@ export class BeaconSync implements IBeaconSync {
188
188
  private addPeer = (data: NetworkEventData[NetworkEvent.peerConnected]): void => {
189
189
  const localStatus = this.chain.getStatus();
190
190
  const syncType = getPeerSyncType(localStatus, data.status, this.chain.forkChoice, this.slotImportTolerance);
191
+ this.logger.verbose("Peer sync type classified", {
192
+ peer: data.peer,
193
+ syncType,
194
+ localFinalizedEpoch: localStatus.finalizedEpoch,
195
+ localFinalizedRoot: toRootHex(localStatus.finalizedRoot),
196
+ localHeadSlot: localStatus.headSlot,
197
+ localHeadRoot: toRootHex(localStatus.headRoot),
198
+ remoteFinalizedEpoch: data.status.finalizedEpoch,
199
+ remoteFinalizedRoot: toRootHex(data.status.finalizedRoot),
200
+ remoteHeadSlot: data.status.headSlot,
201
+ remoteHeadRoot: toRootHex(data.status.headRoot),
202
+ });
191
203
 
192
204
  // For metrics only
193
205
  this.peerSyncType.set(data.peer, syncType);
package/src/sync/types.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  import {RootHex, Slot} from "@lodestar/types";
2
+ import {SignedExecutionPayloadEnvelope} from "@lodestar/types/gloas";
3
+ import {toRootHex} from "@lodestar/utils";
2
4
  import {IBlockInput} from "../chain/blocks/blockInput/index.js";
5
+ import {PayloadEnvelopeInput} from "../chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js";
3
6
 
4
7
  export enum PendingBlockType {
5
8
  /**
@@ -26,6 +29,14 @@ export enum PendingBlockInputStatus {
26
29
  processing = "processing",
27
30
  }
28
31
 
32
+ export enum PendingPayloadInputStatus {
33
+ pending = "pending",
34
+ fetching = "fetching",
35
+ waitingForBlock = "waiting_for_block",
36
+ downloaded = "downloaded",
37
+ processing = "processing",
38
+ }
39
+
29
40
  export type PendingBlockInput = {
30
41
  status: PendingBlockInputStatus;
31
42
  blockInput: IBlockInput;
@@ -44,10 +55,47 @@ export type PendingRootHex = {
44
55
 
45
56
  export type BlockInputSyncCacheItem = PendingBlockInput | PendingRootHex;
46
57
 
58
+ export type PendingPayloadInput = {
59
+ status:
60
+ | PendingPayloadInputStatus.pending
61
+ | PendingPayloadInputStatus.fetching
62
+ | PendingPayloadInputStatus.downloaded
63
+ | PendingPayloadInputStatus.processing;
64
+ payloadInput: PayloadEnvelopeInput;
65
+ timeAddedSec: number;
66
+ timeSyncedSec?: number;
67
+ peerIdStrings: Set<string>;
68
+ };
69
+
70
+ export type PendingPayloadRootHex = {
71
+ status: PendingPayloadInputStatus.pending | PendingPayloadInputStatus.fetching;
72
+ rootHex: RootHex;
73
+ timeAddedSec: number;
74
+ timeSyncedSec?: number;
75
+ peerIdStrings: Set<string>;
76
+ };
77
+
78
+ export type PendingPayloadEnvelope = {
79
+ status: PendingPayloadInputStatus.waitingForBlock;
80
+ envelope: SignedExecutionPayloadEnvelope;
81
+ timeAddedSec: number;
82
+ peerIdStrings: Set<string>;
83
+ };
84
+
85
+ export type PayloadSyncCacheItem = PendingPayloadInput | PendingPayloadRootHex | PendingPayloadEnvelope;
86
+
47
87
  export function isPendingBlockInput(pending: BlockInputSyncCacheItem): pending is PendingBlockInput {
48
88
  return "blockInput" in pending;
49
89
  }
50
90
 
91
+ export function isPendingPayloadInput(pending: PayloadSyncCacheItem): pending is PendingPayloadInput {
92
+ return "payloadInput" in pending;
93
+ }
94
+
95
+ export function isPendingPayloadEnvelope(pending: PayloadSyncCacheItem): pending is PendingPayloadEnvelope {
96
+ return "envelope" in pending;
97
+ }
98
+
51
99
  export function getBlockInputSyncCacheItemRootHex(block: BlockInputSyncCacheItem): RootHex {
52
100
  return isPendingBlockInput(block) ? block.blockInput.blockRootHex : block.rootHex;
53
101
  }
@@ -55,3 +103,27 @@ export function getBlockInputSyncCacheItemRootHex(block: BlockInputSyncCacheItem
55
103
  export function getBlockInputSyncCacheItemSlot(block: BlockInputSyncCacheItem): Slot | string {
56
104
  return isPendingBlockInput(block) ? block.blockInput.slot : "unknown";
57
105
  }
106
+
107
+ export function getPayloadSyncCacheItemRootHex(payload: PayloadSyncCacheItem): RootHex {
108
+ if (isPendingPayloadInput(payload)) {
109
+ return payload.payloadInput.blockRootHex;
110
+ }
111
+
112
+ if (isPendingPayloadEnvelope(payload)) {
113
+ return toRootHex(payload.envelope.message.beaconBlockRoot);
114
+ }
115
+
116
+ return payload.rootHex;
117
+ }
118
+
119
+ export function getPayloadSyncCacheItemSlot(payload: PayloadSyncCacheItem): Slot | string {
120
+ if (isPendingPayloadInput(payload)) {
121
+ return payload.payloadInput.slot;
122
+ }
123
+
124
+ if (isPendingPayloadEnvelope(payload)) {
125
+ return payload.envelope.message.payload.slotNumber;
126
+ }
127
+
128
+ return "unknown";
129
+ }