@lodestar/beacon-node 1.50.0-dev.335476095e → 1.50.0-dev.3430a7cf04

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 (289) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +7 -2
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/beacon/state/index.d.ts.map +1 -1
  5. package/lib/api/impl/beacon/state/index.js +28 -6
  6. package/lib/api/impl/beacon/state/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 +26 -18
  9. package/lib/api/impl/debug/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 +63 -17
  12. package/lib/api/impl/validator/index.js.map +1 -1
  13. package/lib/chain/ColumnReconstructionTracker.d.ts +0 -2
  14. package/lib/chain/ColumnReconstructionTracker.d.ts.map +1 -1
  15. package/lib/chain/ColumnReconstructionTracker.js +4 -5
  16. package/lib/chain/ColumnReconstructionTracker.js.map +1 -1
  17. package/lib/chain/archiveStore/archiveStore.d.ts +5 -0
  18. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  19. package/lib/chain/archiveStore/archiveStore.js +13 -23
  20. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  21. package/lib/chain/archiveStore/utils/pruneHistory.d.ts +1 -1
  22. package/lib/chain/archiveStore/utils/pruneHistory.d.ts.map +1 -1
  23. package/lib/chain/archiveStore/utils/pruneHistory.js +2 -1
  24. package/lib/chain/archiveStore/utils/pruneHistory.js.map +1 -1
  25. package/lib/chain/beaconProposerCache.d.ts +6 -0
  26. package/lib/chain/beaconProposerCache.d.ts.map +1 -1
  27. package/lib/chain/beaconProposerCache.js +16 -0
  28. package/lib/chain/beaconProposerCache.js.map +1 -1
  29. package/lib/chain/blocks/blockInput/blockInput.d.ts +1 -1
  30. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  31. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  32. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  33. package/lib/chain/blocks/importBlock.js +21 -12
  34. package/lib/chain/blocks/importBlock.js.map +1 -1
  35. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  36. package/lib/chain/blocks/verifyBlock.js +6 -6
  37. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  38. package/lib/chain/chain.d.ts +4 -1
  39. package/lib/chain/chain.d.ts.map +1 -1
  40. package/lib/chain/chain.js +65 -22
  41. package/lib/chain/chain.js.map +1 -1
  42. package/lib/chain/interface.d.ts +4 -1
  43. package/lib/chain/interface.d.ts.map +1 -1
  44. package/lib/chain/opPools/aggregatedAttestationPool.d.ts +4 -2
  45. package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
  46. package/lib/chain/opPools/aggregatedAttestationPool.js +30 -8
  47. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  48. package/lib/chain/opPools/opPool.d.ts.map +1 -1
  49. package/lib/chain/opPools/opPool.js +1 -23
  50. package/lib/chain/opPools/opPool.js.map +1 -1
  51. package/lib/chain/opPools/proposerPreferencesPool.d.ts +4 -0
  52. package/lib/chain/opPools/proposerPreferencesPool.d.ts.map +1 -1
  53. package/lib/chain/opPools/proposerPreferencesPool.js +13 -1
  54. package/lib/chain/opPools/proposerPreferencesPool.js.map +1 -1
  55. package/lib/chain/opPools/utils.d.ts +11 -0
  56. package/lib/chain/opPools/utils.d.ts.map +1 -1
  57. package/lib/chain/opPools/utils.js +22 -0
  58. package/lib/chain/opPools/utils.js.map +1 -1
  59. package/lib/chain/options.d.ts +1 -0
  60. package/lib/chain/options.d.ts.map +1 -1
  61. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  62. package/lib/chain/prepareNextSlot.js +15 -6
  63. package/lib/chain/prepareNextSlot.js.map +1 -1
  64. package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
  65. package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
  66. package/lib/chain/produceBlock/produceBlockBody.d.ts +8 -0
  67. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  68. package/lib/chain/produceBlock/produceBlockBody.js +48 -34
  69. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  70. package/lib/chain/reprocess.d.ts +2 -1
  71. package/lib/chain/reprocess.d.ts.map +1 -1
  72. package/lib/chain/reprocess.js +2 -1
  73. package/lib/chain/reprocess.js.map +1 -1
  74. package/lib/chain/seenCache/seenGossipBlockInput.d.ts +7 -0
  75. package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
  76. package/lib/chain/seenCache/seenGossipBlockInput.js +22 -1
  77. package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
  78. package/lib/chain/shufflingCache.d.ts +18 -8
  79. package/lib/chain/shufflingCache.d.ts.map +1 -1
  80. package/lib/chain/shufflingCache.js +72 -18
  81. package/lib/chain/shufflingCache.js.map +1 -1
  82. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  83. package/lib/chain/stateCache/persistentCheckpointsCache.js +1 -1
  84. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  85. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  86. package/lib/chain/validatorMonitor.js +6 -4
  87. package/lib/chain/validatorMonitor.js.map +1 -1
  88. package/lib/constants/constants.d.ts +1 -0
  89. package/lib/constants/constants.d.ts.map +1 -1
  90. package/lib/constants/constants.js +1 -0
  91. package/lib/constants/constants.js.map +1 -1
  92. package/lib/db/beacon.d.ts +4 -1
  93. package/lib/db/beacon.d.ts.map +1 -1
  94. package/lib/db/beacon.js +6 -1
  95. package/lib/db/beacon.js.map +1 -1
  96. package/lib/db/buckets.d.ts +3 -1
  97. package/lib/db/buckets.d.ts.map +1 -1
  98. package/lib/db/buckets.js +2 -0
  99. package/lib/db/buckets.js.map +1 -1
  100. package/lib/db/interface.d.ts +4 -1
  101. package/lib/db/interface.d.ts.map +1 -1
  102. package/lib/db/repositories/blockArchive.js +2 -2
  103. package/lib/db/repositories/blockArchive.js.map +1 -1
  104. package/lib/db/repositories/blockArchiveIndex.d.ts +3 -3
  105. package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
  106. package/lib/db/repositories/blockArchiveIndex.js +1 -2
  107. package/lib/db/repositories/blockArchiveIndex.js.map +1 -1
  108. package/lib/db/repositories/earliestAvailableSlot.d.ts +11 -0
  109. package/lib/db/repositories/earliestAvailableSlot.d.ts.map +1 -0
  110. package/lib/db/repositories/earliestAvailableSlot.js +19 -0
  111. package/lib/db/repositories/earliestAvailableSlot.js.map +1 -0
  112. package/lib/db/repositories/index.d.ts +1 -0
  113. package/lib/db/repositories/index.d.ts.map +1 -1
  114. package/lib/db/repositories/index.js +1 -0
  115. package/lib/db/repositories/index.js.map +1 -1
  116. package/lib/db/repositories/proposerPreferences.d.ts +14 -0
  117. package/lib/db/repositories/proposerPreferences.d.ts.map +1 -0
  118. package/lib/db/repositories/proposerPreferences.js +21 -0
  119. package/lib/db/repositories/proposerPreferences.js.map +1 -0
  120. package/lib/execution/engine/blobVersionedHashes.d.ts +9 -0
  121. package/lib/execution/engine/blobVersionedHashes.d.ts.map +1 -0
  122. package/lib/execution/engine/blobVersionedHashes.js +74 -0
  123. package/lib/execution/engine/blobVersionedHashes.js.map +1 -0
  124. package/lib/execution/engine/http.d.ts +45 -13
  125. package/lib/execution/engine/http.d.ts.map +1 -1
  126. package/lib/execution/engine/http.js +236 -198
  127. package/lib/execution/engine/http.js.map +1 -1
  128. package/lib/execution/engine/index.d.ts +3 -2
  129. package/lib/execution/engine/index.d.ts.map +1 -1
  130. package/lib/execution/engine/index.js +33 -8
  131. package/lib/execution/engine/index.js.map +1 -1
  132. package/lib/execution/engine/interface.d.ts +1 -1
  133. package/lib/execution/engine/interface.d.ts.map +1 -1
  134. package/lib/execution/engine/jsonRpcTransport.d.ts +25 -0
  135. package/lib/execution/engine/jsonRpcTransport.d.ts.map +1 -0
  136. package/lib/execution/engine/jsonRpcTransport.js +158 -0
  137. package/lib/execution/engine/jsonRpcTransport.js.map +1 -0
  138. package/lib/execution/engine/restHttpClient.d.ts +71 -0
  139. package/lib/execution/engine/restHttpClient.d.ts.map +1 -0
  140. package/lib/execution/engine/restHttpClient.js +201 -0
  141. package/lib/execution/engine/restHttpClient.js.map +1 -0
  142. package/lib/execution/engine/restTransport.d.ts +46 -0
  143. package/lib/execution/engine/restTransport.d.ts.map +1 -0
  144. package/lib/execution/engine/restTransport.js +399 -0
  145. package/lib/execution/engine/restTransport.js.map +1 -0
  146. package/lib/execution/engine/sszTypes.d.ts +1261 -0
  147. package/lib/execution/engine/sszTypes.d.ts.map +1 -0
  148. package/lib/execution/engine/sszTypes.js +216 -0
  149. package/lib/execution/engine/sszTypes.js.map +1 -0
  150. package/lib/execution/engine/transport.d.ts +39 -0
  151. package/lib/execution/engine/transport.d.ts.map +1 -0
  152. package/lib/execution/engine/transport.js +2 -0
  153. package/lib/execution/engine/transport.js.map +1 -0
  154. package/lib/execution/engine/types.d.ts +2 -0
  155. package/lib/execution/engine/types.d.ts.map +1 -1
  156. package/lib/execution/engine/types.js +31 -63
  157. package/lib/execution/engine/types.js.map +1 -1
  158. package/lib/execution/engine/utils.d.ts.map +1 -1
  159. package/lib/execution/engine/utils.js +9 -2
  160. package/lib/execution/engine/utils.js.map +1 -1
  161. package/lib/metrics/metrics/lodestar.d.ts +10 -0
  162. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  163. package/lib/metrics/metrics/lodestar.js +22 -0
  164. package/lib/metrics/metrics/lodestar.js.map +1 -1
  165. package/lib/network/core/events.d.ts +5 -1
  166. package/lib/network/core/events.d.ts.map +1 -1
  167. package/lib/network/core/events.js +8 -0
  168. package/lib/network/core/events.js.map +1 -1
  169. package/lib/network/gossip/topic.d.ts +0 -14
  170. package/lib/network/gossip/topic.d.ts.map +1 -1
  171. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  172. package/lib/network/processor/gossipHandlers.js +60 -64
  173. package/lib/network/processor/gossipHandlers.js.map +1 -1
  174. package/lib/network/processor/index.js +3 -3
  175. package/lib/network/processor/index.js.map +1 -1
  176. package/lib/network/reqresp/rateLimit.js +2 -2
  177. package/lib/network/reqresp/rateLimit.js.map +1 -1
  178. package/lib/network/subnets/attnetsService.d.ts.map +1 -1
  179. package/lib/network/subnets/attnetsService.js +3 -1
  180. package/lib/network/subnets/attnetsService.js.map +1 -1
  181. package/lib/node/nodejs.d.ts +3 -1
  182. package/lib/node/nodejs.d.ts.map +1 -1
  183. package/lib/node/nodejs.js +2 -1
  184. package/lib/node/nodejs.js.map +1 -1
  185. package/lib/node/notifier.d.ts.map +1 -1
  186. package/lib/node/notifier.js +12 -13
  187. package/lib/node/notifier.js.map +1 -1
  188. package/lib/node/options.d.ts +3 -2
  189. package/lib/node/options.d.ts.map +1 -1
  190. package/lib/node/options.js +2 -2
  191. package/lib/node/options.js.map +1 -1
  192. package/lib/sync/range/batch.d.ts +5 -5
  193. package/lib/sync/range/batch.d.ts.map +1 -1
  194. package/lib/sync/range/batch.js +11 -17
  195. package/lib/sync/range/batch.js.map +1 -1
  196. package/lib/sync/range/chain.d.ts +4 -4
  197. package/lib/sync/range/chain.d.ts.map +1 -1
  198. package/lib/sync/range/chain.js +7 -5
  199. package/lib/sync/range/chain.js.map +1 -1
  200. package/lib/sync/range/range.d.ts.map +1 -1
  201. package/lib/sync/range/range.js +25 -11
  202. package/lib/sync/range/range.js.map +1 -1
  203. package/lib/sync/unknownBlock.d.ts +5 -2
  204. package/lib/sync/unknownBlock.d.ts.map +1 -1
  205. package/lib/sync/unknownBlock.js +47 -22
  206. package/lib/sync/unknownBlock.js.map +1 -1
  207. package/lib/sync/utils/downloadByRange.d.ts +38 -14
  208. package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
  209. package/lib/sync/utils/downloadByRange.js +84 -39
  210. package/lib/sync/utils/downloadByRange.js.map +1 -1
  211. package/lib/util/asyncIterableToEvents.d.ts +10 -2
  212. package/lib/util/asyncIterableToEvents.d.ts.map +1 -1
  213. package/lib/util/asyncIterableToEvents.js +29 -3
  214. package/lib/util/asyncIterableToEvents.js.map +1 -1
  215. package/lib/util/clock.d.ts.map +1 -1
  216. package/lib/util/clock.js +3 -4
  217. package/lib/util/clock.js.map +1 -1
  218. package/lib/util/metadata.d.ts.map +1 -1
  219. package/lib/util/metadata.js +2 -1
  220. package/lib/util/metadata.js.map +1 -1
  221. package/lib/util/sszBytes.d.ts +2 -2
  222. package/lib/util/sszBytes.d.ts.map +1 -1
  223. package/lib/util/sszBytes.js +22 -14
  224. package/lib/util/sszBytes.js.map +1 -1
  225. package/package.json +17 -16
  226. package/src/api/impl/beacon/blocks/index.ts +10 -3
  227. package/src/api/impl/beacon/state/index.ts +43 -6
  228. package/src/api/impl/debug/index.ts +28 -19
  229. package/src/api/impl/validator/index.ts +86 -19
  230. package/src/chain/ColumnReconstructionTracker.ts +4 -6
  231. package/src/chain/archiveStore/archiveStore.ts +18 -24
  232. package/src/chain/archiveStore/utils/pruneHistory.ts +4 -1
  233. package/src/chain/beaconProposerCache.ts +19 -1
  234. package/src/chain/blocks/blockInput/blockInput.ts +1 -1
  235. package/src/chain/blocks/importBlock.ts +25 -11
  236. package/src/chain/blocks/verifyBlock.ts +7 -6
  237. package/src/chain/chain.ts +88 -21
  238. package/src/chain/interface.ts +5 -1
  239. package/src/chain/opPools/aggregatedAttestationPool.ts +34 -10
  240. package/src/chain/opPools/opPool.ts +1 -31
  241. package/src/chain/opPools/proposerPreferencesPool.ts +20 -1
  242. package/src/chain/opPools/utils.ts +31 -0
  243. package/src/chain/options.ts +1 -1
  244. package/src/chain/prepareNextSlot.ts +22 -6
  245. package/src/chain/produceBlock/computeNewStateRoot.ts +9 -2
  246. package/src/chain/produceBlock/produceBlockBody.ts +78 -39
  247. package/src/chain/reprocess.ts +2 -1
  248. package/src/chain/seenCache/seenGossipBlockInput.ts +25 -1
  249. package/src/chain/shufflingCache.ts +84 -22
  250. package/src/chain/stateCache/persistentCheckpointsCache.ts +4 -1
  251. package/src/chain/validatorMonitor.ts +7 -4
  252. package/src/constants/constants.ts +1 -0
  253. package/src/db/beacon.ts +6 -0
  254. package/src/db/buckets.ts +2 -0
  255. package/src/db/interface.ts +4 -0
  256. package/src/db/repositories/blockArchive.ts +2 -2
  257. package/src/db/repositories/blockArchiveIndex.ts +2 -3
  258. package/src/db/repositories/earliestAvailableSlot.ts +19 -0
  259. package/src/db/repositories/index.ts +1 -0
  260. package/src/db/repositories/proposerPreferences.ts +23 -0
  261. package/src/execution/engine/blobVersionedHashes.ts +72 -0
  262. package/src/execution/engine/http.ts +304 -271
  263. package/src/execution/engine/index.ts +41 -7
  264. package/src/execution/engine/interface.ts +1 -1
  265. package/src/execution/engine/jsonRpcTransport.ts +247 -0
  266. package/src/execution/engine/restHttpClient.ts +269 -0
  267. package/src/execution/engine/restTransport.ts +544 -0
  268. package/src/execution/engine/sszTypes.ts +354 -0
  269. package/src/execution/engine/transport.ts +61 -0
  270. package/src/execution/engine/types.ts +42 -80
  271. package/src/execution/engine/utils.ts +12 -2
  272. package/src/metrics/metrics/lodestar.ts +23 -0
  273. package/src/network/core/events.ts +16 -1
  274. package/src/network/processor/gossipHandlers.ts +91 -77
  275. package/src/network/processor/index.ts +3 -3
  276. package/src/network/reqresp/rateLimit.ts +2 -2
  277. package/src/network/subnets/attnetsService.ts +8 -3
  278. package/src/node/nodejs.ts +4 -0
  279. package/src/node/notifier.ts +14 -13
  280. package/src/node/options.ts +10 -1
  281. package/src/sync/range/batch.ts +14 -19
  282. package/src/sync/range/chain.ts +9 -7
  283. package/src/sync/range/range.ts +26 -12
  284. package/src/sync/unknownBlock.ts +60 -23
  285. package/src/sync/utils/downloadByRange.ts +123 -58
  286. package/src/util/asyncIterableToEvents.ts +44 -5
  287. package/src/util/clock.ts +3 -4
  288. package/src/util/metadata.ts +2 -1
  289. package/src/util/sszBytes.ts +25 -12
