@lodestar/beacon-node 1.39.0 → 1.40.0-dev.1c71f4299a

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 (245) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +8 -18
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/beacon/state/utils.d.ts +2 -7
  5. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  6. package/lib/api/impl/beacon/state/utils.js +0 -12
  7. package/lib/api/impl/beacon/state/utils.js.map +1 -1
  8. package/lib/api/impl/config/constants.d.ts +3 -0
  9. package/lib/api/impl/config/constants.d.ts.map +1 -1
  10. package/lib/api/impl/config/constants.js +5 -1
  11. package/lib/api/impl/config/constants.js.map +1 -1
  12. package/lib/api/impl/debug/index.d.ts +1 -1
  13. package/lib/api/impl/debug/index.d.ts.map +1 -1
  14. package/lib/api/impl/debug/index.js +3 -6
  15. package/lib/api/impl/debug/index.js.map +1 -1
  16. package/lib/api/impl/lodestar/index.d.ts.map +1 -1
  17. package/lib/api/impl/lodestar/index.js +6 -1
  18. package/lib/api/impl/lodestar/index.js.map +1 -1
  19. package/lib/api/impl/proof/index.d.ts.map +1 -1
  20. package/lib/api/impl/proof/index.js +1 -2
  21. package/lib/api/impl/proof/index.js.map +1 -1
  22. package/lib/api/impl/validator/index.d.ts.map +1 -1
  23. package/lib/api/impl/validator/index.js +1 -3
  24. package/lib/api/impl/validator/index.js.map +1 -1
  25. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
  26. package/lib/chain/archiveStore/historicalState/getHistoricalState.js +5 -3
  27. package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
  28. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
  29. package/lib/chain/archiveStore/utils/archiveBlocks.js +23 -14
  30. package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
  31. package/lib/chain/blocks/blockInput/blockInput.d.ts +2 -0
  32. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  33. package/lib/chain/blocks/blockInput/blockInput.js +6 -0
  34. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  35. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  36. package/lib/chain/blocks/importBlock.js +14 -9
  37. package/lib/chain/blocks/importBlock.js.map +1 -1
  38. package/lib/chain/blocks/index.d.ts.map +1 -1
  39. package/lib/chain/blocks/index.js +0 -14
  40. package/lib/chain/blocks/index.js.map +1 -1
  41. package/lib/chain/blocks/types.d.ts +0 -2
  42. package/lib/chain/blocks/types.d.ts.map +1 -1
  43. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  44. package/lib/chain/blocks/verifyBlock.js +8 -8
  45. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  46. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts.map +1 -1
  47. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js +1 -0
  48. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js.map +1 -1
  49. package/lib/chain/blocks/writeBlockInputToDb.d.ts +1 -4
  50. package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
  51. package/lib/chain/blocks/writeBlockInputToDb.js +20 -28
  52. package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
  53. package/lib/chain/chain.d.ts +16 -3
  54. package/lib/chain/chain.d.ts.map +1 -1
  55. package/lib/chain/chain.js +165 -7
  56. package/lib/chain/chain.js.map +1 -1
  57. package/lib/chain/initState.d.ts +1 -1
  58. package/lib/chain/initState.d.ts.map +1 -1
  59. package/lib/chain/initState.js +5 -3
  60. package/lib/chain/initState.js.map +1 -1
  61. package/lib/chain/interface.d.ts +16 -3
  62. package/lib/chain/interface.d.ts.map +1 -1
  63. package/lib/chain/interface.js.map +1 -1
  64. package/lib/chain/lightClient/proofs.d.ts.map +1 -1
  65. package/lib/chain/lightClient/proofs.js +0 -2
  66. package/lib/chain/lightClient/proofs.js.map +1 -1
  67. package/lib/chain/opPools/aggregatedAttestationPool.d.ts +5 -9
  68. package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
  69. package/lib/chain/opPools/aggregatedAttestationPool.js +12 -141
  70. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  71. package/lib/chain/opPools/opPool.js +5 -8
  72. package/lib/chain/opPools/opPool.js.map +1 -1
  73. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  74. package/lib/chain/prepareNextSlot.js +4 -7
  75. package/lib/chain/prepareNextSlot.js.map +1 -1
  76. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  77. package/lib/chain/produceBlock/produceBlockBody.js +1 -1
  78. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  79. package/lib/chain/regen/interface.d.ts +1 -5
  80. package/lib/chain/regen/interface.d.ts.map +1 -1
  81. package/lib/chain/regen/queued.d.ts +4 -7
  82. package/lib/chain/regen/queued.d.ts.map +1 -1
  83. package/lib/chain/regen/queued.js +15 -25
  84. package/lib/chain/regen/queued.js.map +1 -1
  85. package/lib/chain/regen/regen.d.ts +1 -1
  86. package/lib/chain/regen/regen.d.ts.map +1 -1
  87. package/lib/chain/regen/regen.js +13 -17
  88. package/lib/chain/regen/regen.js.map +1 -1
  89. package/lib/chain/shufflingCache.d.ts +16 -11
  90. package/lib/chain/shufflingCache.d.ts.map +1 -1
  91. package/lib/chain/shufflingCache.js +47 -41
  92. package/lib/chain/shufflingCache.js.map +1 -1
  93. package/lib/chain/stateCache/blockStateCacheImpl.d.ts +1 -2
  94. package/lib/chain/stateCache/blockStateCacheImpl.d.ts.map +1 -1
  95. package/lib/chain/stateCache/blockStateCacheImpl.js +2 -2
  96. package/lib/chain/stateCache/blockStateCacheImpl.js.map +1 -1
  97. package/lib/chain/stateCache/fifoBlockStateCache.d.ts +1 -2
  98. package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
  99. package/lib/chain/stateCache/fifoBlockStateCache.js +4 -4
  100. package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
  101. package/lib/chain/stateCache/inMemoryCheckpointsCache.d.ts +4 -5
  102. package/lib/chain/stateCache/inMemoryCheckpointsCache.d.ts.map +1 -1
  103. package/lib/chain/stateCache/inMemoryCheckpointsCache.js +9 -10
  104. package/lib/chain/stateCache/inMemoryCheckpointsCache.js.map +1 -1
  105. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +5 -6
  106. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  107. package/lib/chain/stateCache/persistentCheckpointsCache.js +17 -17
  108. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  109. package/lib/chain/stateCache/types.d.ts +5 -6
  110. package/lib/chain/stateCache/types.d.ts.map +1 -1
  111. package/lib/chain/stateCache/types.js.map +1 -1
  112. package/lib/chain/validation/attestation.d.ts.map +1 -1
  113. package/lib/chain/validation/attestation.js +2 -2
  114. package/lib/chain/validation/attestation.js.map +1 -1
  115. package/lib/chain/validation/attesterSlashing.d.ts.map +1 -1
  116. package/lib/chain/validation/attesterSlashing.js +1 -1
  117. package/lib/chain/validation/attesterSlashing.js.map +1 -1
  118. package/lib/chain/validation/block.d.ts.map +1 -1
  119. package/lib/chain/validation/block.js +2 -0
  120. package/lib/chain/validation/block.js.map +1 -1
  121. package/lib/chain/validation/blsToExecutionChange.d.ts.map +1 -1
  122. package/lib/chain/validation/blsToExecutionChange.js +9 -2
  123. package/lib/chain/validation/blsToExecutionChange.js.map +1 -1
  124. package/lib/chain/validation/proposerSlashing.js +2 -1
  125. package/lib/chain/validation/proposerSlashing.js.map +1 -1
  126. package/lib/chain/validatorMonitor.d.ts +2 -0
  127. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  128. package/lib/chain/validatorMonitor.js +42 -3
  129. package/lib/chain/validatorMonitor.js.map +1 -1
  130. package/lib/db/repositories/checkpointState.d.ts +2 -6
  131. package/lib/db/repositories/checkpointState.d.ts.map +1 -1
  132. package/lib/db/repositories/checkpointState.js +3 -15
  133. package/lib/db/repositories/checkpointState.js.map +1 -1
  134. package/lib/db/repositories/stateArchive.d.ts +9 -9
  135. package/lib/db/repositories/stateArchive.d.ts.map +1 -1
  136. package/lib/db/repositories/stateArchive.js +6 -21
  137. package/lib/db/repositories/stateArchive.js.map +1 -1
  138. package/lib/execution/engine/mock.d.ts +9 -6
  139. package/lib/execution/engine/mock.d.ts.map +1 -1
  140. package/lib/execution/engine/mock.js +34 -7
  141. package/lib/execution/engine/mock.js.map +1 -1
  142. package/lib/index.d.ts +1 -1
  143. package/lib/index.d.ts.map +1 -1
  144. package/lib/index.js +1 -1
  145. package/lib/index.js.map +1 -1
  146. package/lib/metrics/metrics/lodestar.d.ts +8 -6
  147. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  148. package/lib/metrics/metrics/lodestar.js +27 -17
  149. package/lib/metrics/metrics/lodestar.js.map +1 -1
  150. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  151. package/lib/network/processor/gossipHandlers.js +0 -3
  152. package/lib/network/processor/gossipHandlers.js.map +1 -1
  153. package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
  154. package/lib/network/reqresp/handlers/beaconBlocksByRange.js +2 -4
  155. package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
  156. package/lib/network/reqresp/handlers/beaconBlocksByRoot.d.ts +1 -2
  157. package/lib/network/reqresp/handlers/beaconBlocksByRoot.d.ts.map +1 -1
  158. package/lib/network/reqresp/handlers/beaconBlocksByRoot.js +5 -26
  159. package/lib/network/reqresp/handlers/beaconBlocksByRoot.js.map +1 -1
  160. package/lib/network/reqresp/handlers/blobSidecarsByRoot.d.ts +1 -2
  161. package/lib/network/reqresp/handlers/blobSidecarsByRoot.d.ts.map +1 -1
  162. package/lib/network/reqresp/handlers/blobSidecarsByRoot.js +5 -7
  163. package/lib/network/reqresp/handlers/blobSidecarsByRoot.js.map +1 -1
  164. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
  165. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +1 -2
  166. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
  167. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.d.ts.map +1 -1
  168. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +1 -5
  169. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js.map +1 -1
  170. package/lib/network/reqresp/handlers/index.js +2 -2
  171. package/lib/network/reqresp/handlers/index.js.map +1 -1
  172. package/lib/network/reqresp/utils/dataColumnResponseValidation.js +1 -1
  173. package/lib/network/reqresp/utils/dataColumnResponseValidation.js.map +1 -1
  174. package/lib/node/nodejs.d.ts.map +1 -1
  175. package/lib/node/nodejs.js +17 -2
  176. package/lib/node/nodejs.js.map +1 -1
  177. package/lib/sync/range/chain.d.ts.map +1 -1
  178. package/lib/sync/range/chain.js +0 -1
  179. package/lib/sync/range/chain.js.map +1 -1
  180. package/lib/sync/range/range.d.ts.map +1 -1
  181. package/lib/sync/range/range.js +0 -3
  182. package/lib/sync/range/range.js.map +1 -1
  183. package/lib/sync/unknownBlock.d.ts.map +1 -1
  184. package/lib/sync/unknownBlock.js +0 -3
  185. package/lib/sync/unknownBlock.js.map +1 -1
  186. package/lib/util/sszBytes.js +1 -1
  187. package/lib/util/sszBytes.js.map +1 -1
  188. package/package.json +15 -15
  189. package/src/api/impl/beacon/blocks/index.ts +8 -18
  190. package/src/api/impl/beacon/state/utils.ts +2 -22
  191. package/src/api/impl/config/constants.ts +8 -0
  192. package/src/api/impl/debug/index.ts +2 -6
  193. package/src/api/impl/lodestar/index.ts +7 -1
  194. package/src/api/impl/proof/index.ts +1 -2
  195. package/src/api/impl/validator/index.ts +1 -3
  196. package/src/chain/archiveStore/historicalState/getHistoricalState.ts +5 -3
  197. package/src/chain/archiveStore/utils/archiveBlocks.ts +25 -14
  198. package/src/chain/blocks/blockInput/blockInput.ts +8 -0
  199. package/src/chain/blocks/importBlock.ts +15 -9
  200. package/src/chain/blocks/index.ts +0 -19
  201. package/src/chain/blocks/types.ts +0 -2
  202. package/src/chain/blocks/verifyBlock.ts +9 -11
  203. package/src/chain/blocks/verifyBlocksStateTransitionOnly.ts +1 -0
  204. package/src/chain/blocks/writeBlockInputToDb.ts +24 -30
  205. package/src/chain/chain.ts +191 -10
  206. package/src/chain/initState.ts +5 -3
  207. package/src/chain/interface.ts +18 -2
  208. package/src/chain/lightClient/proofs.ts +0 -2
  209. package/src/chain/opPools/aggregatedAttestationPool.ts +19 -191
  210. package/src/chain/opPools/opPool.ts +5 -7
  211. package/src/chain/prepareNextSlot.ts +2 -6
  212. package/src/chain/produceBlock/produceBlockBody.ts +6 -1
  213. package/src/chain/regen/interface.ts +1 -5
  214. package/src/chain/regen/queued.ts +15 -34
  215. package/src/chain/regen/regen.ts +12 -18
  216. package/src/chain/shufflingCache.ts +67 -50
  217. package/src/chain/stateCache/blockStateCacheImpl.ts +2 -3
  218. package/src/chain/stateCache/fifoBlockStateCache.ts +4 -5
  219. package/src/chain/stateCache/inMemoryCheckpointsCache.ts +9 -15
  220. package/src/chain/stateCache/persistentCheckpointsCache.ts +17 -25
  221. package/src/chain/stateCache/types.ts +5 -10
  222. package/src/chain/validation/attestation.ts +3 -3
  223. package/src/chain/validation/attesterSlashing.ts +8 -1
  224. package/src/chain/validation/block.ts +3 -0
  225. package/src/chain/validation/blsToExecutionChange.ts +9 -7
  226. package/src/chain/validation/proposerSlashing.ts +2 -1
  227. package/src/chain/validatorMonitor.ts +52 -3
  228. package/src/db/repositories/checkpointState.ts +3 -19
  229. package/src/db/repositories/stateArchive.ts +13 -27
  230. package/src/execution/engine/mock.ts +40 -13
  231. package/src/index.ts +1 -1
  232. package/src/metrics/metrics/lodestar.ts +28 -17
  233. package/src/network/processor/gossipHandlers.ts +0 -3
  234. package/src/network/reqresp/handlers/beaconBlocksByRange.ts +2 -4
  235. package/src/network/reqresp/handlers/beaconBlocksByRoot.ts +5 -32
  236. package/src/network/reqresp/handlers/blobSidecarsByRoot.ts +5 -9
  237. package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +5 -2
  238. package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +1 -5
  239. package/src/network/reqresp/handlers/index.ts +2 -2
  240. package/src/network/reqresp/utils/dataColumnResponseValidation.ts +1 -1
  241. package/src/node/nodejs.ts +18 -3
  242. package/src/sync/range/chain.ts +0 -1
  243. package/src/sync/range/range.ts +0 -3
  244. package/src/sync/unknownBlock.ts +0 -3
  245. package/src/util/sszBytes.ts +1 -1
