@lodestar/beacon-node 1.51.0-dev.ab919f3073 → 1.51.0-dev.ae4dc9985e

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 +17 -27
  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 +5 -2
  6. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  7. package/lib/api/impl/beacon/state/utils.d.ts +1 -1
  8. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  9. package/lib/api/impl/validator/index.d.ts +6 -0
  10. package/lib/api/impl/validator/index.d.ts.map +1 -1
  11. package/lib/api/impl/validator/index.js +42 -26
  12. package/lib/api/impl/validator/index.js.map +1 -1
  13. package/lib/chain/GetBlobsTracker.d.ts +11 -0
  14. package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
  15. package/lib/chain/GetBlobsTracker.js +85 -27
  16. package/lib/chain/GetBlobsTracker.js.map +1 -1
  17. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  18. package/lib/chain/archiveStore/archiveStore.js +1 -0
  19. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  20. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +4 -0
  21. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
  22. package/lib/chain/archiveStore/utils/archiveBlocks.js +7 -1
  23. package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
  24. package/lib/chain/blocks/importExecutionPayload.d.ts +6 -11
  25. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  26. package/lib/chain/blocks/importExecutionPayload.js +8 -15
  27. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  28. package/lib/chain/blocks/index.js +2 -2
  29. package/lib/chain/blocks/index.js.map +1 -1
  30. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +12 -9
  31. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -1
  32. package/lib/chain/blocks/payloadEnvelopeProcessor.js +24 -19
  33. package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
  34. package/lib/chain/blocks/types.d.ts +4 -1
  35. package/lib/chain/blocks/types.d.ts.map +1 -1
  36. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  37. package/lib/chain/blocks/verifyBlock.js +18 -7
  38. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  39. package/lib/chain/blocks/verifyBlocksDataAvailability.d.ts.map +1 -1
  40. package/lib/chain/blocks/verifyBlocksDataAvailability.js +8 -1
  41. package/lib/chain/blocks/verifyBlocksDataAvailability.js.map +1 -1
  42. package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
  43. package/lib/chain/blocks/verifyBlocksSignatures.js +7 -5
  44. package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
  45. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts +3 -3
  46. package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -1
  47. package/lib/chain/blocks/verifyPayloadsDataAvailability.js +11 -6
  48. package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -1
  49. package/lib/chain/bls/interface.d.ts +2 -0
  50. package/lib/chain/bls/interface.d.ts.map +1 -1
  51. package/lib/chain/bls/multithread/index.d.ts.map +1 -1
  52. package/lib/chain/bls/multithread/index.js +13 -11
  53. package/lib/chain/bls/multithread/index.js.map +1 -1
  54. package/lib/chain/bls/multithread/types.d.ts +1 -1
  55. package/lib/chain/bls/multithread/types.d.ts.map +1 -1
  56. package/lib/chain/bls/multithread/worker.js +1 -1
  57. package/lib/chain/bls/multithread/worker.js.map +1 -1
  58. package/lib/chain/bls/singleThread.js +1 -1
  59. package/lib/chain/bls/singleThread.js.map +1 -1
  60. package/lib/chain/bls/utils.js +1 -1
  61. package/lib/chain/bls/utils.js.map +1 -1
  62. package/lib/chain/chain.d.ts +1 -1
  63. package/lib/chain/chain.d.ts.map +1 -1
  64. package/lib/chain/chain.js.map +1 -1
  65. package/lib/chain/errors/blockError.d.ts +1 -1
  66. package/lib/chain/errors/blockError.d.ts.map +1 -1
  67. package/lib/chain/errors/blockError.js +1 -1
  68. package/lib/chain/errors/blockError.js.map +1 -1
  69. package/lib/chain/errors/executionPayloadEnvelope.d.ts +7 -0
  70. package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
  71. package/lib/chain/errors/executionPayloadEnvelope.js +1 -0
  72. package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
  73. package/lib/chain/interface.d.ts +2 -3
  74. package/lib/chain/interface.d.ts.map +1 -1
  75. package/lib/chain/interface.js.map +1 -1
  76. package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
  77. package/lib/chain/opPools/aggregatedAttestationPool.js +23 -10
  78. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  79. package/lib/chain/opPools/attestationPool.d.ts +1 -1
  80. package/lib/chain/opPools/attestationPool.d.ts.map +1 -1
  81. package/lib/chain/opPools/attestationPool.js +15 -4
  82. package/lib/chain/opPools/attestationPool.js.map +1 -1
  83. package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -1
  84. package/lib/chain/opPools/payloadAttestationPool.js +17 -7
  85. package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
  86. package/lib/chain/opPools/syncCommitteeMessagePool.d.ts.map +1 -1
  87. package/lib/chain/opPools/syncCommitteeMessagePool.js +9 -3
  88. package/lib/chain/opPools/syncCommitteeMessagePool.js.map +1 -1
  89. package/lib/chain/opPools/syncContributionAndProofPool.d.ts.map +1 -1
  90. package/lib/chain/opPools/syncContributionAndProofPool.js +11 -3
  91. package/lib/chain/opPools/syncContributionAndProofPool.js.map +1 -1
  92. package/lib/chain/opPools/utils.d.ts +1 -1
  93. package/lib/chain/opPools/utils.d.ts.map +1 -1
  94. package/lib/chain/opPools/utils.js +1 -1
  95. package/lib/chain/opPools/utils.js.map +1 -1
  96. package/lib/chain/options.d.ts +0 -1
  97. package/lib/chain/options.d.ts.map +1 -1
  98. package/lib/chain/options.js +0 -1
  99. package/lib/chain/options.js.map +1 -1
  100. package/lib/chain/validation/executionPayloadBid.js +13 -13
  101. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  102. package/lib/chain/validation/executionPayloadEnvelope.d.ts +6 -0
  103. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  104. package/lib/chain/validation/executionPayloadEnvelope.js +53 -0
  105. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  106. package/lib/db/beacon.d.ts +7 -0
  107. package/lib/db/beacon.d.ts.map +1 -1
  108. package/lib/db/beacon.js +32 -0
  109. package/lib/db/beacon.js.map +1 -1
  110. package/lib/db/dataColumnStore.d.ts +1 -1
  111. package/lib/db/dataColumnStore.d.ts.map +1 -1
  112. package/lib/db/dataColumnStore.js +1 -4
  113. package/lib/db/dataColumnStore.js.map +1 -1
  114. package/lib/db/flatFileStore/flatFileStore.js +5 -5
  115. package/lib/db/flatFileStore/flatFileStore.js.map +1 -1
  116. package/lib/db/flatFileStore/slotIndex.d.ts.map +1 -1
  117. package/lib/db/flatFileStore/slotIndex.js +2 -2
  118. package/lib/db/flatFileStore/slotIndex.js.map +1 -1
  119. package/lib/db/interface.d.ts +1 -0
  120. package/lib/db/interface.d.ts.map +1 -1
  121. package/lib/db/repositories/dataColumnSidecarArchive.d.ts +6 -0
  122. package/lib/db/repositories/dataColumnSidecarArchive.d.ts.map +1 -1
  123. package/lib/db/repositories/dataColumnSidecarArchive.js +19 -0
  124. package/lib/db/repositories/dataColumnSidecarArchive.js.map +1 -1
  125. package/lib/execution/builder/apiClient.d.ts +14 -8
  126. package/lib/execution/builder/apiClient.d.ts.map +1 -1
  127. package/lib/execution/builder/apiClient.js +12 -10
  128. package/lib/execution/builder/apiClient.js.map +1 -1
  129. package/lib/execution/builder/http.d.ts +2 -0
  130. package/lib/execution/builder/http.d.ts.map +1 -1
  131. package/lib/execution/builder/http.js +2 -0
  132. package/lib/execution/builder/http.js.map +1 -1
  133. package/lib/execution/engine/index.d.ts +1 -1
  134. package/lib/execution/engine/index.d.ts.map +1 -1
  135. package/lib/execution/engine/index.js +1 -1
  136. package/lib/execution/engine/index.js.map +1 -1
  137. package/lib/execution/engine/interface.d.ts +1 -1
  138. package/lib/execution/engine/interface.d.ts.map +1 -1
  139. package/lib/execution/engine/interface.js.map +1 -1
  140. package/lib/execution/engine/types.d.ts.map +1 -1
  141. package/lib/execution/engine/types.js +2 -2
  142. package/lib/execution/engine/types.js.map +1 -1
  143. package/lib/execution/engine/utils.d.ts.map +1 -1
  144. package/lib/execution/engine/utils.js +3 -2
  145. package/lib/execution/engine/utils.js.map +1 -1
  146. package/lib/metrics/metrics/lodestar.d.ts +4 -0
  147. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  148. package/lib/metrics/metrics/lodestar.js +10 -0
  149. package/lib/metrics/metrics/lodestar.js.map +1 -1
  150. package/lib/metrics/server/http.js +5 -5
  151. package/lib/metrics/server/http.js.map +1 -1
  152. package/lib/monitoring/service.js +1 -1
  153. package/lib/monitoring/service.js.map +1 -1
  154. package/lib/network/core/networkCore.d.ts +2 -0
  155. package/lib/network/core/networkCore.d.ts.map +1 -1
  156. package/lib/network/core/networkCore.js +3 -0
  157. package/lib/network/core/networkCore.js.map +1 -1
  158. package/lib/network/core/networkCoreWorker.js +1 -0
  159. package/lib/network/core/networkCoreWorker.js.map +1 -1
  160. package/lib/network/core/networkCoreWorkerHandler.d.ts +2 -0
  161. package/lib/network/core/networkCoreWorkerHandler.d.ts.map +1 -1
  162. package/lib/network/core/networkCoreWorkerHandler.js +3 -0
  163. package/lib/network/core/networkCoreWorkerHandler.js.map +1 -1
  164. package/lib/network/core/types.d.ts +2 -0
  165. package/lib/network/core/types.d.ts.map +1 -1
  166. package/lib/network/gossip/gossipsub.d.ts +1 -0
  167. package/lib/network/gossip/gossipsub.d.ts.map +1 -1
  168. package/lib/network/gossip/gossipsub.js +10 -0
  169. package/lib/network/gossip/gossipsub.js.map +1 -1
  170. package/lib/network/interface.d.ts +2 -0
  171. package/lib/network/interface.d.ts.map +1 -1
  172. package/lib/network/libp2p/index.d.ts.map +1 -1
  173. package/lib/network/libp2p/index.js +5 -1
  174. package/lib/network/libp2p/index.js.map +1 -1
  175. package/lib/network/network.d.ts +2 -0
  176. package/lib/network/network.d.ts.map +1 -1
  177. package/lib/network/network.js +6 -1
  178. package/lib/network/network.js.map +1 -1
  179. package/lib/network/options.d.ts +2 -0
  180. package/lib/network/options.d.ts.map +1 -1
  181. package/lib/network/options.js.map +1 -1
  182. package/lib/network/peers/peerManager.d.ts +2 -1
  183. package/lib/network/peers/peerManager.d.ts.map +1 -1
  184. package/lib/network/peers/peerManager.js +28 -1
  185. package/lib/network/peers/peerManager.js.map +1 -1
  186. package/lib/network/peers/utils/assertPeerRelevance.d.ts +9 -1
  187. package/lib/network/peers/utils/assertPeerRelevance.d.ts.map +1 -1
  188. package/lib/network/peers/utils/assertPeerRelevance.js +32 -21
  189. package/lib/network/peers/utils/assertPeerRelevance.js.map +1 -1
  190. package/lib/network/peers/utils/prioritizePeers.d.ts +4 -1
  191. package/lib/network/peers/utils/prioritizePeers.d.ts.map +1 -1
  192. package/lib/network/peers/utils/prioritizePeers.js +8 -16
  193. package/lib/network/peers/utils/prioritizePeers.js.map +1 -1
  194. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  195. package/lib/network/processor/gossipHandlers.js +30 -19
  196. package/lib/network/processor/gossipHandlers.js.map +1 -1
  197. package/lib/node/nodejs.d.ts +3 -1
  198. package/lib/node/nodejs.d.ts.map +1 -1
  199. package/lib/node/nodejs.js +47 -21
  200. package/lib/node/nodejs.js.map +1 -1
  201. package/lib/node/options.d.ts +3 -1
  202. package/lib/node/options.d.ts.map +1 -1
  203. package/lib/node/options.js +4 -2
  204. package/lib/node/options.js.map +1 -1
  205. package/lib/sync/interface.d.ts.map +1 -1
  206. package/lib/sync/interface.js.map +1 -1
  207. package/lib/sync/sync.d.ts +7 -0
  208. package/lib/sync/sync.d.ts.map +1 -1
  209. package/lib/sync/sync.js +61 -3
  210. package/lib/sync/sync.js.map +1 -1
  211. package/lib/util/file.d.ts.map +1 -1
  212. package/lib/util/file.js +8 -9
  213. package/lib/util/file.js.map +1 -1
  214. package/lib/util/queue/itemQueue.js +1 -1
  215. package/lib/util/queue/itemQueue.js.map +1 -1
  216. package/lib/util/sszBytes.d.ts +5 -0
  217. package/lib/util/sszBytes.d.ts.map +1 -1
  218. package/lib/util/sszBytes.js +35 -2
  219. package/lib/util/sszBytes.js.map +1 -1
  220. package/package.json +16 -17
  221. package/src/api/impl/beacon/blocks/index.ts +35 -45
  222. package/src/api/impl/beacon/pool/index.ts +5 -1
  223. package/src/api/impl/beacon/state/utils.ts +1 -1
  224. package/src/api/impl/validator/index.ts +47 -30
  225. package/src/chain/GetBlobsTracker.ts +97 -38
  226. package/src/chain/archiveStore/archiveStore.ts +1 -0
  227. package/src/chain/archiveStore/utils/archiveBlocks.ts +12 -4
  228. package/src/chain/blocks/importExecutionPayload.ts +13 -21
  229. package/src/chain/blocks/index.ts +6 -2
  230. package/src/chain/blocks/payloadEnvelopeProcessor.ts +35 -24
  231. package/src/chain/blocks/types.ts +4 -1
  232. package/src/chain/blocks/verifyBlock.ts +31 -16
  233. package/src/chain/blocks/verifyBlocksDataAvailability.ts +10 -1
  234. package/src/chain/blocks/verifyBlocksSignatures.ts +7 -5
  235. package/src/chain/blocks/verifyPayloadsDataAvailability.ts +14 -6
  236. package/src/chain/bls/interface.ts +2 -0
  237. package/src/chain/bls/multithread/index.ts +14 -10
  238. package/src/chain/bls/multithread/types.ts +1 -1
  239. package/src/chain/bls/multithread/worker.ts +1 -5
  240. package/src/chain/bls/singleThread.ts +1 -1
  241. package/src/chain/bls/utils.ts +1 -1
  242. package/src/chain/chain.ts +1 -1
  243. package/src/chain/errors/blockError.ts +1 -1
  244. package/src/chain/errors/executionPayloadEnvelope.ts +8 -0
  245. package/src/chain/interface.ts +2 -3
  246. package/src/chain/opPools/aggregatedAttestationPool.ts +25 -9
  247. package/src/chain/opPools/attestationPool.ts +16 -4
  248. package/src/chain/opPools/payloadAttestationPool.ts +18 -7
  249. package/src/chain/opPools/syncCommitteeMessagePool.ts +10 -3
  250. package/src/chain/opPools/syncContributionAndProofPool.ts +13 -3
  251. package/src/chain/opPools/utils.ts +1 -1
  252. package/src/chain/options.ts +0 -2
  253. package/src/chain/validation/executionPayloadBid.ts +14 -13
  254. package/src/chain/validation/executionPayloadEnvelope.ts +68 -1
  255. package/src/db/beacon.ts +39 -0
  256. package/src/db/dataColumnStore.ts +2 -4
  257. package/src/db/flatFileStore/flatFileStore.ts +7 -7
  258. package/src/db/flatFileStore/slotIndex.ts +4 -3
  259. package/src/db/interface.ts +2 -0
  260. package/src/db/repositories/dataColumnSidecarArchive.ts +20 -0
  261. package/src/execution/builder/apiClient.ts +16 -13
  262. package/src/execution/builder/http.ts +4 -0
  263. package/src/execution/engine/index.ts +1 -1
  264. package/src/execution/engine/interface.ts +1 -1
  265. package/src/execution/engine/types.ts +3 -1
  266. package/src/execution/engine/utils.ts +4 -2
  267. package/src/metrics/metrics/lodestar.ts +10 -0
  268. package/src/metrics/server/http.ts +5 -5
  269. package/src/monitoring/service.ts +1 -1
  270. package/src/network/core/networkCore.ts +5 -0
  271. package/src/network/core/networkCoreWorker.ts +1 -0
  272. package/src/network/core/networkCoreWorkerHandler.ts +4 -0
  273. package/src/network/core/types.ts +2 -0
  274. package/src/network/gossip/gossipsub.ts +11 -0
  275. package/src/network/interface.ts +2 -0
  276. package/src/network/libp2p/index.ts +5 -1
  277. package/src/network/network.ts +8 -1
  278. package/src/network/options.ts +2 -0
  279. package/src/network/peers/peerManager.ts +28 -3
  280. package/src/network/peers/utils/assertPeerRelevance.ts +39 -23
  281. package/src/network/peers/utils/prioritizePeers.ts +14 -22
  282. package/src/network/processor/gossipHandlers.ts +35 -21
  283. package/src/node/nodejs.ts +58 -22
  284. package/src/node/options.ts +9 -6
  285. package/src/sync/interface.ts +1 -0
  286. package/src/sync/sync.ts +65 -4
  287. package/src/util/file.ts +8 -9
  288. package/src/util/queue/itemQueue.ts +1 -1
  289. package/src/util/sszBytes.ts +42 -2