@@ -1,5 +1,5 @@
1
1
  import {ChainForkConfig} from "@lodestar/config";
2
- import {Epoch, Root, Slot, gloas} from "@lodestar/types";
2
+ import {Epoch, Root, Slot} from "@lodestar/types";
3
3
  import {ErrorAborted, LodestarError, Logger, prettyPrintIndices, toRootHex} from "@lodestar/utils";
4
4
  import {isBlockInputBlobs, isBlockInputColumns} from "../../chain/blocks/blockInput/blockInput.js";
5
5
  import {BlockInputErrorCode} from "../../chain/blocks/blockInput/errors.js";
@@ -16,7 +16,7 @@ import {ItTrigger} from "../../util/itTrigger.js";
16
16
  import {PeerIdStr} from "../../util/peerId.js";
17
17
  import {WarnResult, wrapError} from "../../util/wrapError.js";
18
18
  import {BATCH_BUFFER_SIZE, EPOCHS_PER_BATCH, MAX_LOOK_AHEAD_EPOCHS} from "../constants.js";
19
- import {DownloadByRangeError, DownloadByRangeErrorCode} from "../utils/downloadByRange.js";
19
+ import {DownloadByRangeError, DownloadByRangeErrorCode, ParentPayload} from "../utils/downloadByRange.js";
20
20
  import {getRateLimitedUntilMs} from "../utils/rateLimit.js";
