@lodestar/beacon-node 1.50.0-dev.55c1d0c0d1 → 1.50.0-dev.586c4d5d51

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 (208) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +6 -1
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/beacon/pool/index.js +4 -4
  5. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  6. package/lib/chain/archiveStore/archiveStore.d.ts +1 -0
  7. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  8. package/lib/chain/archiveStore/archiveStore.js +7 -3
  9. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  10. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts +2 -2
  11. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
  12. package/lib/chain/archiveStore/historicalState/getHistoricalState.js +5 -7
  13. package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
  14. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -1
  15. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
  16. package/lib/chain/archiveStore/historicalState/types.d.ts +2 -2
  17. package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
  18. package/lib/chain/archiveStore/historicalState/worker.js +1 -1
  19. package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
  20. package/lib/chain/archiveStore/interface.d.ts +1 -1
  21. package/lib/chain/archiveStore/interface.d.ts.map +1 -1
  22. package/lib/chain/archiveStore/utils/pruneHistory.d.ts +4 -1
  23. package/lib/chain/archiveStore/utils/pruneHistory.d.ts.map +1 -1
  24. package/lib/chain/archiveStore/utils/pruneHistory.js +4 -3
  25. package/lib/chain/archiveStore/utils/pruneHistory.js.map +1 -1
  26. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  27. package/lib/chain/blocks/importBlock.js +4 -0
  28. package/lib/chain/blocks/importBlock.js.map +1 -1
  29. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +2 -1
  30. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
  31. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  32. package/lib/chain/blocks/verifyBlock.js +1 -1
  33. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  34. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts +2 -1
  35. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts.map +1 -1
  36. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js +5 -4
  37. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js.map +1 -1
  38. package/lib/chain/chain.d.ts +5 -4
  39. package/lib/chain/chain.d.ts.map +1 -1
  40. package/lib/chain/chain.js +32 -16
  41. package/lib/chain/chain.js.map +1 -1
  42. package/lib/chain/errors/envelopeReconstructionError.d.ts +5 -0
  43. package/lib/chain/errors/envelopeReconstructionError.d.ts.map +1 -1
  44. package/lib/chain/errors/envelopeReconstructionError.js +2 -0
  45. package/lib/chain/errors/envelopeReconstructionError.js.map +1 -1
  46. package/lib/chain/errors/gossipValidation.d.ts +3 -1
  47. package/lib/chain/errors/gossipValidation.d.ts.map +1 -1
  48. package/lib/chain/errors/gossipValidation.js +2 -0
  49. package/lib/chain/errors/gossipValidation.js.map +1 -1
  50. package/lib/chain/initState.d.ts +2 -9
  51. package/lib/chain/initState.d.ts.map +1 -1
  52. package/lib/chain/initState.js +5 -38
  53. package/lib/chain/initState.js.map +1 -1
  54. package/lib/chain/interface.d.ts +2 -2
  55. package/lib/chain/interface.d.ts.map +1 -1
  56. package/lib/chain/opPools/opPool.d.ts +5 -4
  57. package/lib/chain/opPools/opPool.d.ts.map +1 -1
  58. package/lib/chain/opPools/opPool.js +62 -18
  59. package/lib/chain/opPools/opPool.js.map +1 -1
  60. package/lib/chain/opPools/utils.d.ts +4 -1
  61. package/lib/chain/opPools/utils.d.ts.map +1 -1
  62. package/lib/chain/opPools/utils.js +11 -1
  63. package/lib/chain/opPools/utils.js.map +1 -1
  64. package/lib/chain/options.d.ts +1 -1
  65. package/lib/chain/options.d.ts.map +1 -1
  66. package/lib/chain/options.js +1 -1
  67. package/lib/chain/options.js.map +1 -1
  68. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  69. package/lib/chain/prepareNextSlot.js +5 -2
  70. package/lib/chain/prepareNextSlot.js.map +1 -1
  71. package/lib/chain/produceBlock/computeNewStateRoot.js +1 -1
  72. package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
  73. package/lib/chain/produceBlock/produceBlockBody.d.ts +3 -1
  74. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  75. package/lib/chain/produceBlock/produceBlockBody.js +6 -2
  76. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  77. package/lib/chain/regen/regen.d.ts +2 -0
  78. package/lib/chain/regen/regen.d.ts.map +1 -1
  79. package/lib/chain/regen/regen.js +10 -4
  80. package/lib/chain/regen/regen.js.map +1 -1
  81. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +9 -2
  82. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
  83. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +23 -13
  84. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
  85. package/lib/chain/validation/attesterSlashing.d.ts +4 -4
  86. package/lib/chain/validation/attesterSlashing.d.ts.map +1 -1
  87. package/lib/chain/validation/attesterSlashing.js +3 -0
  88. package/lib/chain/validation/attesterSlashing.js.map +1 -1
  89. package/lib/chain/validation/proposerSlashing.d.ts +3 -3
  90. package/lib/chain/validation/proposerSlashing.d.ts.map +1 -1
  91. package/lib/chain/validation/proposerSlashing.js +3 -0
  92. package/lib/chain/validation/proposerSlashing.js.map +1 -1
  93. package/lib/chain/validatorMonitor.d.ts +5 -1
  94. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  95. package/lib/chain/validatorMonitor.js +64 -54
  96. package/lib/chain/validatorMonitor.js.map +1 -1
  97. package/lib/db/beacon.d.ts.map +1 -1
  98. package/lib/db/beacon.js +2 -0
  99. package/lib/db/beacon.js.map +1 -1
  100. package/lib/db/repositories/proposerSlashing.d.ts +1 -0
  101. package/lib/db/repositories/proposerSlashing.d.ts.map +1 -1
  102. package/lib/db/repositories/proposerSlashing.js +5 -1
  103. package/lib/db/repositories/proposerSlashing.js.map +1 -1
  104. package/lib/execution/engine/disabled.d.ts +0 -2
  105. package/lib/execution/engine/disabled.d.ts.map +1 -1
  106. package/lib/execution/engine/disabled.js +0 -6
  107. package/lib/execution/engine/disabled.js.map +1 -1
  108. package/lib/execution/engine/http.d.ts +1 -3
  109. package/lib/execution/engine/http.d.ts.map +1 -1
  110. package/lib/execution/engine/http.js +2 -17
  111. package/lib/execution/engine/http.js.map +1 -1
  112. package/lib/execution/engine/interface.d.ts +2 -4
  113. package/lib/execution/engine/interface.d.ts.map +1 -1
  114. package/lib/execution/engine/mock.d.ts +0 -2
  115. package/lib/execution/engine/mock.d.ts.map +1 -1
  116. package/lib/execution/engine/mock.js +0 -8
  117. package/lib/execution/engine/mock.js.map +1 -1
  118. package/lib/execution/engine/types.d.ts +0 -8
  119. package/lib/execution/engine/types.d.ts.map +1 -1
  120. package/lib/execution/engine/types.js.map +1 -1
  121. package/lib/index.d.ts +1 -1
  122. package/lib/index.d.ts.map +1 -1
  123. package/lib/index.js +1 -1
  124. package/lib/index.js.map +1 -1
  125. package/lib/metrics/metrics.d.ts +7 -3
  126. package/lib/metrics/metrics.d.ts.map +1 -1
  127. package/lib/metrics/metrics.js +4 -4
  128. package/lib/metrics/metrics.js.map +1 -1
  129. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  130. package/lib/network/processor/gossipHandlers.js +7 -4
  131. package/lib/network/processor/gossipHandlers.js.map +1 -1
  132. package/lib/network/processor/gossipValidatorFn.d.ts +7 -3
  133. package/lib/network/processor/gossipValidatorFn.d.ts.map +1 -1
  134. package/lib/network/processor/gossipValidatorFn.js +7 -3
  135. package/lib/network/processor/gossipValidatorFn.js.map +1 -1
  136. package/lib/network/processor/index.d.ts +9 -0
  137. package/lib/network/processor/index.d.ts.map +1 -1
  138. package/lib/network/processor/index.js +77 -10
  139. package/lib/network/processor/index.js.map +1 -1
  140. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.d.ts.map +1 -1
  141. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js +41 -26
  142. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js.map +1 -1
  143. package/lib/node/nodejs.d.ts.map +1 -1
  144. package/lib/node/nodejs.js +25 -3
  145. package/lib/node/nodejs.js.map +1 -1
  146. package/lib/sync/range/batch.d.ts +6 -0
  147. package/lib/sync/range/batch.d.ts.map +1 -1
  148. package/lib/sync/range/batch.js +10 -0
  149. package/lib/sync/range/batch.js.map +1 -1
  150. package/lib/sync/range/range.d.ts.map +1 -1
  151. package/lib/sync/range/range.js +50 -18
  152. package/lib/sync/range/range.js.map +1 -1
  153. package/lib/sync/unknownBlock.d.ts +9 -5
  154. package/lib/sync/unknownBlock.d.ts.map +1 -1
  155. package/lib/sync/unknownBlock.js +88 -46
  156. package/lib/sync/unknownBlock.js.map +1 -1
  157. package/lib/util/execution.d.ts +11 -11
  158. package/lib/util/execution.d.ts.map +1 -1
  159. package/lib/util/execution.js +6 -2
  160. package/lib/util/execution.js.map +1 -1
  161. package/package.json +16 -16
  162. package/src/api/impl/beacon/blocks/index.ts +7 -4
  163. package/src/api/impl/beacon/pool/index.ts +4 -4
  164. package/src/chain/archiveStore/archiveStore.ts +10 -4
  165. package/src/chain/archiveStore/historicalState/getHistoricalState.ts +5 -7
  166. package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +1 -1
  167. package/src/chain/archiveStore/historicalState/types.ts +2 -2
  168. package/src/chain/archiveStore/historicalState/worker.ts +1 -2
  169. package/src/chain/archiveStore/interface.ts +1 -1
  170. package/src/chain/archiveStore/utils/pruneHistory.ts +6 -4
  171. package/src/chain/blocks/importBlock.ts +4 -0
  172. package/src/chain/blocks/payloadEnvelopeInput/types.ts +2 -1
  173. package/src/chain/blocks/verifyBlock.ts +1 -0
  174. package/src/chain/blocks/verifyBlocksStateTransitionOnly.ts +6 -3
  175. package/src/chain/chain.ts +38 -19
  176. package/src/chain/errors/envelopeReconstructionError.ts +3 -0
  177. package/src/chain/errors/gossipValidation.ts +2 -0
  178. package/src/chain/initState.ts +8 -60
  179. package/src/chain/interface.ts +2 -2
  180. package/src/chain/opPools/opPool.ts +91 -18
  181. package/src/chain/opPools/utils.ts +31 -3
  182. package/src/chain/options.ts +2 -2
  183. package/src/chain/prepareNextSlot.ts +6 -3
  184. package/src/chain/produceBlock/computeNewStateRoot.ts +1 -1
  185. package/src/chain/produceBlock/produceBlockBody.ts +8 -1
  186. package/src/chain/regen/regen.ts +12 -4
  187. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +31 -13
  188. package/src/chain/validation/attesterSlashing.ts +7 -4
  189. package/src/chain/validation/proposerSlashing.ts +7 -4
  190. package/src/chain/validatorMonitor.ts +75 -57
  191. package/src/db/beacon.ts +2 -0
  192. package/src/db/repositories/proposerSlashing.ts +6 -1
  193. package/src/execution/engine/disabled.ts +0 -8
  194. package/src/execution/engine/http.ts +1 -30
  195. package/src/execution/engine/interface.ts +2 -6
  196. package/src/execution/engine/mock.ts +1 -19
  197. package/src/execution/engine/types.ts +0 -10
  198. package/src/index.ts +1 -1
  199. package/src/metrics/metrics.ts +21 -6
  200. package/src/network/processor/gossipHandlers.ts +7 -4
  201. package/src/network/processor/gossipValidatorFn.ts +13 -3
  202. package/src/network/processor/index.ts +89 -10
  203. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRoot.ts +42 -28
  204. package/src/node/nodejs.ts +31 -3
  205. package/src/sync/range/batch.ts +11 -0
  206. package/src/sync/range/range.ts +50 -18
  207. package/src/sync/unknownBlock.ts +99 -50
  208. package/src/util/execution.ts +17 -9