@@ -1,23 +1,29 @@
1
1
  import {setMaxListeners} from "node:events";
2
2
  import {PrivateKey} from "@libp2p/interface";
3
3
  import {Registry} from "prom-client";
4
+ import {hasher} from "@chainsafe/persistent-merkle-tree";
5
+ import {BeaconApiMethods} from "@lodestar/api/beacon/server";
6
+ import {BeaconConfig} from "@lodestar/config";
7
+ import type {LoggerNode} from "@lodestar/logger/node";
4
8
  import {
5
9
  init as initNativeMetrics,
6
10
  registerLocalValidator as registerNativeLocalValidator,
7
11
  scrapeMetrics as scrapeNativeMetrics,
8
12
  unregisterLocalValidator as unregisterNativeLocalValidator,
9
- } from "@chainsafe/lodestar-z/metrics";
10
- import {type PubkeyCache} from "@chainsafe/lodestar-z/pubkeys";
11
- import {hasher} from "@chainsafe/persistent-merkle-tree";
12
- import {BeaconApiMethods} from "@lodestar/api/beacon/server";
13
- import {BeaconConfig} from "@lodestar/config";
14
- import type {LoggerNode} from "@lodestar/logger/node";
13
+ } from "@lodestar/native/metrics";
14
+ import {type PubkeyCache} from "@lodestar/native/pubkeys";
15
15
  import {ZERO_HASH_HEX} from "@lodestar/params";