21
21
  import {RangeSyncType} from "../utils/remoteSyncType.js";
22
22
  import {Batch, BatchError, BatchErrorCode, BatchMetadata, BatchStatus} from "./batch.js";
@@ -160,7 +160,7 @@ export class SyncChain {
160
160
  private readonly clock: IClock;
161
161
  private readonly metrics: Metrics | null;
162
162
  private readonly custodyConfig: CustodyConfig;
163
- private readonly latestBid: gloas.ExecutionPayloadBid | undefined;
163
+ private readonly parentPayload: ParentPayload | undefined;
164
164
 
165
165
  constructor(
166
166
  initialBatchEpoch: Epoch,
@@ -168,7 +168,7 @@ export class SyncChain {
168
168
  syncType: RangeSyncType,
169
169
  fns: SyncChainFns,
170
170
  modules: SyncChainModules,
171
- latestBid: gloas.ExecutionPayloadBid | undefined
171
+ parentPayload: ParentPayload | undefined
172
172
  ) {
173
173
  const {config, clock, custodyConfig, logger, metrics} = modules;
174
174
  this.firstBatchEpoch = initialBatchEpoch;
@@ -184,7 +184,7 @@ export class SyncChain {
184
184
  this.clock = clock;
185
185
  this.metrics = metrics;
186
186
  this.custodyConfig = custodyConfig;
187
- this.latestBid = latestBid;
187
+ this.parentPayload = parentPayload;
188
188
  this.logger = logger;
189
189
  this.logId = `${syncType}-${nextChainId++}`;
190
190
 
@@ -536,8 +536,8 @@ export class SyncChain {
536
536
  this.clock,
537
537
  this.custodyConfig,
538
538
  this.isFirstBatch,
539
- // `latestBid` is only meaningful for the first batch's parent-payload check
540
- this.isFirstBatch ? this.latestBid : undefined,
539
+ // `parentPayload` is only meaningful for the first batch
540
+ this.isFirstBatch ? this.parentPayload : undefined,
541
541
  this.target.slot
542
542
  );
543
543
  this.isFirstBatch = false;
@@ -586,6 +586,8 @@ export class SyncChain {
586
586
  case DownloadByRangeErrorCode.OUT_OF_RANGE_BLOCKS:
587
587
  case DownloadByRangeErrorCode.PARENT_ROOT_MISMATCH:
588
588
  case DownloadByRangeErrorCode.INVALID_ENVELOPE_BEACON_BLOCK_ROOT:
589
+ case DownloadByRangeErrorCode.INVALID_ENVELOPE_BLOCK_HASH:
590
+ case DownloadByRangeErrorCode.INVALID_ENVELOPE_SLOT:
589
591
  case DownloadByRangeErrorCode.INVALID_CHAIN_SEGMENT:
590
592
  case BlobSidecarErrorCode.INCLUSION_PROOF_INVALID:
591
593
  case BlobSidecarErrorCode.INVALID_KZG_PROOF_BATCH:
@@ -2,8 +2,8 @@ import {EventEmitter} from "node:events";
2
2
  import {StrictEventEmitter} from "strict-event-emitter-types";
3
3
  import {BeaconConfig} from "@lodestar/config";
4
4
  import {IBeaconStateViewGloas, computeStartSlotAtEpoch, isStatePostGloas} from "@lodestar/state-transition";
5
- import {Epoch, Status, fulu} from "@lodestar/types";
6
- import {Logger, prettyPrintIndices, toRootHex} from "@lodestar/utils";
5
+ import {Epoch, Status, fulu, ssz} from "@lodestar/types";
6
+ import {Logger, byteArrayEquals, prettyPrintIndices, toRootHex} from "@lodestar/utils";
7
7
  import {IBlockInput} from "../../chain/blocks/blockInput/types.js";
8
8
  import {PayloadError, PayloadErrorCode} from "../../chain/blocks/importExecutionPayload.js";
9
9
  import {AttestationImportOpt, ImportBlockOpts} from "../../chain/blocks/index.js";
@@ -16,6 +16,7 @@ import {PeerIdStr} from "../../util/peerId.js";
16
16
  import {
17
17
  DownloadByRangeError,
18
18
  DownloadByRangeErrorCode,
19
+ ParentPayload,
19
20
  cacheByRangeResponses,
20
21
  downloadByRange,
21
22
  } from "../utils/downloadByRange.js";
@@ -278,15 +279,14 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
278
279
  private downloadByRange: SyncChainFns["downloadByRange"] = async (peer, batch) => {
279
280
  const batchBlocks = batch.getBlocks();
280
281
  const requests = batch.getRequestsForPeer(peer);
281
- const parentRoot = requests.parentPayloadRequest?.envelopeBlockRoot ?? requests.parentPayloadRequest?.blockRoot;
282
- const parentPayloadCommitments = parentRoot ? batch.getParentPayloadCommitments(parentRoot) : undefined;
282
+ const parentPayload = requests.parentPayloadRequest ? batch.getParentPayload() : undefined;
283
283
  const {result, warnings} = await downloadByRange({
284
284
  config: this.config,
285
285
  network: this.network,
286
286
  logger: this.logger,
287
287
  peerIdStr: peer.peerId,
288
288
  batchBlocks,
289
- parentPayloadCommitments,
289
+ parentPayload,
290
290
  peerDasMetrics: this.chain.metrics?.peerDas,
291
291
  ...requests,
292
292
  });
@@ -299,6 +299,7 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
299
299
  batchBlocks,
300
300
  downloadedPayloadEnvelopes,
301
301
  existingPayloadEnvelopes: batch.getPayloadEnvelopes(),
302
+ parentPayload,
302
303
  custodyConfig: this.chain.custodyConfig,
303
304
  seenTimestampSec: Date.now() / 1000,
304
305
  });
@@ -376,13 +377,26 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
376
377
  private addPeerOrCreateChain(startEpoch: Epoch, target: ChainTarget, peer: PeerIdStr, syncType: RangeSyncType): void {
377
378
  let syncChain = this.chains.get(syncType);
378
379
  if (!syncChain) {
379
- // The first batch of a new sync chain may need to detect whether the parent block was an
380
- // gloas "empty" block (no envelope produced). It does so by comparing the first
381
- // downloaded block's `bid.parentBlockHash` against the head state's `latestExecutionPayloadBid.blockHash`.
380
+ // The first block of the first batch may build on the head's FULL variant before its payload is imported,
381
+ // the batch then downloads the head's payload as dangling parent and validates it against the bid
382
382
  const headState = this.chain.getHeadState();
383
- const latestBid = isStatePostGloas(headState)
384
- ? (headState as IBeaconStateViewGloas).latestExecutionPayloadBid
385
- : undefined;
383
+ let parentPayload: ParentPayload | undefined;
384
+ if (isStatePostGloas(headState) && headState.latestBlockHeader.slot > 0) {
385
+ const header = ssz.phase0.BeaconBlockHeader.clone(headState.latestBlockHeader);
386
+ if (byteArrayEquals(header.stateRoot, ssz.Root.defaultValue())) {
387
+ header.stateRoot = headState.hashTreeRoot();
388
+ }
389
+ const headRoot = ssz.phase0.BeaconBlockHeader.hashTreeRoot(header);
390
+ const headSlot = headState.latestBlockHeader.slot;
391
+ parentPayload = {
392
+ blockRoot: headRoot,
393
+ blockRootHex: toRootHex(headRoot),
394
+ slot: headSlot,
395
+ proposerIndex: headState.latestBlockHeader.proposerIndex,
396
+ forkName: this.config.getForkName(headSlot),
397
+ bid: (headState as IBeaconStateViewGloas).latestExecutionPayloadBid,
398
+ };
399
+ }
386
400
 
387
401
  syncChain = new SyncChain(
388
402
  startEpoch,
@@ -403,7 +417,7 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
403
417
  custodyConfig: this.chain.custodyConfig,
404
418
  metrics: this.metrics,
405
419
  },
406
- latestBid
420
+ parentPayload
407
421
  );
408
422
  this.chains.set(syncType, syncChain);
409
423
 
@@ -73,7 +73,11 @@ type AdvancePendingBlockResult =
73
73
  | "removed";
74
74
 
75
75
  class UnknownBlockRateLimitedError extends Error {
76
- constructor(message: string) {
76
+ constructor(
77
+ message: string,
78
+ /** Earliest backoff expiry seen when the download was deferred, it is retried once that has passed */
79
+ readonly retryAt: number
80
+ ) {
77
81
  super(message);
78
82
  this.name = "UnknownBlockRateLimitedError";
79
83
  }
@@ -849,17 +853,20 @@ export class BlockInputSync {
849
853
  }
850
854
  };
851
855
 
852
- private scheduleRateLimitBackoffRetry(): void {
856
+ /**
857
+ * Returns false if there is no backoff left to wait for, in which case no retry is scheduled.
858
+ */
859
+ private scheduleRateLimitBackoffRetry(): boolean {
853
860
  this.clearRateLimitBackoffTimer();
854
861
 
855
862
  if (!this.subscribedToNetworkEvents || (this.pendingBlocks.size === 0 && this.pendingPayloads.size === 0)) {
856
- return;
863
+ return false;
857
864
  }
858
865
 
859
866
  const now = Date.now();
860
867
  const retryAt = this.peerBalancer.getNextRateLimitRetryAt();
861
868
  if (retryAt === null) {
862
- return;
869
+ return false;
863
870
  }
864
871
 
865
872
  this.rateLimitBackoffTimeout = setTimeout(
@@ -870,6 +877,7 @@ export class BlockInputSync {
870
877
  },
871
878
  Math.max(0, retryAt - now)
872
879
  );
880
+ return true;
873
881
  }
874
882
 
875
883
  private clearRateLimitBackoffTimer(): void {
@@ -910,16 +918,17 @@ export class BlockInputSync {
910
918
  * Poll unknown payloads of the current slot.
911
919
  */
912
920
  private async pollPayloadsAtSlot(slot: Slot, signal: AbortSignal): Promise<void> {
921
+ const fork = this.config.getForkName(slot);
913
922
  // fixed tick count so the loop cannot outlive its slot: for mainnet, it's 6 ticks
914
923
  const tickCount = Math.floor(
915
- (this.config.SLOT_DURATION_MS - this.config.getPayloadDueMs()) / PAYLOAD_POLL_INTERVAL_MS
924
+ (this.config.getSlotDurationMs(fork) - this.config.getPayloadDueMs(fork)) / PAYLOAD_POLL_INTERVAL_MS
916
925
  );
917
926
  // a root still missing on several ticks is searched on each of them, recorded once
918
927
  const searchedRoots = new Set<RootHex>();
919
928
  let polls = 0;
920
929
 
921
930
  try {
922
- await sleep(Math.max(0, this.config.getPayloadDueMs() - this.chain.clock.msFromSlot(slot)), signal);
931
+ await sleep(Math.max(0, this.config.getPayloadDueMs(fork) - this.chain.clock.msFromSlot(slot)), signal);
923
932
 
924
933
  for (polls = 0; polls < tickCount; polls++) {
925
934
  let importedCount = 0;
@@ -1081,7 +1090,11 @@ export class BlockInputSync {
1081
1090
  pendingBlock.status = PendingBlockInputStatus.pending;
1082
1091
  }
1083
1092
  this.logger.debug("Deferring unknown block download due to peer rate limit", logCtx, res.err);
1084
- this.scheduleRateLimitBackoffRetry();
1093
+ if (!this.scheduleRateLimitBackoffRetry() || res.err.retryAt <= Date.now()) {
1094
+ // The backoff this download waited for expired in the meantime, a timer is only armed if another
1095
+ // peer is still in backoff and would retry it later than needed
1096
+ this.triggerUnknownBlockSearch();
1097
+ }
1085
1098
  return;
1086
1099
  }
1087
1100
 
@@ -1364,6 +1377,14 @@ export class BlockInputSync {
1364
1377
  if (!isPendingPayloadEnvelope(payload)) {
1365
1378
  payload.status = PendingPayloadInputStatus.pending;
1366
1379
  }
1380
+ if (
1381
+ res.err instanceof UnknownBlockRateLimitedError &&
1382
+ (!this.scheduleRateLimitBackoffRetry() || res.err.retryAt <= Date.now())
1383
+ ) {
1384
+ // The backoff this download waited for expired in the meantime, a timer is only armed if another
1385
+ // peer is still in backoff and would retry it later than needed
1386
+ this.triggerUnknownBlockSearch();
1387
+ }
1367
1388
  }
1368
1389
 
1369
1390
  private async processPayload(pendingPayload: PendingPayloadInput): Promise<void> {
@@ -1488,16 +1509,21 @@ export class BlockInputSync {
1488
1509
  const pendingColumns = payloadInput?.hasAllData()
1489
1510
  ? new Set<number>()
1490
1511
  : new Set(payloadInput?.getMissingSampledColumnMeta().missing ?? []);
1512
+ // Same `now` for both calls, a backoff expiring in between would be reported as no peer available
1513
+ const now = Date.now();
1491
1514
  // prefer peers that gossiped this payload root to us (#9923)
1492
1515
  const peerMeta = this.peerBalancer.bestPeerForPendingColumns(
1493
1516
  pendingColumns,
1494
1517
  excludedPeers,
1495
- cacheItem.peerIdStrings
1518
+ cacheItem.peerIdStrings,
1519
+ now
1496
1520
  );
1497
1521
  if (peerMeta === null) {
1498
- if (this.peerBalancer.getNextRateLimitRetryAt(pendingColumns, excludedPeers) !== null) {
1522
+ const retryAt = this.peerBalancer.getNextRateLimitRetryAt(pendingColumns, excludedPeers, now);
1523
+ if (retryAt !== null) {
1499
1524
  throw new UnknownBlockRateLimitedError(
1500
- `Error fetching payload by root slot=${slot} root=${rootHex} after ${i}: peers with needed columns are rate-limited`
1525
+ `Error fetching payload by root slot=${slot} root=${rootHex} after ${i}: peers with needed columns are rate-limited`,
1526
+ retryAt
1501
1527
  );
1502
1528
  }
1503
1529
 
@@ -1636,9 +1662,11 @@ export class BlockInputSync {
1636
1662
  );
1637
1663
  this.metrics?.blockInputSync.payloadFetchPeers.set({result: FetchResult.FailureMaxAttempts}, i - 1);
1638
1664
 
1639
- if (deferredByRateLimit && this.peerBalancer.getNextRateLimitRetryAt() !== null) {
1665
+ const retryAt = deferredByRateLimit ? this.peerBalancer.getNextRateLimitRetryAt() : null;
1666
+ if (retryAt !== null) {
1640
1667
  throw new UnknownBlockRateLimitedError(
1641
- `Error fetching payload with slot=${slot} root=${rootHex} after ${i - 1} attempts: peers are rate-limited`
1668
+ `Error fetching payload with slot=${slot} root=${rootHex} after ${i - 1} attempts: peers are rate-limited`,
1669
+ retryAt
1642
1670
  );
1643
1671
  }
1644
1672
  throw Error(`Error fetching payload with slot=${slot} root=${rootHex} after ${i - 1} attempts.`);
@@ -1730,16 +1758,21 @@ export class BlockInputSync {
1730
1758
  isPendingBlockInput(cacheItem) && isBlockInputColumns(cacheItem.blockInput)
1731
1759
  ? new Set(cacheItem.blockInput.getMissingSampledColumnMeta().missing)
1732
1760
  : defaultPendingColumns;
1761
+ // Same `now` for both calls, a backoff expiring in between would be reported as no peer available
1762
+ const now = Date.now();
1733
1763
  // prefer peers that gossiped this block root to us (#9923)
1734
1764
  const peerMeta = this.peerBalancer.bestPeerForPendingColumns(
1735
1765
  pendingColumns,
1736
1766
  excludedPeers,
1737
- cacheItem.peerIdStrings
1767
+ cacheItem.peerIdStrings,
1768
+ now
1738
1769
  );
1739
1770
  if (peerMeta === null) {
1740
- if (this.peerBalancer.getNextRateLimitRetryAt(pendingColumns, excludedPeers) !== null) {
1771
+ const retryAt = this.peerBalancer.getNextRateLimitRetryAt(pendingColumns, excludedPeers, now);
1772
+ if (retryAt !== null) {
1741
1773
  throw new UnknownBlockRateLimitedError(
1742
- `Error fetching UnknownBlockRoot slot=${slot} root=${rootHex} after ${i}: peers with needed columns are rate-limited`
1774
+ `Error fetching UnknownBlockRoot slot=${slot} root=${rootHex} after ${i}: peers with needed columns are rate-limited`,
1775
+ retryAt
1743
1776
  );
1744
1777
  }
1745
1778
 
@@ -1845,8 +1878,9 @@ export class BlockInputSync {
1845
1878
 
1846
1879
  const message = `Error fetching BlockInput with slot=${slot} root=${rootHex} after ${i - 1} attempts.`;
1847
1880
 
1848
- if (deferredByRateLimit && this.peerBalancer.getNextRateLimitRetryAt() !== null) {
1849
- throw new UnknownBlockRateLimitedError(`${message} Peers are rate-limited.`);
1881
+ const retryAt = deferredByRateLimit ? this.peerBalancer.getNextRateLimitRetryAt() : null;
1882
+ if (retryAt !== null) {
1883
+ throw new UnknownBlockRateLimitedError(`${message} Peers are rate-limited.`, retryAt);
1850
1884
  }
1851
1885
 
1852
1886
  if (!isPendingBlockInput(cacheItem)) {
@@ -2037,8 +2071,11 @@ export class UnknownBlockPeerBalancer {
2037
2071
  this.rateLimitedUntilByPeer.set(peerId, rateLimitedUntilMs);
2038
2072
  }
2039
2073
 
2040
- getNextRateLimitRetryAt(pendingColumns?: Set<number>, excludedPeers?: Set<PeerIdStr>): number | null {
2041
- const now = Date.now();
2074
+ getNextRateLimitRetryAt(
2075
+ pendingColumns?: Set<number>,
2076
+ excludedPeers?: Set<PeerIdStr>,
2077
+ now = Date.now()
2078
+ ): number | null {
2042
2079
  let retryAt: number | null = null;
2043
2080
 
2044
2081
  for (const [peerId, rateLimitedUntil] of this.rateLimitedUntilByPeer.entries()) {
@@ -2077,9 +2114,10 @@ export class UnknownBlockPeerBalancer {
2077
2114
  bestPeerForPendingColumns(
2078
2115
  pendingColumns: Set<number>,
2079
2116
  excludedPeers: Set<PeerIdStr>,
2080
- preferredPeers?: Set<PeerIdStr>
2117
+ preferredPeers?: Set<PeerIdStr>,
2118
+ now = Date.now()
2081
2119
  ): PeerSyncMeta | null {
2082
- const eligiblePeers = this.filterPeers(pendingColumns, excludedPeers);
2120
+ const eligiblePeers = this.filterPeers(pendingColumns, excludedPeers, now);
2083
2121
  if (eligiblePeers.length === 0) {
2084
2122
  return null;
2085
2123
  }
@@ -2120,8 +2158,7 @@ export class UnknownBlockPeerBalancer {
2120
2158
  return totalActiveRequests;
2121
2159
  }
2122
2160
 
2123
- private filterPeers(pendingDataColumns: Set<number>, excludedPeers: Set<PeerIdStr>): PeerIdStr[] {
2124
- const now = Date.now();
2161
+ private filterPeers(pendingDataColumns: Set<number>, excludedPeers: Set<PeerIdStr>, now: number): PeerIdStr[] {
2125
2162
  let maxColumnCount = 0;
2126
2163
  const considerPeers: {peerId: PeerIdStr; columnCount: number}[] = [];
2127
2164
  for (const [peerId, syncMeta] of this.peersMeta.entries()) {