@@ -24,7 +24,7 @@ import {
24
24
  altair,
25
25
  deneb,
26
26
  } from "@lodestar/types";
27
- import {LogData, LogHandler, LogLevel, Logger, MapDef, MapDefMax, toRootHex} from "@lodestar/utils";
27
+ import {LogData, LogHandler, LogLevel, Logger, MapDef, MapDefMax, prettyPrintIndices, toRootHex} from "@lodestar/utils";
28
28
  import {GENESIS_SLOT} from "../constants/constants.js";
29
29
  import {RegistryMetricCreator} from "../metrics/index.js";
30
30
 
@@ -39,7 +39,8 @@ const MAX_CACHED_DISTINCT_TARGETS = 4;
39
39
  const LATE_ATTESTATION_SUBMISSION_BPS = 5000;
40
40
  const LATE_BLOCK_SUBMISSION_BPS = 2500;
41
41
 
42
- const RETAIN_REGISTERED_VALIDATORS_MS = 1 * 3600 * 1000; // 1 hour
42
+ /** Number of epochs to retain registered validators after their last registration */
43
+ const RETAIN_REGISTERED_VALIDATORS_EPOCHS = 2;
43
44
 
44
45
  type Seconds = number;
45
46
  export enum OpSource {
@@ -97,6 +98,8 @@ export type ValidatorMonitor = {
97
98
  ): void;
98
99
  onceEveryEndOfEpoch(state: CachedBeaconStateAllForks): void;
99
100
  scrapeMetrics(slotClock: Slot): void;
101
+ /** Returns the list of validator indices currently being monitored */
102
+ getMonitoredValidatorIndices(): ValidatorIndex[];
100
103
  };