@@ -17,7 +17,7 @@ export async function getNearestState(
17
17
  slot: number,
18
18
  config: BeaconConfig,
19
19
  db: IBeaconDb,
20
- nativeStateView: boolean
20
+ nativeStateTransition: boolean
21
21
  ): Promise<IBeaconStateView> {
22
22
  const stateBytesArr = await db.stateArchive.binaries({limit: 1, lte: slot, reverse: true});
23
23
  if (!stateBytesArr.length) {
@@ -25,9 +25,7 @@ export async function getNearestState(
25
25
  }
26
26
 
27
27
  const stateBytes = stateBytesArr[0];
28
- return nativeStateView
29
- ? createBeaconStateViewForHistoricalRegen({useNative: true, stateBytes})
30
- : createBeaconStateViewForHistoricalRegen({useNative: false, config, stateBytes});
28
+ return createBeaconStateViewForHistoricalRegen({nativeStateTransition: nativeStateTransition, config, stateBytes});
31
29
  }
32
30
 
33
31
  /**
@@ -37,13 +35,13 @@ export async function getHistoricalState(
37
35
  slot: number,
38
36
  config: BeaconConfig,
39
37
  db: IBeaconDb,
40
- nativeStateView: boolean,
38
+ nativeStateTransition: boolean,
41
39
  metrics?: HistoricalStateRegenMetrics
42
40
  ): Promise<Uint8Array> {
43
41
  const regenTimer = metrics?.regenTime.startTimer();
44
42
 
45
43
  const loadStateTimer = metrics?.loadStateTime.startTimer();
46
- let state = await getNearestState(slot, config, db, nativeStateView).catch((e) => {
44
+ let state = await getNearestState(slot, config, db, nativeStateTransition).catch((e) => {
47
45
  metrics?.regenErrorCount.inc({reason: RegenErrorType.loadState});
48
46
  throw e;
49
47
  });
@@ -54,7 +52,7 @@ export async function getHistoricalState(
54
52
  for await (const block of db.blockArchive.valuesStream({gt: state.slot, lte: slot})) {
55
53
  try {
56
54
  state = state.stateTransition(
57
- block,
55
+ {block},
58
56
  {
59
57
  verifyProposer: false,
60
58
  verifySignatures: false,
@@ -36,7 +36,7 @@ export class HistoricalStateRegen implements HistoricalStateWorkerApi {
36
36
  dataColumnDir: modules.opts.dataColumnDir,
37
37
  metricsEnabled: Boolean(modules.metrics),
38
38
  loggerOpts: modules.logger.toOpts(),
39
- nativeStateView: modules.opts.nativeStateView,
39
+ nativeStateTransition: modules.opts.nativeStateTransition,
40
40
  };
41
41
 
42
42
  const worker = new Worker(path.join(WORKER_DIR, "worker.js"), {
@@ -8,7 +8,7 @@ export type HistoricalStateRegenInitModules = {
8
8
  genesisTime: number;
9
9
  dbLocation: string;
10
10
  dataColumnDir: string;
11
- nativeStateView: boolean;
11
+ nativeStateTransition: boolean;
12
12
  };
13
13
  config: BeaconConfig;
14
14
  logger: LoggerNode;
@@ -29,7 +29,7 @@ export type HistoricalStateWorkerData = {
29
29
  dataColumnDir: string;
30
30
  metricsEnabled: boolean;
31
31
  loggerOpts: LoggerNodeOpts;
32
- nativeStateView: boolean;
32
+ nativeStateTransition: boolean;
33
33
  };
34
34
 
35
35
  export type HistoricalStateWorkerApi = {
@@ -36,7 +36,6 @@ const abortController = new AbortController();
36
36
  const metricsRegister = workerData.metricsEnabled ? new RegistryMetricCreator() : null;
37
37
  let historicalStateRegenMetrics: HistoricalStateRegenMetrics | undefined;
38
38
  let queueMetrics: QueueMetrics | undefined;
39
-
40
39
  if (metricsRegister) {
41
40
  const closeMetrics = collectNodeJSMetrics(metricsRegister, "lodestar_historical_state_worker_");
42
41
  abortController.signal.addEventListener("abort", closeMetrics, {once: true});
@@ -65,7 +64,7 @@ const api: HistoricalStateWorkerApi = {
65
64
  historicalStateRegenMetrics?.regenRequestCount.inc();
66
65
 
67
66
  const stateBytes = await queue.push<Uint8Array>(() =>
68
- getHistoricalState(slot, config, db, workerData.nativeStateView, historicalStateRegenMetrics)
67
+ getHistoricalState(slot, config, db, workerData.nativeStateTransition, historicalStateRegenMetrics)
69
68
  );
70
69
  const result = Transfer(stateBytes, [stateBytes.buffer]) as unknown as Uint8Array;
71
70
 
@@ -25,7 +25,7 @@ export type ArchiveStoreOpts = StatesArchiveOpts & {
25
25
  archiveDataEpochs?: number;
26
26
  pruneHistory?: boolean;
27
27
  serveHistoricalState?: boolean;
28
- nativeStateView?: boolean;
28
+ nativeStateTransition?: boolean;
29
29
  };
30
30
 
31
31
  export type ProposalStats = {
@@ -11,8 +11,9 @@ export async function pruneHistory(
11
11
  logger: Logger,
12
12
  metrics: Metrics | null | undefined,
13
13
  finalizedEpoch: Epoch,
14
- currentEpoch: Epoch
15
- ): Promise<Slot> {
14
+ currentEpoch: Epoch,
15
+ statePruneFromSlot: Slot = 0
16
+ ): Promise<{blockCutoffSlot: Slot; stateCutoffSlot: Slot}> {
16
17
  const blockCutoffEpoch = Math.min(
17
18
  // set by config, with underflow protection
18
19
  Math.max(currentEpoch - config.MIN_EPOCHS_FOR_BLOCK_REQUESTS, 0),
@@ -28,6 +29,7 @@ export async function pruneHistory(
28
29
  currentEpoch,
29
30
  finalizedEpoch,
30
31
  blockCutoffEpoch,
32
+ statePruneFromSlot,
31
33
  stateCutoffSlot,
32
34
  });
33
35
 
@@ -35,7 +37,7 @@ export async function pruneHistory(
35
37
  const [blocks, envelopes, states] = await Promise.all([
36
38
  db.blockArchive.keys({gte: 0, lt: blockCutoffSlot}),
37
39
  db.executionPayloadEnvelopeArchive.keys({gte: 0, lt: blockCutoffSlot}),
38
- db.stateArchive.keys({gte: 0, lt: stateCutoffSlot}),
40
+ stateCutoffSlot > statePruneFromSlot ? db.stateArchive.keys({gte: statePruneFromSlot, lt: stateCutoffSlot}) : [],
39
41
  ]);
40
42
  step0?.();
41
43
 
@@ -64,5 +66,5 @@ export async function pruneHistory(
64
66
 
65
67
  metrics?.pruneHistory.pruneCount.inc();
66
68
 
67
- return blockCutoffSlot;
69
+ return {blockCutoffSlot, stateCutoffSlot};
68
70
  }
@@ -538,6 +538,10 @@ export async function importBlock(
538
538
  block: blockRootHex,
539
539
  slot: blockSlot,
540
540
  executionOptimistic: blockSummary != null && isOptimisticBlock(blockSummary),
541
+ ...(isGloasBeaconBlock(block.message) && {
542
+ blockHash: toRootHex(block.message.body.signedExecutionPayloadBid.message.blockHash),
543
+ builderIndex: block.message.body.signedExecutionPayloadBid.message.builderIndex,
544
+ }),
541
545
  });
542
546
  }
543
547
  if (this.emitter.listenerCount(routes.events.EventType.voluntaryExit)) {
@@ -22,8 +22,9 @@ export enum PayloadEnvelopeInputSource {
22
22
  * - finalized: below the finalized slot
23
23
  * - prune: explicit prune by root
24
24
  * - cap: insertion-order backstop cap (MAX_PAYLOAD_ENVELOPE_INPUT_CACHE_SIZE)
25
+ * - invalid: the cached envelope failed import with a definitive invalid verdict
25
26
  */
26
- export type PayloadEnvelopeInputPruneReason = "belowParent" | "finalized" | "remove" | "cap";
27
+ export type PayloadEnvelopeInputPruneReason = "belowParent" | "finalized" | "remove" | "cap" | "invalid";
27
28
 
28
29
  export type SourceMeta = {
29
30
  source: PayloadEnvelopeInputSource;
@@ -188,6 +188,7 @@ export async function verifyBlocksInEpoch(
188
188
  blockInputs,
189
189
  // hack availability for state transition eval as availability is separately determined
190
190
  blocks.map(() => DataAvailabilityStatus.Available),
191
+ this.serializedCache,
191
192
  this.logger,
192
193
  this.metrics,
193
194
  this.validatorMonitor,
@@ -7,6 +7,7 @@ import {
7
7
  import {ErrorAborted, Logger, byteArrayEquals} from "@lodestar/utils";
8
8
  import {Metrics} from "../../metrics/index.js";
9
9
  import {nextEventLoop} from "../../util/eventLoop.js";
10
+ import {SerializedCache} from "../../util/serializedCache.js";
10
11
  import {BlockError, BlockErrorCode} from "../errors/index.js";
11
12
  import {BlockProcessOpts} from "../options.js";
12
13
  import {ValidatorMonitor} from "../validatorMonitor.js";
@@ -25,6 +26,7 @@ export async function verifyBlocksStateTransitionOnly(
25
26
  preState0: IBeaconStateView,
26
27
  blocks: IBlockInput[],
27
28
  dataAvailabilityStatuses: DataAvailabilityStatus[],
29
+ serializedCache: SerializedCache,
28
30
  logger: Logger,
29
31
  metrics: Metrics | null,
30
32
  validatorMonitor: ValidatorMonitor | null,
@@ -37,7 +39,8 @@ export async function verifyBlocksStateTransitionOnly(
37
39
 
38
40
  for (let i = 0; i < blocks.length; i++) {
39
41
  const {validProposerSignature, validSignatures} = opts;
40
- const block = blocks[i].getBlock();
42
+ const blockInput = blocks[i];
43
+ const block = blockInput.getBlock();
41
44
  const preState = i === 0 ? preState0 : postStates[i - 1];
42
45
  const dataAvailabilityStatus = dataAvailabilityStatuses[i];
43
46
 
@@ -47,7 +50,7 @@ export async function verifyBlocksStateTransitionOnly(
47
50
  let postState: IBeaconStateView;
48
51
  try {
49
52
  postState = preState.stateTransition(
50
- block,
53
+ {block, ssz: serializedCache.get(block)},
51
54
  {
52
55
  // NOTE: Assume valid for now while sending payload to execution engine in parallel
53
56
  // Latter verifyBlocksInEpoch() will make sure that payload is indeed valid
@@ -60,7 +63,7 @@ export async function verifyBlocksStateTransitionOnly(
60
63
  verifySignatures: !useBlsBatchVerify && !validSignatures,
61
64
  dontTransferCache: false,
62
65
  },
63
- {metrics, validatorMonitor}
66
+ {metrics: metrics?.stateTransition, validatorMonitor}
64
67
  );
65
68
  } catch (e) {
66
69
  throw new BlockError(block, {
@@ -71,7 +71,7 @@ import {BufferPool} from "../util/bufferPool.js";
71
71
  import {Clock, ClockEvent, IClock} from "../util/clock.js";
72
72
  import {CustodyConfig, getValidatorsCustodyRequirement} from "../util/dataColumns.js";
73
73
  import {callInNextEventLoop} from "../util/eventLoop.js";
74
- import {ReconstructMismatchPolicy, isRebuildMiss, reconstructExecutionPayloadEnvelopes} from "../util/execution.js";
74
+ import {ReconstructMissPolicy, isRebuildMiss, reconstructExecutionPayloadEnvelopes} from "../util/execution.js";
75
75
  import {ensureDir, writeIfNotExist} from "../util/file.js";
76
76
  import {isOptimisticBlock} from "../util/forkChoice.js";
77
77
  import {JobItemQueue} from "../util/queue/itemQueue.js";
@@ -432,6 +432,7 @@ export class BeaconChain implements IBeaconChain {
432
432
  blockStateCache,
433
433
  checkpointStateCache,
434
434
  seenBlockInputCache: this.seenBlockInputCache,
435
+ serializedCache: this.serializedCache,
435
436
  db,
436
437
  metrics,
437
438
  validatorMonitor,
@@ -611,7 +612,7 @@ export class BeaconChain implements IBeaconChain {
611
612
  /** Populate in-memory caches with persisted data. Call at least once on startup */
612
613
  async loadFromDisk(): Promise<void> {
613
614
  await this.regen.init();
614
- await this.opPool.fromPersisted(this.db);
615
+ await this.opPool.fromPersisted(this.db, this.getHeadState(), this.bls, this.clock.currentSlot);
615
616
  }
616
617
 
617
618
  /** Persist in-memory data to the DB. Call at least once before stopping the process */
@@ -702,6 +703,26 @@ export class BeaconChain implements IBeaconChain {
702
703
  stateRoot: RootHex,
703
704
  opts?: StateGetOpts
704
705
  ): Promise<{state: IBeaconStateView | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null> {
706
+ const finalizedBlock = this.forkChoice.getFinalizedBlock();
707
+ const finalizedCheckpoint = this.forkChoice.getFinalizedCheckpoint();
708
+ // Checkpoint state only equals the block post-state if the block is at the epoch start slot
709
+ if (
710
+ finalizedBlock.stateRoot === stateRoot &&
711
+ finalizedBlock.slot === computeStartSlotAtEpoch(finalizedCheckpoint.epoch)
712
+ ) {
713
+ const state = this.regen.getCheckpointStateSync({
714
+ epoch: finalizedCheckpoint.epoch,
715
+ rootHex: finalizedCheckpoint.rootHex,
716
+ });
717
+ if (state) {
718
+ return {
719
+ state,
720
+ executionOptimistic: isOptimisticBlock(finalizedBlock),
721
+ finalized: finalizedCheckpoint.epoch !== GENESIS_EPOCH,
722
+ };
723
+ }
724
+ }
725
+
705
726
  if (opts?.allowRegen) {
706
727
  const state = await this.regen.getState(stateRoot, RegenCaller.restApi);
707
728
  const block = this.forkChoice.getBlockDefaultStatus(
@@ -934,12 +955,13 @@ export class BeaconChain implements IBeaconChain {
934
955
 
935
956
  /**
936
957
  * Batch variant: archived header envelopes are rebuilt 32 per EL round-trip. Aligned with `requests`.
937
- * A body root mismatch is a local inconsistency: `"throw"` surfaces it, `"omit"` logs it and
938
- * returns null for that entry, for peer-facing paths where the spec allows omission.
958
+ * An archived envelope that cannot be rebuilt (EL-unavailable body or body root mismatch) is not the
959
+ * same as an unknown one: `"throw"` surfaces it, `"omit"` returns null for that entry, for
960
+ * peer-facing paths where the spec allows omission.
939
961
  */
940
962
  async getSerializedExecutionPayloadEnvelopes(
941
963
  requests: {blockSlot: Slot; blockRootHex: RootHex}[],
942
- onMismatch: ReconstructMismatchPolicy = "throw"
964
+ onMiss: ReconstructMissPolicy = "throw"
943
965
  ): Promise<(Uint8Array | null)[]> {
944
966
  const out: (Uint8Array | null)[] = new Array(requests.length).fill(null);
945
967
  const headerEnvelopes: gloas.SignedExecutionPayloadHeaderEnvelope[] = [];
@@ -978,14 +1000,14 @@ export class BeaconChain implements IBeaconChain {
978
1000
  for (let j = 0; j < rebuilt.length; j++) {
979
1001
  const result = rebuilt[j];
980
1002
  if (isRebuildMiss(result)) {
981
- if (result.reason === "mismatch") {
982
- if (onMismatch === "throw") throw result.error;
983
- this.logger.debug(
984
- "Archived envelope failed body root check against EL bodies",
985
- {slot: result.slot},
986
- result.error
987
- );
988
- }
1003
+ if (onMiss === "throw") throw result.error;
1004
+ this.logger.debug(
1005
+ result.reason === "mismatch"
1006
+ ? "Archived envelope failed body root check against EL bodies"
1007
+ : "EL cannot serve bodies for archived envelope, omitting",
1008
+ {slot: result.slot},
1009
+ result.error
1010
+ );
989
1011
  continue;
990
1012
  }
991
1013
  out[headerEnvelopeIdxs[j]] = ssz.gloas.SignedExecutionPayloadEnvelope.serialize(result);
@@ -1016,10 +1038,7 @@ export class BeaconChain implements IBeaconChain {
1016
1038
  const [result] = await reconstructExecutionPayloadEnvelopes(this.executionEngine, this.metrics, [
1017
1039
  archived.headerEnvelope,
1018
1040
  ]);
1019
- if (isRebuildMiss(result)) {
1020
- if (result.reason === "mismatch") throw result.error;
1021
- return null;
1022
- }
1041
+ if (isRebuildMiss(result)) throw result.error;
1023
1042
  return result;
1024
1043
  }
1025
1044
 
@@ -1329,13 +1348,13 @@ export class BeaconChain implements IBeaconChain {
1329
1348
  };
1330
1349
 
1331
1350
  try {
1332
- await validateApiProposerSlashing(this, proposerSlashing);
1351
+ const verifiedDomain = await validateApiProposerSlashing(this, proposerSlashing);
1352
+ this.opPool.insertProposerSlashing(proposerSlashing, verifiedDomain);
1333
1353
  } catch (e) {
1334
1354
  this.logger.debug("Produced proposer slashing is not valid", {slot: blockSlot, proposerIndex}, e as Error);
1335
1355
  return;
1336
1356
  }
1337
1357
 
1338
- this.opPool.insertProposerSlashing(proposerSlashing);
1339
1358
  this.emitter.emit(routes.events.EventType.proposerSlashing, proposerSlashing);
1340
1359
  this.emitter.emit(ChainEvent.publishProposerSlashing, proposerSlashing);
1341
1360
  this.metrics?.opPool.proposerSlashingsProduced.inc();
@@ -4,6 +4,8 @@ import {LodestarError} from "@lodestar/utils";
4
4
  export enum EnvelopeReconstructionErrorCode {
5
5
  /** The EL failed to answer engine_getPayloadBodiesByHashV2 (transport / EL down). Transient. */
6
6
  ENGINE_UNAVAILABLE = "ENVELOPE_RECONSTRUCTION_ERROR_ENGINE_UNAVAILABLE",
7
+ /** The EL does not have the block or its block access list (pruned, or not yet re-indexed after a restart). May recover. */
8
+ BODY_UNAVAILABLE = "ENVELOPE_RECONSTRUCTION_ERROR_BODY_UNAVAILABLE",
7
9
  /** A body returned by the EL does not hash to the root stored in the header envelope. Local DB/EL inconsistency. */
8
10
  BODY_ROOT_MISMATCH = "ENVELOPE_RECONSTRUCTION_ERROR_BODY_ROOT_MISMATCH",
9
11
  /** A by-range stream stopped short at a slot that cannot be served; the response so far is still valid */
@@ -12,6 +14,7 @@ export enum EnvelopeReconstructionErrorCode {
12
14
 
13
15
  export type EnvelopeReconstructionErrorType =
14
16
  | {code: EnvelopeReconstructionErrorCode.ENGINE_UNAVAILABLE}
17
+ | {code: EnvelopeReconstructionErrorCode.BODY_UNAVAILABLE; slot: Slot}
15
18
  | {
16
19
  code: EnvelopeReconstructionErrorCode.BODY_ROOT_MISMATCH;
17
20
  slot: Slot;
@@ -9,6 +9,8 @@ export enum GossipErrorCode {
9
9
  INVALID_SERIALIZED_BYTES_ERROR_CODE = "GOSSIP_ERROR_INVALID_SERIALIZED_BYTES",
10
10
  PAST_SLOT = "GOSSIP_ERROR_PAST_SLOT",
11
11
  FUTURE_SLOT = "GOSSIP_ERROR_FUTURE_SLOT",
12
+ FATAL_PEER = "GOSSIP_ERROR_FATAL_PEER",
13
+ INVALID_SLOT = "GOSSIP_ERROR_INVALID_SLOT",
12
14
  }
13
15
 
14
16
  export class GossipActionError<T extends {code: string}> extends LodestarError<T> {
@@ -1,14 +1,8 @@
1
1
  import {ChainForkConfig} from "@lodestar/config";
2
2
  import {ForkPostGloas, ForkSeq, ZERO_HASH} from "@lodestar/params";
3
- import {
4
- BeaconStateAllForks,
5
- BeaconStateGloas,
6
- IBeaconStateView,
7
- computeEpochAtSlot,
8
- computeStartSlotAtEpoch,
9
- } from "@lodestar/state-transition";
3
+ import {BeaconStateAllForks, IBeaconStateView, computeEpochAtSlot, isStatePostGloas} from "@lodestar/state-transition";
10
4
  import {SignedBeaconBlock, ssz} from "@lodestar/types";
11
- import {Logger, byteArrayEquals, toHex, toRootHex} from "@lodestar/utils";
5
+ import {LodestarError, Logger, byteArrayEquals, toRootHex} from "@lodestar/utils";
12
6
  import {GENESIS_SLOT} from "../constants/index.js";
13
7
  import {IBeaconDb} from "../db/index.js";
14
8
  import {Metrics} from "../metrics/index.js";
@@ -17,7 +11,7 @@ import {getStateTypeFromBytes} from "../util/multifork.js";
17
11
  export async function persistAnchorState(
18
12
  config: ChainForkConfig,
19
13
  db: IBeaconDb,
20
- anchorState: BeaconStateAllForks,
14
+ anchorState: IBeaconStateView,
21
15
  anchorStateBytes: Uint8Array
22
16
  ): Promise<void> {
23
17
  if (anchorState.slot === GENESIS_SLOT) {
@@ -33,7 +27,8 @@ export async function persistAnchorState(
33
27
  const latestBlockRoot = ssz.phase0.BeaconBlockHeader.hashTreeRoot(latestBlockHeader);
34
28
 
35
29
  if (!byteArrayEquals(blockRoot, latestBlockRoot)) {
36
- throw Error(
30
+ throw new LodestarError(
31
+ {code: "GENESIS_BLOCK_ROOT_MISMATCH"},
37
32
  `Genesis block root ${toRootHex(blockRoot)} does not match genesis state latest block root ${toRootHex(latestBlockRoot)}`
38
33
  );
39
34
  }
@@ -48,16 +43,15 @@ export async function persistAnchorState(
48
43
  }
49
44
  }
50
45
 
51
- export function createGenesisBlock(config: ChainForkConfig, genesisState: BeaconStateAllForks): SignedBeaconBlock {
46
+ export function createGenesisBlock(config: ChainForkConfig, genesisState: IBeaconStateView): SignedBeaconBlock {
52
47
  const types = config.getForkTypes(GENESIS_SLOT);
53
48
  const genesisBlock = types.SignedBeaconBlock.defaultValue();
54
49
  const stateRoot = genesisState.hashTreeRoot();
55
50
  genesisBlock.message.stateRoot = stateRoot;
56
51
 
57
- if (config.getForkSeq(GENESIS_SLOT) >= ForkSeq.gloas) {
52
+ if (config.getForkSeq(GENESIS_SLOT) >= ForkSeq.gloas && isStatePostGloas(genesisState)) {
58
53
  const gloasBlock = genesisBlock as SignedBeaconBlock<ForkPostGloas>;
59
- const gloasState = genesisState as BeaconStateGloas;
60
- gloasBlock.message.body.signedExecutionPayloadBid.message = gloasState.latestExecutionPayloadBid.toValue();
54
+ gloasBlock.message.body.signedExecutionPayloadBid.message = genesisState.latestExecutionPayloadBid;
61
55
  }
62
56
 
63
57
  return genesisBlock;
@@ -86,52 +80,6 @@ export async function initStateFromDb(
86
80
  return state;
87
81
  }
88
82
 
89
- /**
90
- * Initialize and persist an anchor state (either weak subjectivity or genesis)
91
- */
92
- export async function checkAndPersistAnchorState(
93
- config: ChainForkConfig,
94
- db: IBeaconDb,
95
- logger: Logger,
96
- anchorState: BeaconStateAllForks,
97
- anchorStateBytes: Uint8Array,
98
- {
99
- isWithinWeakSubjectivityPeriod,
100
- isCheckpointState,
101
- }: {isWithinWeakSubjectivityPeriod: boolean; isCheckpointState: boolean}
102
- ): Promise<void> {
103
- const expectedFork = config.getForkInfo(computeStartSlotAtEpoch(anchorState.fork.epoch));
104
- const expectedForkVersion = toHex(expectedFork.version);
105
- const stateFork = toHex(anchorState.fork.currentVersion);
106
- if (stateFork !== expectedForkVersion) {
107
- throw Error(
108
- `State current fork version ${stateFork} not equal to current config ${expectedForkVersion}. Maybe caused by importing a state from a different network`
109
- );
110
- }
111
-
112
- const stateInfo = isCheckpointState ? "checkpoint" : "db";
113
- if (isWithinWeakSubjectivityPeriod) {
114
- logger.info(`Initializing beacon from a valid ${stateInfo} state`, {
115
- slot: anchorState.slot,
116
- epoch: computeEpochAtSlot(anchorState.slot),
117
- stateRoot: toRootHex(anchorState.hashTreeRoot()),
118
- isWithinWeakSubjectivityPeriod,
119
- });
120
- } else {
121
- logger.warn(`Initializing from a stale ${stateInfo} state vulnerable to long range attacks`, {
122
- slot: anchorState.slot,
123
- epoch: computeEpochAtSlot(anchorState.slot),
124
- stateRoot: toRootHex(anchorState.hashTreeRoot()),
125
- isWithinWeakSubjectivityPeriod,
126
- });
127
- logger.warn("Checkpoint sync recommended, please use --help to see checkpoint sync options");
128
- }
129
-
130
- if (isCheckpointState || anchorState.slot === GENESIS_SLOT) {
131
- await persistAnchorState(config, db, anchorState, anchorStateBytes);
132
- }
133
- }
134
-
135
83
  export function initBeaconMetrics(metrics: Metrics, state: IBeaconStateView): void {
136
84
  metrics.headSlot.set(state.slot);
137
85
  metrics.previousJustifiedEpoch.set(state.previousJustifiedCheckpoint.epoch);
@@ -30,7 +30,7 @@ import {Metrics} from "../metrics/metrics.js";
30
30
  import {BufferPool} from "../util/bufferPool.js";
31
31
  import {IClock} from "../util/clock.js";
32
32
  import {CustodyConfig} from "../util/dataColumns.js";
33
- import {ReconstructMismatchPolicy} from "../util/execution.js";
33
+ import {ReconstructMissPolicy} from "../util/execution.js";
34
34
  import {SerializedCache} from "../util/serializedCache.js";
35
35
  import {IArchiveStore} from "./archiveStore/interface.js";
36
36
  import {CheckpointBalancesCache} from "./balancesCache.js";
@@ -239,7 +239,7 @@ export interface IBeaconChain {
239
239
  getSerializedExecutionPayloadEnvelope(blockSlot: Slot, blockRootHex: string): Promise<Uint8Array | null>;
240
240
  getSerializedExecutionPayloadEnvelopes(
241
241
  requests: {blockSlot: Slot; blockRootHex: RootHex}[],
242
- onMismatch?: ReconstructMismatchPolicy
242
+ onMiss?: ReconstructMissPolicy
243
243
  ): Promise<(Uint8Array | null)[]>;
244
244
  getExecutionPayloadEnvelope(
245
245
  blockSlot: Slot,