16
- import {IBeaconStateView, isStatePostBellatrix, isStatePostGloas} from "@lodestar/state-transition";
16
+ import {
17
+ IBeaconStateView,
18
+ computeStartSlotAtEpoch,
19
+ isStatePostBellatrix,
20
+ isStatePostGloas,
21
+ } from "@lodestar/state-transition";
17
22
  import {Slot} from "@lodestar/types";
18
- import {sleep, toRootHex} from "@lodestar/utils";
23
+ import {defer, sleep, toRootHex} from "@lodestar/utils";
19
24
  import {ProcessShutdownCallback} from "@lodestar/validator";
20
25
  import {BeaconRestApiServer, getApi} from "../api/index.js";
26
+ import {getDataColumnSidecarsMinEpoch} from "../chain/archiveStore/utils/archiveBlocks.js";
21
27
  import {BeaconChain, IBeaconChain, initBeaconMetrics} from "../chain/index.js";
22
28
  import {ValidatorMonitor, createValidatorMonitor} from "../chain/validatorMonitor.js";
23
29
  import {IBeaconDb} from "../db/index.js";
@@ -111,6 +117,7 @@ export class BeaconNode {
111
117
 
112
118
  status: BeaconNodeStatus;
113
119
  private controller?: AbortController;
120
+ private closePromise: Promise<void> | undefined;
114
121
 
115
122
  constructor({
116
123
  opts,
@@ -212,6 +219,17 @@ export class BeaconNode {
212
219
 
213
220
  const clock = new Clock({config, genesisTime: anchorState.genesisTime, signal});
214
221
 
222
+ // Before any lookup into the legacy column buckets, which can be slow until compacted
223
+ const columnsMinEpoch =
224
+ opts.chain.archiveDataEpochs === Infinity
225
+ ? null
226
+ : getDataColumnSidecarsMinEpoch(config, clock.currentEpoch, opts.chain.archiveDataEpochs);
227
+ await db.compactLegacyDataColumns(
228
+ columnsMinEpoch !== null && columnsMinEpoch >= config.FULU_FORK_EPOCH
229
+ ? computeStartSlotAtEpoch(columnsMinEpoch)
230
+ : 0
231
+ );
232
+
215
233
  await db.init();
216
234
 
217
235
  // Prune hot db repos
@@ -280,6 +298,7 @@ export class BeaconNode {
280
298
  : undefined,
281
299
  builderApiClientOpts: {
282
300
  timeout: opts.executionBuilder.timeout,
301
+ bidDeadline: opts.executionBuilder.bidDeadline,
283
302
  // Sent with all builder api requests, unless the node runs in private mode
284
303
  userAgent: opts.executionBuilder.userAgent,
285
304
  },
@@ -375,23 +394,40 @@ export class BeaconNode {
375
394
  /**
376
395
  * Stop beacon node and its sub-components.
377
396
  */
378
- async close(): Promise<void> {
379
- if (this.status === BeaconNodeStatus.started) {
380
- this.status = BeaconNodeStatus.closing;
381
- this.sync.close();
382
- if (this.restApi) await this.restApi.close();
383
- await this.network.close();
384
- if (this.metricsServer) await this.metricsServer.close();
385
- if (this.monitoring) await this.monitoring.close();
386
- await this.chain.persistToDisk();
387
- await this.chain.close();
397
+ close(): Promise<void> {
398
+ if (this.closePromise !== undefined) return this.closePromise;
399
+ const completion = defer<void>();
400
+ this.closePromise = completion.promise;
401
+ this.status = BeaconNodeStatus.closing;
402
+ void this.closeInternal().then(completion.resolve, completion.reject);
403
+ return this.closePromise;
404
+ }
405
+
406
+ private async closeInternal(): Promise<void> {
407
+ const errors: unknown[] = [];
408
+ for (const cleanup of [
409
+ () => this.sync.close(),
410
+ () => this.restApi?.close(),
411
+ () => this.network.close(),
412
+ () => this.metricsServer?.close(),
413
+ () => this.monitoring?.close(),
414
+ () => this.chain.persistToDisk(),
415
+ () => this.chain.close(),
388
416
  // Abort signal last: close() calls above clear intervals/timeouts so no new
389
417
  // operations get scheduled. If we aborted first, a still-pending interval could
390
418
  // fire and schedule a new operation after abort, leaving it stuck and delaying shutdown.
391
- if (this.controller) this.controller.abort();
392
- await sleep(DELAY_BEFORE_CLOSING_DB_MS);
393
- await this.db.close();
394
- this.status = BeaconNodeStatus.closed;
419
+ () => this.controller?.abort(),
420
+ () => sleep(DELAY_BEFORE_CLOSING_DB_MS),
421
+ () => this.db.close(),
422
+ ]) {
423
+ try {
424
+ await cleanup();
425
+ } catch (error) {
426
+ errors.push(error);
427
+ }
395
428
  }
429
+ this.status = BeaconNodeStatus.closed;
430
+ if (errors.length === 1) throw errors[0];
431
+ if (errors.length > 1) throw new AggregateError(errors, "Beacon node cleanup failed");
396
432
  }
397
433
  }
@@ -1,7 +1,9 @@
1
+ import {BLOCK_PRODUCTION_RACE_CUTOFF_GLOAS_BPS} from "../api/impl/validator/index.js";
1
2
  import {ApiOptions, defaultApiOptions} from "../api/options.js";
2
3
  import {ArchiveMode, DEFAULT_ARCHIVE_MODE, IChainOptions, defaultChainOptions} from "../chain/options.js";
3
4
  import {ValidatorMonitorOpts, defaultValidatorMonitorOpts} from "../chain/validatorMonitor.js";
4
5
  import {DatabaseOptions, defaultDbOptions} from "../db/options.js";
6
+ import {BUILDER_BID_LAG_BUFFER_MS} from "../execution/builder/apiClient.js";
5
7
  import {
6
8
  EngineApiMode,
7
9
  ExecutionBuilderOpts,
@@ -19,16 +21,17 @@ import {SyncOptions, defaultSyncOptions} from "../sync/options.js";
19
21
 
20
22
  // Re-export so the CLI doesn't need to depend on lodestar-api
21
23
  export {allNamespaces} from "../api/rest/index.js";
22
-
23
- // Re-export to use as default values in CLI args
24
+ export type {EngineApiMode};
25
+ // Re-export to use as default values and for validation in CLI args
24
26
  export {
25
- defaultExecutionEngineHttpOpts,
26
- defaultExecutionBuilderHttpOpts,
27
- engineApiModes,
28
27
  ArchiveMode,
28
+ BLOCK_PRODUCTION_RACE_CUTOFF_GLOAS_BPS,
29
+ BUILDER_BID_LAG_BUFFER_MS,
29
30
  DEFAULT_ARCHIVE_MODE,
31
+ defaultExecutionBuilderHttpOpts,
32
+ defaultExecutionEngineHttpOpts,
33
+ engineApiModes,
30
34
  };
31
- export type {EngineApiMode};
32
35
 
33
36
  export interface IBeaconNodeOptions {
34
37
  api: ApiOptions;
@@ -7,6 +7,7 @@ import {IBeaconDb} from "../db/index.js";
7
7
  import {Metrics} from "../metrics/index.js";
8
8
  import {INetwork} from "../network/index.js";
9
9
  import {SyncChainDebugState} from "./range/chain.js";
10
+
10
11
  export type {SyncChainDebugState};
11
12
 
12
13
  export type SyncingStatus = routes.node.SyncingStatus;
package/src/sync/sync.ts CHANGED
@@ -1,13 +1,17 @@
1
1
  import {SLOTS_PER_EPOCH} from "@lodestar/params";
2
- import {Slot} from "@lodestar/types";
2
+ import {computeStartSlotAtEpoch} from "@lodestar/state-transition";
3
+ import {Slot, Status} from "@lodestar/types";
3
4
  import {Logger, toRootHex} from "@lodestar/utils";
4
5
  import {IBeaconChain} from "../chain/index.js";
5
- import {GENESIS_SLOT} from "../constants/constants.js";
6
+ import {GENESIS_EPOCH, GENESIS_SLOT} from "../constants/constants.js";
7
+ import {GoodByeReasonCode} from "../constants/index.js";
8
+ import {IBeaconDb} from "../db/index.js";
6
9
  import {ExecutionEngineState} from "../execution/index.js";
7
10
  import {Metrics} from "../metrics/index.js";
8
- import {INetwork, NetworkEvent, NetworkEventData} from "../network/index.js";
11
+ import {INetwork, NetworkEvent, NetworkEventData, PeerAction} from "../network/index.js";
9
12
  import {ClockEvent} from "../util/clock.js";
10
13
  import {isOptimisticBlock} from "../util/forkChoice.js";
14
+ import {PeerIdStr} from "../util/peerId.js";
11
15
  import {MIN_EPOCH_TO_START_GOSSIP} from "./constants.js";
12
16
  import {IBeaconSync, SyncChainDebugState, SyncModules, SyncState, SyncingStatus, syncStateMetric} from "./interface.js";
13
17
  import {SyncOptions} from "./options.js";
@@ -19,6 +23,7 @@ export class BeaconSync implements IBeaconSync {
19
23
  private readonly logger: Logger;
20
24
  private readonly network: INetwork;
21
25
  private readonly chain: IBeaconChain;
26
+ private readonly db: IBeaconDb;
22
27
  private readonly metrics: Metrics | null;
23
28
  private readonly opts: SyncOptions;
24
29
 
@@ -30,10 +35,11 @@ export class BeaconSync implements IBeaconSync {
30
35
  private readonly slotImportTolerance: Slot;
31
36
 
32
37
  constructor(opts: SyncOptions, modules: SyncModules) {
33
- const {config, chain, metrics, network, logger} = modules;
38
+ const {config, chain, db, metrics, network, logger} = modules;
34
39
  this.opts = opts;
35
40
  this.network = network;
36
41
  this.chain = chain;
42
+ this.db = db;
37
43
  this.metrics = metrics;
38
44
  this.logger = logger;
39
45
  this.rangeSync = new RangeSync(modules, opts);
@@ -192,6 +198,11 @@ export class BeaconSync implements IBeaconSync {
192
198
  */
193
199
  private addPeer = (data: NetworkEventData[NetworkEvent.peerConnected]): void => {
194
200
  const localStatus = this.chain.getStatus();
201
+ // Genesis and equal finalized epochs are already checked by assertPeerRelevance in the network worker
202
+ if (data.status.finalizedEpoch > GENESIS_EPOCH && data.status.finalizedEpoch < localStatus.finalizedEpoch) {
203
+ void this.verifyPastFinalizedCheckpoint(data.peer, data.status);
204
+ }
205
+
195
206
  const syncType = getPeerSyncType(localStatus, data.status, this.chain.forkChoice, this.slotImportTolerance);
196
207
  this.logger.verbose("Peer sync type classified", {
197
208
  peer: data.peer,
@@ -216,6 +227,56 @@ export class BeaconSync implements IBeaconSync {
216
227
  this.updateSyncState();
217
228
  };
218
229
 
230
+ /**
231
+ * A behind peer's finalized checkpoint must be the canonical block in effect at the start slot of its epoch
232
+ */
233
+ async verifyPastFinalizedCheckpoint(peer: PeerIdStr, remote: Status): Promise<void> {
234
+ const startSlot = computeStartSlotAtEpoch(remote.finalizedEpoch);
235
+ const root = toRootHex(remote.finalizedRoot);
236
+ try {
237
+ let reason: string | null = null;
238
+ // After a finality jump, finalized blocks stay in fork choice until the archiver migrates them.
239
+ // Fork choice is pruned only after archiving, so a miss here means the db already has this range.
240
+ const canonicalBlock = this.chain.forkChoice.getCanonicalBlockClosestLteSlot(startSlot);
241
+ if (canonicalBlock !== null) {
242
+ if (canonicalBlock.blockRoot === root) return;
243
+ reason = "finalized_root_not_canonical";
244
+ } else {
245
+ const slot = await this.db.blockArchive.getSlotByRoot(remote.finalizedRoot);
246
+ if (slot !== null && slot > startSlot) {
247
+ reason = "finalized_root_after_epoch_start";
248
+ } else if (slot !== startSlot) {
249
+ const childSlot = await this.db.blockArchive.getSlotByParentRoot(remote.finalizedRoot);
250
+ if (childSlot !== null) {
251
+ if (childSlot <= startSlot) reason = "finalized_root_not_in_effect_at_epoch_start";
252
+ } else if (slot === null && startSlot > this.chain.earliestAvailableSlot) {
253
+ // childSlot == null too, neither the root nor a child is canonical
254
+ // or they are canonical and both pruned but peer's finalized epoch starts after earliestAvailableSlot
255
+ reason = "unknown_finalized_root";
256
+ }
257
+ }
258
+ }
259
+
260
+ if (reason !== null) {
261
+ this.logger.debug("Peer finalized checkpoint not in our chain", {
262
+ peer,
263
+ finalizedEpoch: remote.finalizedEpoch,
264
+ root,
265
+ reason,
266
+ });
267
+ this.metrics?.syncPeerFinalizedCheckpointMismatch.inc({reason});
268
+ this.network.reportPeer(peer, PeerAction.Fatal, "PeerFinalizedCheckpointMismatch");
269
+ await this.network.goodbyeAndDisconnect(peer, GoodByeReasonCode.IRRELEVANT_NETWORK);
270
+ }
271
+ } catch (e) {
272
+ this.logger.debug(
273
+ "Error verifying peer finalized checkpoint",
274
+ {peer, finalizedEpoch: remote.finalizedEpoch, root},
275
+ e as Error
276
+ );
277
+ }
278
+ }
279
+
219
280
  /**
220
281
  * Must be called by libp2p when a peer is removed from the peer manager
221
282
  */
package/src/util/file.ts CHANGED
@@ -1,25 +1,24 @@
1
- import fs from "node:fs";
2
- import {promisify} from "node:util";
1
+ import {readFile as fsReadFile, mkdir, readdir, stat, unlink, writeFile} from "node:fs/promises";
3
2
 
4
3
  /** Ensure a directory exists */
5
4
  export async function ensureDir(path: string): Promise<void> {
6
5
  try {
7
- await promisify(fs.stat)(path);
6
+ await stat(path);
8
7
  } catch (_) {
9
8
  // not exists
10
- await promisify(fs.mkdir)(path, {recursive: true});
9
+ await mkdir(path, {recursive: true});
11
10
  }
12
11
  }
13
12
 
14
13
  /** Write data to a file if it does not exist */
15
14
  export async function writeIfNotExist(filepath: string, bytes: Uint8Array): Promise<boolean> {
16
15
  try {
17
- await promisify(fs.stat)(filepath);
16
+ await stat(filepath);
18
17
  return false;
19
18
  // file exists, do nothing
20
19
  } catch (_) {
21
20
  // not exists
22
- await promisify(fs.writeFile)(filepath, bytes);
21
+ await writeFile(filepath, bytes);
23
22
  return true;
24
23
  }
25
24
  }
@@ -27,7 +26,7 @@ export async function writeIfNotExist(filepath: string, bytes: Uint8Array): Prom
27
26
  /** Remove a file if it exists */
28
27
  export async function removeFile(path: string): Promise<boolean> {
29
28
  try {
30
- await promisify(fs.unlink)(path);
29
+ await unlink(path);
31
30
  return true;
32
31
  } catch (_) {
33
32
  // may not exists
@@ -37,7 +36,7 @@ export async function removeFile(path: string): Promise<boolean> {
37
36
 
38
37
  export async function readFile(path: string): Promise<Uint8Array | null> {
39
38
  try {
40
- return await fs.promises.readFile(path);
39
+ return await fsReadFile(path);
41
40
  } catch (_) {
42
41
  return null;
43
42
  }
@@ -45,7 +44,7 @@ export async function readFile(path: string): Promise<Uint8Array | null> {
45
44
 
46
45
  export async function readFileNames(folderPath: string): Promise<string[]> {
47
46
  try {
48
- return await fs.promises.readdir(folderPath);
47
+ return await readdir(folderPath);
49
48
  } catch (_) {
50
49
  return [];
51
50
  }
@@ -69,7 +69,7 @@ export class JobItemQueue<Args extends any[], R> {
69
69
  if (this.jobs.length === 1 && this.opts.noYieldIfOneItem) {
70
70
  void this.runJob();
71
71
  } else if (this.runningJobs < this.opts.maxConcurrency) {
72
- callInNextEventLoop(this.runJob);
72
+ callInNextEventLoop(() => void this.runJob());
73
73
  }
74
74
  });
75
75
  }
@@ -652,6 +652,46 @@ export function getBeaconBlockRootFromExecutionPayloadEnvelopeSerialized(data: U
652
652
  return "0x" + blockRootBuf.toString("hex");
653
653
  }
654
654
 
655
+ // transactions offset within ExecutionPayload fixed portion, see SLOT_NUMBER_OFFSET_IN_EXECUTION_PAYLOAD:
656
+ // everything up to and including blockHash(32) = 504, followed by withdrawals_offset(4)
657
+ const PAYLOAD_START_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE =
658
+ ENVELOPE_START_IN_SIGNED + EXECUTION_PAYLOAD_ENVELOPE_FIXED_SIZE; // 180
659
+ const TRANSACTIONS_OFFSET_POSITION_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE =
660
+ PAYLOAD_START_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE + 504; // 684
661
+ const WITHDRAWALS_OFFSET_POSITION_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE =
662
+ TRANSACTIONS_OFFSET_POSITION_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE + 4; // 688
663
+
664
+ /**
665
+ * Transaction count of the payload, read from the SSZ offsets without deserializing the envelope.
666
+ * Returns null on malformed offsets, deserialization reports the exact error.
667
+ */
668
+ export function getTransactionCountFromExecutionPayloadEnvelopeSerialized(data: Uint8Array): number | null {
669
+ if (data.length < WITHDRAWALS_OFFSET_POSITION_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE + 4) {
670
+ return null;
671
+ }
672
+
673
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
674
+ const transactionsOffset = view.getUint32(TRANSACTIONS_OFFSET_POSITION_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE, true);
675
+ const withdrawalsOffset = view.getUint32(WITHDRAWALS_OFFSET_POSITION_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE, true);
676
+ if (transactionsOffset > withdrawalsOffset) {
677
+ return null;
678
+ }
679
+ if (transactionsOffset === withdrawalsOffset) {
680
+ return 0;
681
+ }
682
+
683
+ const transactionsStart = PAYLOAD_START_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE + transactionsOffset;
684
+ if (transactionsStart + 4 > data.length) {
685
+ return null;
686
+ }
687
+ // first offset of a non-empty list is the size of its offset table, 4 bytes per element
688
+ const firstTransactionOffset = view.getUint32(transactionsStart, true);
689
+ if (firstTransactionOffset % 4 !== 0 || firstTransactionOffset > withdrawalsOffset - transactionsOffset) {
690
+ return null;
691
+ }
692
+ return firstTransactionOffset / 4;
693
+ }
694
+
655
695
  /**
656
696
  * BeaconState of all forks (up until Electra, check with new forks)
657
697
  * class BeaconState(Container):
@@ -854,7 +894,7 @@ export function getBlobKzgCommitmentsCountFromSignedBeaconBlockSerialized(
854
894
 
855
895
  const start = bidMsgStart + commitmentsRange.start;
856
896
  const end = bidMsgStart + commitmentsRange.end;
857
- return Math.round(((end > blockBytes.byteLength ? blockBytes.byteLength : end) - start) / commitmentSize);
897
+ return Math.round((Math.min(end, blockBytes.byteLength) - start) / commitmentSize);
858
898
  }
859
899
 
860
900
  const {SignedBeaconBlock, BeaconBlock, BeaconBlockBody, KZGCommitment} = ssz[forkName as ForkPostDeneb];
@@ -880,5 +920,5 @@ export function getBlobKzgCommitmentsCountFromSignedBeaconBlockSerialized(
880
920
  const end = messageRange.end + bodyRange.end + kzgCommitmentsRange.end;
881
921
  const start = messageRange.start + bodyRange.start + kzgCommitmentsRange.start;
882
922
 
883
- return Math.round(((end > blockBytes.byteLength ? blockBytes.byteLength : end) - start) / commitmentSize);
923
+ return Math.round((Math.min(end, blockBytes.byteLength) - start) / commitmentSize);
884
924
  }