101
104
 
102
105
  export type ValidatorMonitorOpts = {
@@ -284,6 +287,9 @@ export function createValidatorMonitor(
284
287
  logger[logLevel](message, context);
285
288
  };
286
289
 
290
+ // Calculate retain time dynamically based on slot duration (2 epochs)
291
+ const retainRegisteredValidatorsMs = SLOTS_PER_EPOCH * config.SLOT_DURATION_MS * RETAIN_REGISTERED_VALIDATORS_EPOCHS;
292
+
287
293
  /** The validators that require additional monitoring. */
288
294
  const validators = new MapDef<ValidatorIndex, MonitoredValidator>(() => ({
289
295
  summaries: new Map<Epoch, EpochSummary>(),
@@ -306,11 +312,19 @@ export function createValidatorMonitor(
306
312
 
307
313
  let lastRegisteredStatusEpoch = -1;
308
314
 
315
+ // Track validator additions/removals per epoch for logging
316
+ const addedValidatorsInEpoch: Set<ValidatorIndex> = new Set();
317
+ const removedValidatorsInEpoch: Set<ValidatorIndex> = new Set();
318
+
309
319
  const validatorMonitorMetrics = metricsRegister ? createValidatorMonitorMetrics(metricsRegister) : null;
310
320
 
311
321
  const validatorMonitor: ValidatorMonitor = {
312
322
  registerLocalValidator(index) {
323
+ const isNewValidator = !validators.has(index);
313
324
  validators.getOrDefault(index).lastRegisteredTimeMs = Date.now();
325
+ if (isNewValidator) {
326
+ addedValidatorsInEpoch.add(index);
327
+ }
314
328
  },
315
329
 
316
330
  registerLocalValidatorInSyncCommittee(index, untilEpoch) {
@@ -673,11 +687,29 @@ export function createValidatorMonitor(
673
687
 
674
688
  // Prune validators not seen in a while
675
689
  for (const [index, validator] of validators.entries()) {
676
- if (Date.now() - validator.lastRegisteredTimeMs > RETAIN_REGISTERED_VALIDATORS_MS) {
690
+ if (Date.now() - validator.lastRegisteredTimeMs > retainRegisteredValidatorsMs) {
677
691
  validators.delete(index);
692
+ removedValidatorsInEpoch.add(index);
678
693
  }
679
694
  }
680
695
 
696
+ // Log validator monitor status every epoch
697
+ const allIndices = Array.from(validators.keys()).sort((a, b) => a - b);
698
+ const addedIndices = Array.from(addedValidatorsInEpoch).sort((a, b) => a - b);
699
+ const removedIndices = Array.from(removedValidatorsInEpoch).sort((a, b) => a - b);
700
+
701
+ log("Validator monitor status", {
702
+ epoch: computeEpochAtSlot(headState.slot),
703
+ added: addedIndices.length > 0 ? prettyPrintIndices(addedIndices) : "none",
704
+ removed: removedIndices.length > 0 ? prettyPrintIndices(removedIndices) : "none",
705
+ total: validators.size,
706
+ indices: prettyPrintIndices(allIndices),
707
+ });
708
+
709
+ // Clear tracking sets for next epoch
710
+ addedValidatorsInEpoch.clear();
711
+ removedValidatorsInEpoch.clear();
712
+
681
713
  // Compute summaries of previous epoch attestation performance
682
714
  const prevEpoch = computeEpochAtSlot(headState.slot) - 1;
683
715
 
@@ -736,6 +768,13 @@ export function createValidatorMonitor(
736
768
  scrapeMetrics(slotClock) {
737
769
  validatorMonitorMetrics?.validatorsConnected.set(validators.size);
738
770
 
771
+ // Update static metric with connected validator indices
772
+ if (validatorMonitorMetrics?.validatorsConnectedIndices) {
773
+ validatorMonitorMetrics.validatorsConnectedIndices.reset();
774
+ const allIndices = Array.from(validators.keys()).sort((a, b) => a - b);
775
+ validatorMonitorMetrics.validatorsConnectedIndices.set({indices: prettyPrintIndices(allIndices)}, 1);
776
+ }
777
+
739
778
  const epoch = computeEpochAtSlot(slotClock);
740
779
  const slotInEpoch = slotClock % SLOTS_PER_EPOCH;
741
780
 
@@ -815,6 +854,10 @@ export function createValidatorMonitor(
815
854
  validatorMonitorMetrics?.prevEpochSyncCommitteeHits.set(prevEpochSyncCommitteeHits);
816
855
  validatorMonitorMetrics?.prevEpochSyncCommitteeMisses.set(prevEpochSyncCommitteeMisses);
817
856
  },
857
+
858
+ getMonitoredValidatorIndices() {
859
+ return Array.from(validators.keys()).sort((a, b) => a - b);
860
+ },
818
861
  };
819
862
 
820
863
  // Register a single collect() function to run all validatorMonitor metrics
@@ -1098,6 +1141,12 @@ function createValidatorMonitorMetrics(register: RegistryMetricCreator) {
1098
1141
  help: "Count of validators that are specifically monitored by this beacon node",
1099
1142
  }),
1100
1143
 
1144
+ validatorsConnectedIndices: register.gauge<{indices: string}>({
1145
+ name: "validator_monitor_indices",
1146
+ help: "Static metric with connected validator indices as label, value is always 1",
1147
+ labelNames: ["indices"],
1148
+ }),
1149
+
1101
1150
  validatorsInSyncCommittee: register.gauge({
1102
1151
  name: "validator_monitor_validators_in_sync_committee",
1103
1152
  help: "Count of validators monitored by this beacon node that are part of sync committee",
@@ -1,31 +1,15 @@
1
1
  import {ChainForkConfig} from "@lodestar/config";
2
- import {Db, Repository} from "@lodestar/db";
3
- import {BeaconStateAllForks} from "@lodestar/state-transition";
4
- import {ssz} from "@lodestar/types";
2
+ import {BinaryRepository, Db} from "@lodestar/db";
5
3
  import {Bucket, getBucketNameByValue} from "../buckets.js";
6
4
 
7
5
  /**
8
6
  * Store temporary checkpoint states.
9
7
  * We should only put/get binary data from this repository, consumer will load it into an existing state ViewDU object.
10
8
  */
11
- export class CheckpointStateRepository extends Repository<Uint8Array, BeaconStateAllForks> {
9
+ export class CheckpointStateRepository extends BinaryRepository<Uint8Array> {
12
10
  constructor(config: ChainForkConfig, db: Db) {
13
- // Pick some type but won't be used. Casted to any because no type can match `BeaconStateAllForks`
14
- const type = ssz.phase0.BeaconState;
15
11
  const bucket = Bucket.allForks_checkpointState;
16
12
  // biome-ignore lint/suspicious/noExplicitAny: The type is complex to specify a proper override
17
- super(config, db, bucket, type as any, getBucketNameByValue(bucket));
18
- }
19
-
20
- getId(): Uint8Array {
21
- throw Error("CheckpointStateRepository does not work with value");
22
- }
23
-
24
- encodeValue(): Uint8Array {
25
- throw Error("CheckpointStateRepository does not work with value");
26
- }
27
-
28
- decodeValue(): BeaconStateAllForks {
29
- throw Error("CheckpointStateRepository does not work with value");
13
+ super(config, db, bucket, getBucketNameByValue(bucket));
30
14
  }
31
15
  }
@@ -1,39 +1,25 @@
1
1
  import {ChainForkConfig} from "@lodestar/config";
2
- import {Db, Repository} from "@lodestar/db";
3
- import {BeaconStateAllForks} from "@lodestar/state-transition";
4
- import {Epoch, Root, RootHex, Slot, ssz} from "@lodestar/types";
2
+ import {BinaryRepository, Db} from "@lodestar/db";
3
+ import {Root, RootHex, Slot} from "@lodestar/types";
5
4
  import {bytesToInt, toHex} from "@lodestar/utils";
6
- import {getStateTypeFromBytes} from "../../util/multifork.js";
7
5
  import {Bucket, getBucketNameByValue} from "../buckets.js";
8
6
  import {getRootIndex, getRootIndexKey, storeRootIndex} from "./stateArchiveIndex.js";
9
7
 
10
- export class StateArchiveRepository extends Repository<Slot, BeaconStateAllForks> {
8
+ export type BeaconStateArchive = {
9
+ serialize(): Uint8Array;
10
+ hashTreeRoot(): Root;
11
+ };
12
+
13
+ export class StateArchiveRepository extends BinaryRepository<Slot> {
11
14
  constructor(config: ChainForkConfig, db: Db) {
12
- // Pick some type but won't be used. Casted to any because no type can match `BeaconStateAllForks`
13
- // biome-ignore lint/suspicious/noExplicitAny: We need to use `any` type here
14
- const type = ssz.phase0.BeaconState as any;
15
15
  const bucket = Bucket.allForks_stateArchive;
16
- super(config, db, bucket, type, getBucketNameByValue(bucket));
17
- }
18
-
19
- // Overrides for multi-fork
20
-
21
- encodeValue(value: BeaconStateAllForks): Uint8Array {
22
- return value.serialize();
23
- }
24
-
25
- decodeValue(data: Uint8Array): BeaconStateAllForks {
26
- return getStateTypeFromBytes(this.config, data).deserializeToViewDU(data);
16
+ super(config, db, bucket, getBucketNameByValue(bucket));
27
17
  }
28
18
 
29
19
  // Handle key as slot
30
20
 
31
- async put(key: Slot, value: BeaconStateAllForks): Promise<void> {
32
- await Promise.all([super.put(key, value), storeRootIndex(this.db, key, value.hashTreeRoot())]);
33
- }
34
-
35
- getId(state: BeaconStateAllForks): Epoch {
36
- return state.slot;
21
+ async put(key: Slot, value: BeaconStateArchive): Promise<void> {
22
+ await Promise.all([super.putBinary(key, value.serialize()), storeRootIndex(this.db, key, value.hashTreeRoot())]);
37
23
  }
38
24
 
39
25
  decodeKey(data: Uint8Array): number {
@@ -42,10 +28,10 @@ export class StateArchiveRepository extends Repository<Slot, BeaconStateAllForks
42
28
 
43
29
  // Index Root -> Slot
44
30
 
45
- async getByRoot(stateRoot: Root): Promise<BeaconStateAllForks | null> {
31
+ async getBinaryByRoot(stateRoot: Root): Promise<Uint8Array | null> {
46
32
  const slot = await this.getSlotByRoot(stateRoot);
47
33
  if (slot !== null && Number.isInteger(slot)) {
48
- return this.get(slot);
34
+ return this.getBinary(slot);
49
35
  }
50
36
  return null;
51
37
  }
@@ -1,4 +1,5 @@
1
1
  import crypto from "node:crypto";
2
+ import {ChainConfig} from "@lodestar/config";
2
3
  import {
3
4
  BLOB_TX_TYPE,
4
5
  BYTES_PER_FIELD_ELEMENT,
@@ -7,7 +8,9 @@ import {
7
8
  ForkPostBellatrix,
8
9
  ForkPostCapella,
9
10
  ForkSeq,
11
+ SLOTS_PER_EPOCH,
10
12
  } from "@lodestar/params";
13
+ import {computeTimeAtSlot} from "@lodestar/state-transition";
11
14
  import {ExecutionPayload, RootHex, bellatrix, deneb, ssz} from "@lodestar/types";
12
15
  import {fromHex, toRootHex} from "@lodestar/utils";
13
16
  import {ZERO_HASH_HEX} from "../../constants/index.js";
@@ -34,14 +37,11 @@ const INTEROP_GAS_LIMIT = 30e6;
34
37
  const PRUNE_PAYLOAD_ID_AFTER_MS = 5000;
35
38
 
36
39
  export type ExecutionEngineMockOpts = {
37
- genesisBlockHash: string;
40
+ genesisBlockHash?: string;
38
41
  eth1BlockHash?: string;
39
42
  onlyPredefinedResponses?: boolean;
40
- capellaForkTimestamp?: number;
41
- denebForkTimestamp?: number;
42
- electraForkTimestamp?: number;
43
- fuluForkTimestamp?: number;
44
- gloasForkTimestamp?: number;
43
+ genesisTime?: number;
44
+ config?: ChainConfig;
45
45
  };
46
46
 
47
47
  type ExecutionBlock = {
@@ -74,17 +74,21 @@ export class ExecutionEngineMockBackend implements JsonRpcBackend {
74
74
  /** Preparing payloads to be retrieved via engine_getPayloadV1 */
75
75
  private readonly preparingPayloads = new Map<number, PreparedPayload>();
76
76
  private readonly payloadsForDeletion = new Map<number, number>();
77
-
78
77
  private readonly predefinedPayloadStatuses = new Map<RootHex, PayloadStatus>();
79
78
 
80
79
  private payloadId = 0;
80
+ private capellaForkTimestamp: number;
81
+ private denebForkTimestamp: number;
82
+ private electraForkTimestamp: number;
83
+ private fuluForkTimestamp: number;
84
+ private gloasForkTimestamp: number;
81
85
 
82
86
  readonly handlers: {
83
87
  [K in keyof EngineApiRpcParamTypes]: (...args: EngineApiRpcParamTypes[K]) => EngineApiRpcReturnTypes[K];
84
88
  };
85
89
 
86
90
  constructor(private readonly opts: ExecutionEngineMockOpts) {
87
- this.validBlocks.set(opts.genesisBlockHash, {
91
+ this.validBlocks.set(opts.genesisBlockHash ?? ZERO_HASH_HEX, {
88
92
  parentHash: ZERO_HASH_HEX,
89
93
  blockHash: ZERO_HASH_HEX,
90
94
  timestamp: 0,
@@ -100,6 +104,29 @@ export class ExecutionEngineMockBackend implements JsonRpcBackend {
100
104
  blockNumber: 1,
101
105
  });
102
106
 
107
+ const {config} = opts;
108
+
109
+ this.capellaForkTimestamp =
110
+ opts.genesisTime && config
111
+ ? computeTimeAtSlot(config, config.CAPELLA_FORK_EPOCH * SLOTS_PER_EPOCH, opts.genesisTime)
112
+ : Infinity;
113
+ this.denebForkTimestamp =
114
+ opts.genesisTime && config
115
+ ? computeTimeAtSlot(config, config.DENEB_FORK_EPOCH * SLOTS_PER_EPOCH, opts.genesisTime)
116
+ : Infinity;
117
+ this.electraForkTimestamp =
118
+ opts.genesisTime && config
119
+ ? computeTimeAtSlot(config, config.ELECTRA_FORK_EPOCH * SLOTS_PER_EPOCH, opts.genesisTime)
120
+ : Infinity;
121
+ this.fuluForkTimestamp =
122
+ opts.genesisTime && config
123
+ ? computeTimeAtSlot(config, config.FULU_FORK_EPOCH * SLOTS_PER_EPOCH, opts.genesisTime)
124
+ : Infinity;
125
+ this.gloasForkTimestamp =
126
+ opts.genesisTime && config
127
+ ? computeTimeAtSlot(config, config.GLOAS_FORK_EPOCH * SLOTS_PER_EPOCH, opts.genesisTime)
128
+ : Infinity;
129
+
103
130
  this.handlers = {
104
131
  engine_newPayloadV1: this.notifyNewPayload.bind(this),
105
132
  engine_newPayloadV2: this.notifyNewPayload.bind(this),
@@ -448,11 +475,11 @@ export class ExecutionEngineMockBackend implements JsonRpcBackend {
448
475
  }
449
476
 
450
477
  private timestampToFork(timestamp: number): ForkPostBellatrix {
451
- if (timestamp >= (this.opts.gloasForkTimestamp ?? Infinity)) return ForkName.gloas;
452
- if (timestamp >= (this.opts.fuluForkTimestamp ?? Infinity)) return ForkName.fulu;
453
- if (timestamp >= (this.opts.electraForkTimestamp ?? Infinity)) return ForkName.electra;
454
- if (timestamp >= (this.opts.denebForkTimestamp ?? Infinity)) return ForkName.deneb;
455
- if (timestamp >= (this.opts.capellaForkTimestamp ?? Infinity)) return ForkName.capella;
478
+ if (timestamp >= this.gloasForkTimestamp) return ForkName.gloas;
479
+ if (timestamp >= this.fuluForkTimestamp) return ForkName.fulu;
480
+ if (timestamp >= this.electraForkTimestamp) return ForkName.electra;
481
+ if (timestamp >= this.denebForkTimestamp) return ForkName.deneb;
482
+ if (timestamp >= this.capellaForkTimestamp) return ForkName.capella;
456
483
  return ForkName.bellatrix;
457
484
  }
458
485
  }
package/src/index.ts CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  export type {RestApiServerMetrics, RestApiServerModules, RestApiServerOpts} from "./api/rest/base.js";
4
4
  export {RestApiServer} from "./api/rest/base.js";
5
- export {checkAndPersistAnchorState, initStateFromDb} from "./chain/index.js";
5
+ export {checkAndPersistAnchorState} from "./chain/index.js";
6
6
  export {DbCPStateDatastore} from "./chain/stateCache/datastore/db.js";
7
7
  export {FileCPStateDatastore} from "./chain/stateCache/datastore/file.js";
8
8
  export {BeaconDb, type IBeaconDb} from "./db/index.js";
@@ -212,6 +212,31 @@ export function createLodestarMetrics(
212
212
  }),
213
213
  },
214
214
 
215
+ unfinalizedBlockWritesQueue: {
216
+ length: register.gauge({
217
+ name: "lodestar_unfinalized_block_writes_queue_length",
218
+ help: "Count of total unfinalized block writes queue length",
219
+ }),
220
+ droppedJobs: register.gauge({
221
+ name: "lodestar_unfinalized_block_writes_queue_dropped_jobs_total",
222
+ help: "Count of total unfinalized block writes queue dropped jobs",
223
+ }),
224
+ jobTime: register.histogram({
225
+ name: "lodestar_unfinalized_block_writes_queue_job_time_seconds",
226
+ help: "Time to process unfinalized block writes queue job in seconds",
227
+ buckets: [0.01, 0.1, 1, 4, 12],
228
+ }),
229
+ jobWaitTime: register.histogram({
230
+ name: "lodestar_unfinalized_block_writes_queue_job_wait_time_seconds",
231
+ help: "Time from job added to the unfinalized block writes queue to starting in seconds",
232
+ buckets: [0.01, 0.1, 1, 4, 12],
233
+ }),
234
+ concurrency: register.gauge({
235
+ name: "lodestar_unfinalized_block_writes_queue_concurrency",
236
+ help: "Current concurrency of unfinalized block writes queue",
237
+ }),
238
+ },
239
+
215
240
  engineHttpProcessorQueue: {
216
241
  length: register.gauge({
217
242
  name: "lodestar_engine_http_processor_queue_length",
@@ -1308,33 +1333,19 @@ export function createLodestarMetrics(
1308
1333
  name: "lodestar_shuffling_cache_miss_count",
1309
1334
  help: "Count of shuffling cache miss",
1310
1335
  }),
1311
- shufflingBuiltMultipleTimes: register.gauge({
1312
- name: "lodestar_shuffling_cache_recalculated_shuffling_count",
1313
- help: "Count of shuffling that were build multiple times",
1314
- }),
1315
- shufflingPromiseNotResolvedAndThrownAway: register.gauge({
1316
- name: "lodestar_shuffling_cache_promise_not_resolved_and_thrown_away_count",
1317
- help: "Count of shuffling cache promises that were discarded and the shuffling was built synchronously",
1336
+ shufflingSetMultipleTimes: register.gauge({
1337
+ name: "lodestar_shuffling_cache_set_multiple_times_count",
1338
+ help: "Count of shuffling that were set multiple times",
1318
1339
  }),
1319
1340
  shufflingPromiseNotResolved: register.gauge({
1320
1341
  name: "lodestar_shuffling_cache_promise_not_resolved_count",
1321
1342
  help: "Count of shuffling cache promises that were requested before the promise was resolved",
1322
1343
  }),
1323
- nextShufflingNotOnEpochCache: register.gauge({
1324
- name: "lodestar_shuffling_cache_next_shuffling_not_on_epoch_cache",
1325
- help: "The next shuffling was not on the epoch cache before the epoch transition",
1326
- }),
1327
1344
  shufflingPromiseResolutionTime: register.histogram({
1328
1345
  name: "lodestar_shuffling_cache_promise_resolution_time_seconds",
1329
1346
  help: "Time from promise insertion until promise resolution when shuffling was ready in seconds",
1330
1347
  buckets: [0.5, 1, 1.5, 2],
1331
1348
  }),
1332
- shufflingCalculationTime: register.histogram<{source: "build" | "getSync"}>({
1333
- name: "lodestar_shuffling_cache_shuffling_calculation_time_seconds",
1334
- help: "Run time of shuffling calculation",
1335
- buckets: [0.5, 0.75, 1, 1.25, 1.5],
1336
- labelNames: ["source"],
1337
- }),
1338
1349
  },
1339
1350
 
1340
1351
  seenCache: {
@@ -436,14 +436,11 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
436
436
  blsVerifyOnMainThread: true,
437
437
  // to track block process steps
438
438
  seenTimestampSec,
439
- // gossip block is validated, we want to process it asap
440
- eagerPersistBlock: true,
441
439
  })
442
440
  .then(() => {
443
441
  // Returns the delay between the start of `block.slot` and `current time`
444
442
  const delaySec = chain.clock.secFromSlot(slot);
445
443
  metrics?.gossipBlock.elapsedTimeTillProcessed.observe(delaySec);
446
- chain.seenBlockInputCache.prune(blockInput.blockRootHex);
447
444
  })
448
445
  .catch((e) => {
449
446
  // Adjust verbosity based on error type
@@ -4,7 +4,6 @@ import {GENESIS_SLOT, isForkPostDeneb, isForkPostFulu} from "@lodestar/params";
4
4
  import {RespStatus, ResponseError, ResponseOutgoing} from "@lodestar/reqresp";
5
5
  import {computeEpochAtSlot} from "@lodestar/state-transition";
6
6
  import {deneb, phase0} from "@lodestar/types";
7
- import {fromHex} from "@lodestar/utils";
8
7
  import {IBeaconChain} from "../../../chain/index.js";
9
8
  import {IBeaconDb} from "../../../db/index.js";
10
9
  import {prettyPrintPeerId} from "../../util.ts";
@@ -22,7 +21,6 @@ export async function* onBeaconBlocksByRange(
22
21
  const endSlot = startSlot + count;
23
22
 
24
23
  const finalized = db.blockArchive;
25
- const unfinalized = db.block;
26
24
  // in the case of initializing from a non-finalized state, we don't have the finalized block so this api does not work
27
25
  // chain.forkChoice.getFinalizeBlock().slot
28
26
  const finalizedSlot = chain.forkChoice.getFinalizedCheckpointSlot();
@@ -65,7 +63,7 @@ export async function* onBeaconBlocksByRange(
65
63
  // re-org there's no need to abort the request
66
64
  // Spec: https://github.com/ethereum/consensus-specs/blob/a1e46d1ae47dd9d097725801575b46907c12a1f8/specs/eip4844/p2p-interface.md#blobssidecarsbyrange-v1
67
65
 
68
- const blockBytes = await unfinalized.getBinary(fromHex(block.blockRoot));
66
+ const blockBytes = await chain.getSerializedBlockByRoot(block.blockRoot);
69
67
  if (!blockBytes) {
70
68
  throw new ResponseError(
71
69
  RespStatus.SERVER_ERROR,
@@ -74,7 +72,7 @@ export async function* onBeaconBlocksByRange(
74
72
  }
75
73
 
76
74
  yield {
77
- data: blockBytes,
75
+ data: blockBytes.block,
78
76
  boundary: chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(block.slot)),
79
77
  };
80
78
  }
@@ -1,48 +1,21 @@
1
1
  import {ResponseOutgoing} from "@lodestar/reqresp";
2
2
  import {computeEpochAtSlot} from "@lodestar/state-transition";
3
- import {Slot} from "@lodestar/types";
4
3
  import {toRootHex} from "@lodestar/utils";
5
4
  import {IBeaconChain} from "../../../chain/index.js";
6
- import {IBeaconDb} from "../../../db/index.js";
7
- import {getSlotFromSignedBeaconBlockSerialized} from "../../../util/sszBytes.js";
8
5
  import {BeaconBlocksByRootRequest} from "../../../util/types.js";
9
6
 
10
7
  export async function* onBeaconBlocksByRoot(
11
8
  requestBody: BeaconBlocksByRootRequest,
12
- chain: IBeaconChain,
13
- db: IBeaconDb
9
+ chain: IBeaconChain
14
10
  ): AsyncIterable<ResponseOutgoing> {
15
11
  for (const blockRoot of requestBody) {
16
12
  const root = blockRoot;
17
- const summary = chain.forkChoice.getBlock(root);
18
- let blockBytes: Uint8Array | null = null;
19
-
20
- // finalized block has summary in forkchoice but it stays in blockArchive db
21
- if (summary) {
22
- blockBytes = await db.block.getBinary(root);
23
- }
24
-
25
- let slot: Slot | undefined = undefined;
26
- if (!blockBytes) {
27
- const blockEntry = await db.blockArchive.getBinaryEntryByRoot(root);
28
- if (blockEntry) {
29
- slot = blockEntry.key;
30
- blockBytes = blockEntry.value;
31
- }
32
- }
33
-
34
- if (blockBytes) {
35
- if (slot === undefined) {
36
- const slotFromBytes = getSlotFromSignedBeaconBlockSerialized(blockBytes);
37
- if (slotFromBytes === null) {
38
- throw Error(`Invalid block bytes for block root ${toRootHex(root)}`);
39
- }
40
- slot = slotFromBytes;
41
- }
13
+ const block = await chain.getSerializedBlockByRoot(toRootHex(root));
42
14
 
15
+ if (block) {
43
16
  yield {
44
- data: blockBytes,
45
- boundary: chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(slot)),
17
+ data: block.block,
18
+ boundary: chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(block.slot)),
46
19
  };
47
20
  }
48
21
  }
@@ -2,16 +2,13 @@ import {BLOB_SIDECAR_FIXED_SIZE} from "@lodestar/params";
2
2
  import {RespStatus, ResponseError, ResponseOutgoing} from "@lodestar/reqresp";
3
3
  import {computeEpochAtSlot} from "@lodestar/state-transition";
4
4
  import {RootHex} from "@lodestar/types";
5
- import {fromHex, toRootHex} from "@lodestar/utils";
5
+ import {toRootHex} from "@lodestar/utils";
6
6
  import {IBeaconChain} from "../../../chain/index.js";
7
- import {IBeaconDb} from "../../../db/index.js";
8
- import {BLOB_SIDECARS_IN_WRAPPER_INDEX} from "../../../db/repositories/blobSidecars.js";
9
7
  import {BlobSidecarsByRootRequest} from "../../../util/types.js";
10
8
 
11
9
  export async function* onBlobSidecarsByRoot(
12
10
  requestBody: BlobSidecarsByRootRequest,
13
- chain: IBeaconChain,
14
- db: IBeaconDb
11
+ chain: IBeaconChain
15
12
  ): AsyncIterable<ResponseOutgoing> {
16
13
  const finalizedSlot = chain.forkChoice.getFinalizedBlock().slot;
17
14
 
@@ -34,14 +31,13 @@ export async function* onBlobSidecarsByRoot(
34
31
 
35
32
  // Check if we need to load sidecars for a new block root
36
33
  if (lastFetchedSideCars === null || lastFetchedSideCars.blockRoot !== blockRootHex) {
37
- const blobSideCarsBytesWrapped = await db.blobSidecars.getBinary(fromHex(block.blockRoot));
38
- if (!blobSideCarsBytesWrapped) {
34
+ const blobSidecarsBytes = await chain.getSerializedBlobSidecars(block.slot, blockRootHex);
35
+ if (!blobSidecarsBytes) {
39
36
  // Handle the same to onBeaconBlocksByRange
40
37
  throw new ResponseError(RespStatus.SERVER_ERROR, `No item for root ${block.blockRoot} slot ${block.slot}`);
41
38
  }
42
- const blobSideCarsBytes = blobSideCarsBytesWrapped.slice(BLOB_SIDECARS_IN_WRAPPER_INDEX);
43
39
 
44
- lastFetchedSideCars = {blockRoot: blockRootHex, bytes: blobSideCarsBytes};
40
+ lastFetchedSideCars = {blockRoot: blockRootHex, bytes: blobSidecarsBytes};
45
41
  }
46
42
 
47
43
  const blobSidecarBytes = lastFetchedSideCars.bytes.slice(
@@ -38,7 +38,6 @@ export async function* onDataColumnSidecarsByRange(
38
38
  }
39
39
 
40
40
  const finalized = db.dataColumnSidecarArchive;
41
- const unfinalized = db.dataColumnSidecar;
42
41
  const finalizedSlot = chain.forkChoice.getFinalizedBlock().slot;
43
42
 
44
43
  // Finalized range of columns
@@ -92,7 +91,11 @@ export async function* onDataColumnSidecarsByRange(
92
91
  // at the time of the start of the request. Spec is clear the chain of columns must be consistent, but on
93
92
  // re-org there's no need to abort the request
94
93
  // Spec: https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/specs/fulu/p2p-interface.md#L425-L429
95
- const dataColumnSidecars = await unfinalized.getManyBinary(fromHex(block.blockRoot), availableColumns);
94
+ const dataColumnSidecars = await chain.getSerializedDataColumnSidecars(
95
+ block.slot,
96
+ block.blockRoot,
97
+ availableColumns
98
+ );
96
99
 
97
100
  const unavailableColumnIndices: ColumnIndex[] = [];
98
101
  for (let i = 0; i < dataColumnSidecars.length; i++) {
@@ -61,11 +61,7 @@ export async function* onDataColumnSidecarsByRoot(
61
61
  continue;
62
62
  }
63
63
 
64
- const dataColumns = block
65
- ? // Non-finalized sidecars are stored by block root
66
- await db.dataColumnSidecar.getManyBinary(blockRoot, availableColumns)
67
- : // Finalized sidecars are archived and stored by slot
68
- await db.dataColumnSidecarArchive.getManyBinary(slot, availableColumns);
64
+ const dataColumns = await chain.getSerializedDataColumnSidecars(slot, blockRootHex, availableColumns);
69
65
 
70
66
  const unavailableColumnIndices: ColumnIndex[] = [];
71
67
  for (let i = 0; i < dataColumns.length; i++) {
@@ -42,12 +42,12 @@ export function getReqRespHandlers({db, chain}: {db: IBeaconDb; chain: IBeaconCh
42
42
  [ReqRespMethod.BeaconBlocksByRoot]: (req) => {
43
43
  const fork = chain.config.getForkName(chain.clock.currentSlot);
44
44
  const body = BeaconBlocksByRootRequestType(fork, chain.config).deserialize(req.data);
45
- return onBeaconBlocksByRoot(body, chain, db);
45
+ return onBeaconBlocksByRoot(body, chain);
46
46
  },
47
47
  [ReqRespMethod.BlobSidecarsByRoot]: (req) => {
48
48
  const fork = chain.config.getForkName(chain.clock.currentSlot);
49
49
  const body = BlobSidecarsByRootRequestType(fork, chain.config).deserialize(req.data);
50
- return onBlobSidecarsByRoot(body, chain, db);
50
+ return onBlobSidecarsByRoot(body, chain);
51
51
  },
52
52
  [ReqRespMethod.BlobSidecarsByRange]: (req) => {
53
53
  const body = ssz.deneb.BlobSidecarsByRangeRequest.deserialize(req.data);
@@ -55,7 +55,7 @@ export async function handleColumnSidecarUnavailability({
55
55
  const blobsCount = getBlobKzgCommitmentsCountFromSignedBeaconBlockSerialized(chain.config, blockBytes);
56
56
 
57
57
  // There are zero blobs for that column index, so we can safely return without any error
58
- if (blobsCount > 0) return;
58
+ if (blobsCount === 0) return;
59
59
 
60
60
  // There are blobs for that column index so we should have synced for it
61
61
  // We need to inform to peers that we don't have that expected data
@@ -6,9 +6,10 @@ import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
6
6
  import {BeaconApiMethods} from "@lodestar/api/beacon/server";
7
7
  import {BeaconConfig} from "@lodestar/config";
8
8
  import type {LoggerNode} from "@lodestar/logger/node";
9
- import {CachedBeaconStateAllForks, Index2PubkeyCache} from "@lodestar/state-transition";
9
+ import {ZERO_HASH_HEX} from "@lodestar/params";
10
+ import {CachedBeaconStateAllForks, Index2PubkeyCache, isExecutionCachedStateType} from "@lodestar/state-transition";
10
11
  import {phase0} from "@lodestar/types";
11
- import {sleep} from "@lodestar/utils";
12
+ import {sleep, toRootHex} from "@lodestar/utils";
12
13
  import {ProcessShutdownCallback} from "@lodestar/validator";
13
14
  import {BeaconRestApiServer, getApi} from "../api/index.js";
14
15
  import {BeaconChain, IBeaconChain, initBeaconMetrics} from "../chain/index.js";
@@ -221,6 +222,20 @@ export class BeaconNode {
221
222
  )
222
223
  : null;
223
224
 
225
+ let executionEngineOpts = opts.executionEngine;
226
+ if (opts.executionEngine.mode === "mock") {
227
+ const eth1BlockHash = isExecutionCachedStateType(anchorState)
228
+ ? toRootHex(anchorState.latestExecutionPayloadHeader.blockHash)
229
+ : undefined;
230
+ executionEngineOpts = {
231
+ ...opts.executionEngine,
232
+ genesisBlockHash: ZERO_HASH_HEX,
233
+ eth1BlockHash,
234
+ genesisTime: anchorState.genesisTime,
235
+ config,
236
+ };
237
+ }
238
+
224
239
  const chain = new BeaconChain(opts.chain, {
225
240
  privateKey,
226
241
  config,
@@ -236,7 +251,7 @@ export class BeaconNode {
236
251
  validatorMonitor,
237
252
  anchorState,
238
253
  isAnchorStateFinalized,
239
- executionEngine: initializeExecutionEngine(opts.executionEngine, {
254
+ executionEngine: initializeExecutionEngine(executionEngineOpts, {
240
255
  metrics,
241
256
  signal,
242
257
  logger: logger.child({module: LoggerModule.execution}),
@@ -585,7 +585,6 @@ export class SyncChain {
585
585
 
586
586
  if (!res.err) {
587
587
  batch.processingSuccess();
588
- this.pruneBlockInputs(batch.getBlocks());
589
588
 
590
589
  // If the processed batch is not empty, validate previous AwaitingValidation blocks.
591
590
  if (blocks.length > 0) {