@lodestar/beacon-node 1.39.0-dev.882891d89c → 1.39.0-dev.90493ebb47

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 (91) hide show
  1. package/README.md +1 -1
  2. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  3. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +4 -2
  4. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  5. package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
  6. package/lib/chain/blocks/verifyBlocksSignatures.js +2 -1
  7. package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
  8. package/lib/chain/chain.d.ts +8 -9
  9. package/lib/chain/chain.d.ts.map +1 -1
  10. package/lib/chain/chain.js +17 -33
  11. package/lib/chain/chain.js.map +1 -1
  12. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  13. package/lib/chain/forkChoice/index.js +3 -3
  14. package/lib/chain/forkChoice/index.js.map +1 -1
  15. package/lib/chain/interface.d.ts +4 -7
  16. package/lib/chain/interface.d.ts.map +1 -1
  17. package/lib/chain/interface.js.map +1 -1
  18. package/lib/chain/produceBlock/produceBlockBody.js +1 -1
  19. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  20. package/lib/chain/validation/aggregateAndProof.js +9 -0
  21. package/lib/chain/validation/aggregateAndProof.js.map +1 -1
  22. package/lib/chain/validation/attesterSlashing.d.ts.map +1 -1
  23. package/lib/chain/validation/attesterSlashing.js +2 -2
  24. package/lib/chain/validation/attesterSlashing.js.map +1 -1
  25. package/lib/chain/validation/blobSidecar.d.ts.map +1 -1
  26. package/lib/chain/validation/blobSidecar.js +2 -3
  27. package/lib/chain/validation/blobSidecar.js.map +1 -1
  28. package/lib/chain/validation/block.d.ts.map +1 -1
  29. package/lib/chain/validation/block.js +3 -3
  30. package/lib/chain/validation/block.js.map +1 -1
  31. package/lib/chain/validation/blsToExecutionChange.d.ts.map +1 -1
  32. package/lib/chain/validation/blsToExecutionChange.js +9 -2
  33. package/lib/chain/validation/blsToExecutionChange.js.map +1 -1
  34. package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
  35. package/lib/chain/validation/dataColumnSidecar.js +2 -3
  36. package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
  37. package/lib/chain/validation/proposerSlashing.js +3 -2
  38. package/lib/chain/validation/proposerSlashing.js.map +1 -1
  39. package/lib/chain/validation/voluntaryExit.js +1 -1
  40. package/lib/chain/validation/voluntaryExit.js.map +1 -1
  41. package/lib/network/peers/discover.d.ts.map +1 -1
  42. package/lib/network/peers/discover.js.map +1 -1
  43. package/lib/node/nodejs.d.ts +6 -3
  44. package/lib/node/nodejs.d.ts.map +1 -1
  45. package/lib/node/nodejs.js +3 -1
  46. package/lib/node/nodejs.js.map +1 -1
  47. package/lib/node/notifier.d.ts.map +1 -1
  48. package/lib/node/notifier.js +9 -6
  49. package/lib/node/notifier.js.map +1 -1
  50. package/lib/sync/backfill/backfill.d.ts.map +1 -1
  51. package/lib/sync/backfill/backfill.js +2 -2
  52. package/lib/sync/backfill/backfill.js.map +1 -1
  53. package/lib/sync/backfill/verify.d.ts +2 -2
  54. package/lib/sync/backfill/verify.d.ts.map +1 -1
  55. package/lib/sync/backfill/verify.js +3 -3
  56. package/lib/sync/backfill/verify.js.map +1 -1
  57. package/package.json +28 -20
  58. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +9 -2
  59. package/src/chain/blocks/verifyBlocksSignatures.ts +11 -3
  60. package/src/chain/chain.ts +27 -38
  61. package/src/chain/forkChoice/index.ts +3 -2
  62. package/src/chain/interface.ts +4 -6
  63. package/src/chain/produceBlock/produceBlockBody.ts +1 -1
  64. package/src/chain/validation/aggregateAndProof.ts +12 -0
  65. package/src/chain/validation/attesterSlashing.ts +14 -2
  66. package/src/chain/validation/blobSidecar.ts +3 -3
  67. package/src/chain/validation/block.ts +3 -2
  68. package/src/chain/validation/blsToExecutionChange.ts +9 -7
  69. package/src/chain/validation/dataColumnSidecar.ts +3 -3
  70. package/src/chain/validation/proposerSlashing.ts +8 -2
  71. package/src/chain/validation/voluntaryExit.ts +1 -1
  72. package/src/network/peers/discover.ts +3 -3
  73. package/src/node/nodejs.ts +9 -2
  74. package/src/node/notifier.ts +13 -7
  75. package/src/sync/backfill/backfill.ts +2 -14
  76. package/src/sync/backfill/verify.ts +2 -9
  77. package/lib/chain/rewards/attestationsRewards.d.ts +0 -8
  78. package/lib/chain/rewards/attestationsRewards.d.ts.map +0 -1
  79. package/lib/chain/rewards/attestationsRewards.js +0 -112
  80. package/lib/chain/rewards/attestationsRewards.js.map +0 -1
  81. package/lib/chain/rewards/blockRewards.d.ts +0 -15
  82. package/lib/chain/rewards/blockRewards.d.ts.map +0 -1
  83. package/lib/chain/rewards/blockRewards.js +0 -94
  84. package/lib/chain/rewards/blockRewards.js.map +0 -1
  85. package/lib/chain/rewards/syncCommitteeRewards.d.ts +0 -7
  86. package/lib/chain/rewards/syncCommitteeRewards.d.ts.map +0 -1
  87. package/lib/chain/rewards/syncCommitteeRewards.js +0 -36
  88. package/lib/chain/rewards/syncCommitteeRewards.js.map +0 -1
  89. package/src/chain/rewards/attestationsRewards.ts +0 -206
  90. package/src/chain/rewards/blockRewards.ts +0 -153
  91. package/src/chain/rewards/syncCommitteeRewards.ts +0 -60
@@ -8,7 +8,12 @@ import {
8
8
  ProtoBlock,
9
9
  } from "@lodestar/fork-choice";
10
10
  import {ForkSeq} from "@lodestar/params";
11
- import {CachedBeaconStateAllForks, isExecutionBlockBodyType, isExecutionStateType} from "@lodestar/state-transition";
11
+ import {
12
+ CachedBeaconStateAllForks,
13
+ isExecutionBlockBodyType,
14
+ isExecutionEnabled,
15
+ isExecutionStateType,
16
+ } from "@lodestar/state-transition";
12
17
  import {bellatrix, electra} from "@lodestar/types";
13
18
  import {ErrorAborted, Logger, toRootHex} from "@lodestar/utils";
14
19
  import {ExecutionPayloadStatus, IExecutionEngine} from "../../execution/engine/interface.js";
@@ -145,7 +150,9 @@ export async function verifyBlockExecutionPayload(
145
150
  const block = blockInput.getBlock();
146
151
  /** Not null if execution is enabled */
147
152
  const executionPayloadEnabled =
148
- isExecutionStateType(preState0) && isExecutionBlockBodyType(block.message.body)
153
+ isExecutionStateType(preState0) &&
154
+ isExecutionBlockBodyType(block.message.body) &&
155
+ isExecutionEnabled(preState0, block.message)
149
156
  ? block.message.body.executionPayload
150
157
  : null;
151
158
 
@@ -28,6 +28,7 @@ export async function verifyBlocksSignatures(
28
28
  ): Promise<{verifySignaturesTime: number}> {
29
29
  const isValidPromises: Promise<boolean>[] = [];
30
30
  const recvToValLatency = Date.now() / 1000 - (opts.seenTimestampSec ?? Date.now() / 1000);
31
+ const currentSyncCommitteeIndexed = preState0.epochCtx.currentSyncCommitteeIndexed;
31
32
 
32
33
  // Verifies signatures after running state transition, so all SyncCommittee signed roots are known at this point.
33
34
  // We must ensure block.slot <= state.slot before running getAllBlockSignatureSets().
@@ -41,9 +42,16 @@ export async function verifyBlocksSignatures(
41
42
  : //
42
43
  // Verify signatures per block to track which block is invalid
43
44
  bls.verifySignatureSets(
44
- getBlockSignatureSets(config, index2pubkey, preState0, block, indexedAttestationsByBlock[i], {
45
- skipProposerSignature: opts.validProposerSignature,
46
- })
45
+ getBlockSignatureSets(
46
+ config,
47
+ index2pubkey,
48
+ currentSyncCommitteeIndexed,
49
+ block,
50
+ indexedAttestationsByBlock[i],
51
+ {
52
+ skipProposerSignature: opts.validProposerSignature,
53
+ }
54
+ )
47
55
  );
48
56
 
49
57
  // getBlockSignatureSets() takes 45ms in benchmarks for 2022Q2 mainnet blocks (100 sigs). When syncing a 32 blocks
@@ -14,13 +14,14 @@ import {
14
14
  EpochShuffling,
15
15
  Index2PubkeyCache,
16
16
  computeAnchorCheckpoint,
17
+ computeAttestationsRewards,
18
+ computeBlockRewards,
17
19
  computeEndSlotAtEpoch,
18
20
  computeEpochAtSlot,
19
21
  computeStartSlotAtEpoch,
20
- createCachedBeaconState,
22
+ computeSyncCommitteeRewards,
21
23
  getEffectiveBalanceIncrementsZeroInactive,
22
24
  getEffectiveBalancesFromStateBytes,
23
- isCachedBeaconState,
24
25
  processSlots,
25
26
  } from "@lodestar/state-transition";
26
27
  import {
@@ -38,6 +39,7 @@ import {
38
39
  Wei,
39
40
  isBlindedBeaconBlock,
40
41
  phase0,
42
+ rewards,
41
43
  } from "@lodestar/types";
42
44
  import {Logger, fromHex, gweiToWei, isErrorAborted, pruneSetToMax, sleep, toRootHex} from "@lodestar/utils";
43
45
  import {ProcessShutdownCallback} from "@lodestar/validator";
@@ -79,9 +81,6 @@ import {AssembledBlockType, BlockType, ProduceResult} from "./produceBlock/index
79
81
  import {BlockAttributes, produceBlockBody, produceCommonBlockBody} from "./produceBlock/produceBlockBody.js";
80
82
  import {QueuedStateRegenerator, RegenCaller} from "./regen/index.js";
81
83
  import {ReprocessController} from "./reprocess.js";
82
- import {AttestationsRewards, computeAttestationsRewards} from "./rewards/attestationsRewards.js";
83
- import {BlockRewards, computeBlockRewards} from "./rewards/blockRewards.js";
84
- import {SyncCommitteeRewards, computeSyncCommitteeRewards} from "./rewards/syncCommitteeRewards.js";
85
84
  import {
86
85
  SeenAggregators,
87
86
  SeenAttesters,
@@ -204,6 +203,8 @@ export class BeaconChain implements IBeaconChain {
204
203
  {
205
204
  privateKey,
206
205
  config,
206
+ pubkey2index,
207
+ index2pubkey,
207
208
  db,
208
209
  dbName,
209
210
  dataDir,
@@ -219,6 +220,8 @@ export class BeaconChain implements IBeaconChain {
219
220
  }: {
220
221
  privateKey: PrivateKey;
221
222
  config: BeaconConfig;
223
+ pubkey2index: PubkeyIndexMap;
224
+ index2pubkey: Index2PubkeyCache;
222
225
  db: IBeaconDb;
223
226
  dbName: string;
224
227
  dataDir: string;
@@ -228,7 +231,7 @@ export class BeaconChain implements IBeaconChain {
228
231
  clock?: IClock;
229
232
  metrics: Metrics | null;
230
233
  validatorMonitor: ValidatorMonitor | null;
231
- anchorState: BeaconStateAllForks;
234
+ anchorState: CachedBeaconStateAllForks;
232
235
  isAnchorStateFinalized: boolean;
233
236
  executionEngine: IExecutionEngine;
234
237
  executionBuilder?: IExecutionBuilder;
@@ -287,39 +290,25 @@ export class BeaconChain implements IBeaconChain {
287
290
  logger,
288
291
  });
289
292
 
290
- // Restore state caches
291
- // anchorState may already by a CachedBeaconState. If so, don't create the cache again, since deserializing all
292
- // pubkeys takes ~30 seconds for 350k keys (mainnet 2022Q2).
293
- // When the BeaconStateCache is created in initializeBeaconStateFromEth1 it may be incorrect. Until we can ensure that
294
- // it's safe to re-use _ANY_ BeaconStateCache, this option is disabled by default and only used in tests.
295
- const cachedState =
296
- isCachedBeaconState(anchorState) && opts.skipCreateStateCacheIfAvailable
297
- ? anchorState
298
- : createCachedBeaconState(anchorState, {
299
- config,
300
- pubkey2index: new PubkeyIndexMap(),
301
- index2pubkey: [],
302
- });
303
- this._earliestAvailableSlot = cachedState.slot;
304
-
305
- this.shufflingCache = cachedState.epochCtx.shufflingCache = new ShufflingCache(metrics, logger, this.opts, [
293
+ this._earliestAvailableSlot = anchorState.slot;
294
+ this.shufflingCache = anchorState.epochCtx.shufflingCache = new ShufflingCache(metrics, logger, this.opts, [
306
295
  {
307
- shuffling: cachedState.epochCtx.previousShuffling,
308
- decisionRoot: cachedState.epochCtx.previousDecisionRoot,
296
+ shuffling: anchorState.epochCtx.previousShuffling,
297
+ decisionRoot: anchorState.epochCtx.previousDecisionRoot,
309
298
  },
310
299
  {
311
- shuffling: cachedState.epochCtx.currentShuffling,
312
- decisionRoot: cachedState.epochCtx.currentDecisionRoot,
300
+ shuffling: anchorState.epochCtx.currentShuffling,
301
+ decisionRoot: anchorState.epochCtx.currentDecisionRoot,
313
302
  },
314
303
  {
315
- shuffling: cachedState.epochCtx.nextShuffling,
316
- decisionRoot: cachedState.epochCtx.nextDecisionRoot,
304
+ shuffling: anchorState.epochCtx.nextShuffling,
305
+ decisionRoot: anchorState.epochCtx.nextDecisionRoot,
317
306
  },
318
307
  ]);
319
308
 
320
- // Persist single global instance of state caches
321
- this.pubkey2index = cachedState.epochCtx.pubkey2index;
322
- this.index2pubkey = cachedState.epochCtx.index2pubkey;
309
+ // Global cache of validators pubkey/index mapping
310
+ this.pubkey2index = pubkey2index;
311
+ this.index2pubkey = index2pubkey;
323
312
 
324
313
  const fileDataStore = opts.nHistoricalStatesFileDataStore ?? true;
325
314
  const blockStateCache = this.opts.nHistoricalStates
@@ -350,15 +339,15 @@ export class BeaconChain implements IBeaconChain {
350
339
  }
351
340
 
352
341
  const {checkpoint} = computeAnchorCheckpoint(config, anchorState);
353
- blockStateCache.add(cachedState);
354
- blockStateCache.setHeadState(cachedState);
355
- checkpointStateCache.add(checkpoint, cachedState);
342
+ blockStateCache.add(anchorState);
343
+ blockStateCache.setHeadState(anchorState);
344
+ checkpointStateCache.add(checkpoint, anchorState);
356
345
 
357
346
  const forkChoice = initializeForkChoice(
358
347
  config,
359
348
  emitter,
360
349
  clock.currentSlot,
361
- cachedState,
350
+ anchorState,
362
351
  isAnchorStateFinalized,
363
352
  opts,
364
353
  this.justifiedBalancesGetter.bind(this),
@@ -1297,7 +1286,7 @@ export class BeaconChain implements IBeaconChain {
1297
1286
  }
1298
1287
  }
1299
1288
 
1300
- async getBlockRewards(block: BeaconBlock | BlindedBeaconBlock): Promise<BlockRewards> {
1289
+ async getBlockRewards(block: BeaconBlock | BlindedBeaconBlock): Promise<rewards.BlockRewards> {
1301
1290
  let preState = this.regen.getPreStateSync(block);
1302
1291
 
1303
1292
  if (preState === null) {
@@ -1314,7 +1303,7 @@ export class BeaconChain implements IBeaconChain {
1314
1303
  async getAttestationsRewards(
1315
1304
  epoch: Epoch,
1316
1305
  validatorIds?: (ValidatorIndex | string)[]
1317
- ): Promise<{rewards: AttestationsRewards; executionOptimistic: boolean; finalized: boolean}> {
1306
+ ): Promise<{rewards: rewards.AttestationsRewards; executionOptimistic: boolean; finalized: boolean}> {
1318
1307
  // We use end slot of (epoch + 1) to ensure we have seen all attestations. On-time or late. Any late attestation beyond this slot is not considered
1319
1308
  const slot = computeEndSlotAtEpoch(epoch + 1);
1320
1309
  const stateResult = await this.getStateBySlot(slot, {allowRegen: false}); // No regen if state not in cache
@@ -1340,7 +1329,7 @@ export class BeaconChain implements IBeaconChain {
1340
1329
  async getSyncCommitteeRewards(
1341
1330
  block: BeaconBlock | BlindedBeaconBlock,
1342
1331
  validatorIds?: (ValidatorIndex | string)[]
1343
- ): Promise<SyncCommitteeRewards> {
1332
+ ): Promise<rewards.SyncCommitteeRewards> {
1344
1333
  let preState = this.regen.getPreStateSync(block);
1345
1334
 
1346
1335
  if (preState === null) {
@@ -18,6 +18,7 @@ import {
18
18
  getBlockRootAtSlot,
19
19
  getEffectiveBalanceIncrementsZeroInactive,
20
20
  isExecutionStateType,
21
+ isMergeTransitionComplete,
21
22
  } from "@lodestar/state-transition";
22
23
  import {Slot, ssz} from "@lodestar/types";
23
24
  import {Logger, toRootHex} from "@lodestar/utils";
@@ -134,7 +135,7 @@ export function initializeForkChoiceFromFinalizedState(
134
135
  unrealizedFinalizedEpoch: finalizedCheckpoint.epoch,
135
136
  unrealizedFinalizedRoot: toRootHex(finalizedCheckpoint.root),
136
137
 
137
- ...(isExecutionStateType(state)
138
+ ...(isExecutionStateType(state) && isMergeTransitionComplete(state)
138
139
  ? {
139
140
  executionPayloadBlockHash: toRootHex(state.latestExecutionPayloadHeader.blockHash),
140
141
  executionPayloadNumber: state.latestExecutionPayloadHeader.blockNumber,
@@ -215,7 +216,7 @@ export function initializeForkChoiceFromUnfinalizedState(
215
216
  unrealizedFinalizedEpoch: finalizedCheckpoint.epoch,
216
217
  unrealizedFinalizedRoot: toRootHex(finalizedCheckpoint.root),
217
218
 
218
- ...(isExecutionStateType(unfinalizedState)
219
+ ...(isExecutionStateType(unfinalizedState) && isMergeTransitionComplete(unfinalizedState)
219
220
  ? {
220
221
  executionPayloadBlockHash: toRootHex(unfinalizedState.latestExecutionPayloadHeader.blockHash),
221
222
  executionPayloadNumber: unfinalizedState.latestExecutionPayloadHeader.blockNumber,
@@ -23,6 +23,7 @@ import {
23
23
  altair,
24
24
  capella,
25
25
  phase0,
26
+ rewards,
26
27
  } from "@lodestar/types";
27
28
  import {Logger} from "@lodestar/utils";
28
29
  import {IExecutionBuilder, IExecutionEngine} from "../execution/index.js";
@@ -48,9 +49,6 @@ import {IChainOptions} from "./options.js";
48
49
  import {AssembledBlockType, BlockAttributes, BlockType, ProduceResult} from "./produceBlock/produceBlockBody.js";
49
50
  import {IStateRegenerator, RegenCaller} from "./regen/index.js";
50
51
  import {ReprocessController} from "./reprocess.js";
51
- import {AttestationsRewards} from "./rewards/attestationsRewards.js";
52
- import {BlockRewards} from "./rewards/blockRewards.js";
53
- import {SyncCommitteeRewards} from "./rewards/syncCommitteeRewards.js";
54
52
  import {
55
53
  SeenAggregators,
56
54
  SeenAttesters,
@@ -255,15 +253,15 @@ export interface IBeaconChain {
255
253
  regenCanAcceptWork(): boolean;
256
254
  blsThreadPoolCanAcceptWork(): boolean;
257
255
 
258
- getBlockRewards(blockRef: BeaconBlock | BlindedBeaconBlock): Promise<BlockRewards>;
256
+ getBlockRewards(blockRef: BeaconBlock | BlindedBeaconBlock): Promise<rewards.BlockRewards>;
259
257
  getAttestationsRewards(
260
258
  epoch: Epoch,
261
259
  validatorIds?: (ValidatorIndex | string)[]
262
- ): Promise<{rewards: AttestationsRewards; executionOptimistic: boolean; finalized: boolean}>;
260
+ ): Promise<{rewards: rewards.AttestationsRewards; executionOptimistic: boolean; finalized: boolean}>;
263
261
  getSyncCommitteeRewards(
264
262
  blockRef: BeaconBlock | BlindedBeaconBlock,
265
263
  validatorIds?: (ValidatorIndex | string)[]
266
- ): Promise<SyncCommitteeRewards>;
264
+ ): Promise<rewards.SyncCommitteeRewards>;
267
265
  }
268
266
 
269
267
  export type SSZObjectType =
@@ -623,7 +623,7 @@ function preparePayloadAttributes(
623
623
  (payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals = getExpectedWithdrawals(
624
624
  ForkSeq[fork],
625
625
  prepareState as CachedBeaconStateCapella
626
- ).withdrawals;
626
+ ).expectedWithdrawals;
627
627
  }
628
628
 
629
629
  if (ForkSeq[fork] >= ForkSeq.deneb) {
@@ -245,6 +245,18 @@ async function validateAggregateAndProof(
245
245
  });
246
246
  }
247
247
 
248
+ // Same race-condition check as above for seen aggregators
249
+ if (
250
+ !skipValidationKnownAttesters &&
251
+ chain.seenAggregatedAttestations.isKnown(targetEpoch, attIndex, attDataRootHex, aggregationBits)
252
+ ) {
253
+ throw new AttestationError(GossipAction.IGNORE, {
254
+ code: AttestationErrorCode.ATTESTERS_ALREADY_KNOWN,
255
+ targetEpoch,
256
+ aggregateRoot: attDataRootHex,
257
+ });
258
+ }
259
+
248
260
  chain.seenAggregators.add(targetEpoch, aggregatorIndex);
249
261
  chain.seenAggregatedAttestations.add(
250
262
  targetEpoch,
@@ -43,7 +43,14 @@ export async function validateAttesterSlashing(
43
43
  // [REJECT] All of the conditions within process_attester_slashing pass validation.
44
44
  try {
45
45
  // verifySignature = false, verified in batch below
46
- assertValidAttesterSlashing(chain.index2pubkey, state, attesterSlashing, false);
46
+ assertValidAttesterSlashing(
47
+ chain.config,
48
+ chain.index2pubkey,
49
+ state.slot,
50
+ state.validators.length,
51
+ attesterSlashing,
52
+ false
53
+ );
47
54
  } catch (e) {
48
55
  throw new AttesterSlashingError(GossipAction.REJECT, {
49
56
  code: AttesterSlashingErrorCode.INVALID,
@@ -51,7 +58,12 @@ export async function validateAttesterSlashing(
51
58
  });
52
59
  }
53
60
 
54
- const signatureSets = getAttesterSlashingSignatureSets(chain.config, chain.index2pubkey, state, attesterSlashing);
61
+ const signatureSets = getAttesterSlashingSignatureSets(
62
+ chain.config,
63
+ chain.index2pubkey,
64
+ state.slot,
65
+ attesterSlashing
66
+ );
55
67
  if (!(await chain.bls.verifySignatureSets(signatureSets, {batchable: true, priority: prioritizeBls}))) {
56
68
  throw new AttesterSlashingError(GossipAction.REJECT, {
57
69
  code: AttesterSlashingErrorCode.INVALID,
@@ -138,8 +138,9 @@ export async function validateGossipBlobSidecar(
138
138
  const signature = blobSidecar.signedBlockHeader.signature;
139
139
  if (!chain.seenBlockInputCache.isVerifiedProposerSignature(blobSlot, blockHex, signature)) {
140
140
  const signatureSet = getBlockHeaderProposerSignatureSetByParentStateSlot(
141
+ chain.config,
141
142
  chain.index2pubkey,
142
- blockState,
143
+ blockState.slot,
143
144
  blobSidecar.signedBlockHeader
144
145
  );
145
146
  // Don't batch so verification is not delayed
@@ -243,10 +244,9 @@ export async function validateBlockBlobSidecars(
243
244
  const blockRootHex = toRootHex(blockRoot);
244
245
  const signature = firstSidecarSignedBlockHeader.signature;
245
246
  if (!chain.seenBlockInputCache.isVerifiedProposerSignature(blockSlot, blockRootHex, signature)) {
246
- const headState = await chain.getHeadState();
247
247
  const signatureSet = getBlockHeaderProposerSignatureSetByHeaderSlot(
248
+ chain.config,
248
249
  chain.index2pubkey,
249
- headState,
250
250
  firstSidecarSignedBlockHeader
251
251
  );
252
252
 
@@ -6,6 +6,7 @@ import {
6
6
  computeTimeAtSlot,
7
7
  getBlockProposerSignatureSet,
8
8
  isExecutionBlockBodyType,
9
+ isExecutionEnabled,
9
10
  isExecutionStateType,
10
11
  } from "@lodestar/state-transition";
11
12
  import {SignedBeaconBlock, deneb} from "@lodestar/types";
@@ -139,7 +140,7 @@ export async function validateGossipBlock(
139
140
  if (fork === ForkName.bellatrix) {
140
141
  if (!isExecutionBlockBodyType(block.body)) throw Error("Not merge block type");
141
142
  const executionPayload = block.body.executionPayload;
142
- if (isExecutionStateType(blockState)) {
143
+ if (isExecutionStateType(blockState) && isExecutionEnabled(blockState, block)) {
143
144
  const expectedTimestamp = computeTimeAtSlot(config, blockSlot, chain.genesisTime);
144
145
  if (executionPayload.timestamp !== computeTimeAtSlot(config, blockSlot, chain.genesisTime)) {
145
146
  throw new BlockGossipError(GossipAction.REJECT, {
@@ -153,7 +154,7 @@ export async function validateGossipBlock(
153
154
 
154
155
  // [REJECT] The proposer signature, signed_beacon_block.signature, is valid with respect to the proposer_index pubkey.
155
156
  if (!chain.seenBlockInputCache.isVerifiedProposerSignature(blockSlot, blockRoot, signedBlock.signature)) {
156
- const signatureSet = getBlockProposerSignatureSet(chain.config, chain.index2pubkey, blockState, signedBlock);
157
+ const signatureSet = getBlockProposerSignatureSet(chain.config, chain.index2pubkey, signedBlock);
157
158
  // Don't batch so verification is not delayed
158
159
  if (!(await chain.bls.verifySignatureSets([signatureSet], {verifyOnMainThread: true}))) {
159
160
  throw new BlockGossipError(GossipAction.REJECT, {
@@ -1,8 +1,4 @@
1
- import {
2
- CachedBeaconStateCapella,
3
- getBlsToExecutionChangeSignatureSet,
4
- isValidBlsToExecutionChange,
5
- } from "@lodestar/state-transition";
1
+ import {getBlsToExecutionChangeSignatureSet, isValidBlsToExecutionChange} from "@lodestar/state-transition";
6
2
  import {capella} from "@lodestar/types";
7
3
  import {BlsToExecutionChangeError, BlsToExecutionChangeErrorCode, GossipAction} from "../errors/index.js";
8
4
  import {IBeaconChain} from "../index.js";
@@ -42,10 +38,16 @@ async function validateBlsToExecutionChange(
42
38
  // and chanes relevant to `isValidBlsToExecutionChange()` happen only on processBlock(), not processEpoch()
43
39
  const state = chain.getHeadState();
44
40
  const {config} = chain;
45
-
41
+ const addressChange = blsToExecutionChange.message;
42
+ if (addressChange.validatorIndex >= state.validators.length) {
43
+ throw new BlsToExecutionChangeError(GossipAction.REJECT, {
44
+ code: BlsToExecutionChangeErrorCode.INVALID,
45
+ });
46
+ }
47
+ const validator = state.validators.getReadonly(addressChange.validatorIndex);
46
48
  // [REJECT] All of the conditions within process_bls_to_execution_change pass validation.
47
49
  // verifySignature = false, verified in batch below
48
- const {valid} = isValidBlsToExecutionChange(state as CachedBeaconStateCapella, blsToExecutionChange, false);
50
+ const {valid} = isValidBlsToExecutionChange(config, validator, blsToExecutionChange, false);
49
51
  if (!valid) {
50
52
  throw new BlsToExecutionChangeError(GossipAction.REJECT, {
51
53
  code: BlsToExecutionChangeErrorCode.INVALID,
@@ -135,8 +135,9 @@ export async function validateGossipDataColumnSidecar(
135
135
  const signature = dataColumnSidecar.signedBlockHeader.signature;
136
136
  if (!chain.seenBlockInputCache.isVerifiedProposerSignature(blockHeader.slot, blockRootHex, signature)) {
137
137
  const signatureSet = getBlockHeaderProposerSignatureSetByParentStateSlot(
138
+ chain.config,
138
139
  chain.index2pubkey,
139
- blockState,
140
+ blockState.slot,
140
141
  dataColumnSidecar.signedBlockHeader
141
142
  );
142
143
 
@@ -336,10 +337,9 @@ export async function validateBlockDataColumnSidecars(
336
337
  const slot = firstSidecarSignedBlockHeader.message.slot;
337
338
  const signature = firstSidecarSignedBlockHeader.signature;
338
339
  if (!chain.seenBlockInputCache.isVerifiedProposerSignature(slot, rootHex, signature)) {
339
- const headState = await chain.getHeadState();
340
340
  const signatureSet = getBlockHeaderProposerSignatureSetByHeaderSlot(
341
+ chain.config,
341
342
  chain.index2pubkey,
342
- headState,
343
343
  firstSidecarSignedBlockHeader
344
344
  );
345
345
 
@@ -35,8 +35,9 @@ async function validateProposerSlashing(
35
35
 
36
36
  // [REJECT] All of the conditions within process_proposer_slashing pass validation.
37
37
  try {
38
+ const proposer = state.validators.getReadonly(proposerSlashing.signedHeader1.message.proposerIndex);
38
39
  // verifySignature = false, verified in batch below
39
- assertValidProposerSlashing(state, proposerSlashing, false);
40
+ assertValidProposerSlashing(chain.config, chain.index2pubkey, state.slot, proposerSlashing, proposer, false);
40
41
  } catch (e) {
41
42
  throw new ProposerSlashingError(GossipAction.REJECT, {
42
43
  code: ProposerSlashingErrorCode.INVALID,
@@ -44,7 +45,12 @@ async function validateProposerSlashing(
44
45
  });
45
46
  }
46
47
 
47
- const signatureSets = getProposerSlashingSignatureSets(chain.config, chain.index2pubkey, state, proposerSlashing);
48
+ const signatureSets = getProposerSlashingSignatureSets(
49
+ chain.config,
50
+ chain.index2pubkey,
51
+ state.slot,
52
+ proposerSlashing
53
+ );
48
54
  if (!(await chain.bls.verifySignatureSets(signatureSets, {batchable: true, priority: prioritizeBls}))) {
49
55
  throw new ProposerSlashingError(GossipAction.REJECT, {
50
56
  code: ProposerSlashingErrorCode.INVALID,
@@ -59,7 +59,7 @@ async function validateVoluntaryExit(
59
59
  });
60
60
  }
61
61
 
62
- const signatureSet = getVoluntaryExitSignatureSet(chain.config, chain.index2pubkey, state, voluntaryExit);
62
+ const signatureSet = getVoluntaryExitSignatureSet(chain.config, chain.index2pubkey, state.slot, voluntaryExit);
63
63
  if (!(await chain.bls.verifySignatureSets([signatureSet], {batchable: true, priority: prioritizeBls}))) {
64
64
  throw new VoluntaryExitError(GossipAction.REJECT, {
65
65
  code: VoluntaryExitErrorCode.INVALID_SIGNATURE,
@@ -1,4 +1,4 @@
1
- import type {PeerId, PeerInfo, PrivateKey} from "@libp2p/interface";
1
+ import type {PeerId, PeerInfo, PendingDial, PrivateKey} from "@libp2p/interface";
2
2
  import {Multiaddr} from "@multiformats/multiaddr";
3
3
  import {ENR} from "@chainsafe/enr";
4
4
  import {BeaconConfig} from "@lodestar/config";
@@ -217,7 +217,7 @@ export class PeerDiscovery {
217
217
  const pendingDials = new Set(
218
218
  this.libp2p.services.components.connectionManager
219
219
  .getDialQueue()
220
- .map((pendingDial) => pendingDial.peerId?.toString())
220
+ .map((pendingDial: PendingDial) => pendingDial.peerId?.toString())
221
221
  );
222
222
  for (const [id, cachedENR] of this.cachedENRs.entries()) {
223
223
  if (
@@ -458,7 +458,7 @@ export class PeerDiscovery {
458
458
  if (
459
459
  this.libp2p.services.components.connectionManager
460
460
  .getDialQueue()
461
- .find((pendingDial) => pendingDial.peerId?.equals(peerId))
461
+ .find((pendingDial: PendingDial) => pendingDial.peerId?.equals(peerId))
462
462
  ) {
463
463
  return DiscoveredPeerStatus.already_dialing;
464
464
  }
@@ -2,10 +2,11 @@ import {setMaxListeners} from "node:events";
2
2
  import {PrivateKey} from "@libp2p/interface";
3
3
  import {Registry} from "prom-client";
4
4
  import {hasher} from "@chainsafe/persistent-merkle-tree";
5
+ import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
5
6
  import {BeaconApiMethods} from "@lodestar/api/beacon/server";
6
7
  import {BeaconConfig} from "@lodestar/config";
7
8
  import type {LoggerNode} from "@lodestar/logger/node";
8
- import {BeaconStateAllForks} from "@lodestar/state-transition";
9
+ import {CachedBeaconStateAllForks, Index2PubkeyCache} from "@lodestar/state-transition";
9
10
  import {phase0} from "@lodestar/types";
10
11
  import {sleep} from "@lodestar/utils";
11
12
  import {ProcessShutdownCallback} from "@lodestar/validator";
@@ -45,13 +46,15 @@ export type BeaconNodeModules = {
45
46
  export type BeaconNodeInitModules = {
46
47
  opts: IBeaconNodeOptions;
47
48
  config: BeaconConfig;
49
+ pubkey2index: PubkeyIndexMap;
50
+ index2pubkey: Index2PubkeyCache;
48
51
  db: IBeaconDb;
49
52
  logger: LoggerNode;
50
53
  processShutdownCallback: ProcessShutdownCallback;
51
54
  privateKey: PrivateKey;
52
55
  dataDir: string;
53
56
  peerStoreDir?: string;
54
- anchorState: BeaconStateAllForks;
57
+ anchorState: CachedBeaconStateAllForks;
55
58
  isAnchorStateFinalized: boolean;
56
59
  wsCheckpoint?: phase0.Checkpoint;
57
60
  metricsRegistries?: Registry[];
@@ -146,6 +149,8 @@ export class BeaconNode {
146
149
  static async init<T extends BeaconNode = BeaconNode>({
147
150
  opts,
148
151
  config,
152
+ pubkey2index,
153
+ index2pubkey,
149
154
  db,
150
155
  logger,
151
156
  processShutdownCallback,
@@ -220,6 +225,8 @@ export class BeaconNode {
220
225
  privateKey,
221
226
  config,
222
227
  clock,
228
+ pubkey2index,
229
+ index2pubkey,
223
230
  dataDir,
224
231
  db,
225
232
  dbName: opts.db.name,
@@ -6,6 +6,7 @@ import {
6
6
  computeEpochAtSlot,
7
7
  computeStartSlotAtEpoch,
8
8
  isExecutionCachedStateType,
9
+ isMergeTransitionComplete,
9
10
  } from "@lodestar/state-transition";
10
11
  import {Epoch} from "@lodestar/types";
11
12
  import {ErrorAborted, Logger, prettyBytes, prettyBytesShort, sleep} from "@lodestar/utils";
@@ -171,13 +172,18 @@ function getHeadExecutionInfo(
171
172
 
172
173
  // Add execution status to notifier only if head is on/post bellatrix
173
174
  if (isExecutionCachedStateType(headState)) {
174
- const executionPayloadHashInfo =
175
- headInfo.executionStatus !== ExecutionStatus.PreMerge ? headInfo.executionPayloadBlockHash : "empty";
176
- const executionPayloadNumberInfo =
177
- headInfo.executionStatus !== ExecutionStatus.PreMerge ? headInfo.executionPayloadNumber : NaN;
178
- return [
179
- `exec-block: ${executionStatusStr}(${executionPayloadNumberInfo} ${prettyBytesShort(executionPayloadHashInfo)})`,
180
- ];
175
+ if (isMergeTransitionComplete(headState)) {
176
+ const executionPayloadHashInfo =
177
+ headInfo.executionStatus !== ExecutionStatus.PreMerge ? headInfo.executionPayloadBlockHash : "empty";
178
+ const executionPayloadNumberInfo =
179
+ headInfo.executionStatus !== ExecutionStatus.PreMerge ? headInfo.executionPayloadNumber : NaN;
180
+ return [
181
+ `exec-block: ${executionStatusStr}(${executionPayloadNumberInfo} ${prettyBytesShort(
182
+ executionPayloadHashInfo
183
+ )})`,
184
+ ];
185
+ }
186
+ return [`exec-block: ${executionStatusStr}`];
181
187
  }
182
188
 
183
189
  return [];
@@ -750,13 +750,7 @@ export class BackfillSync extends (EventEmitter as {new (): BackfillSyncEmitter}
750
750
 
751
751
  // GENESIS_SLOT doesn't has valid signature
752
752
  if (anchorBlock.message.slot === GENESIS_SLOT) return;
753
- await verifyBlockProposerSignature(
754
- this.chain.config,
755
- this.chain.index2pubkey,
756
- this.chain.bls,
757
- this.chain.getHeadState(),
758
- [anchorBlock]
759
- );
753
+ await verifyBlockProposerSignature(this.chain.config, this.chain.index2pubkey, this.chain.bls, [anchorBlock]);
760
754
 
761
755
  // We can write to the disk if this is ahead of prevFinalizedCheckpointBlock otherwise
762
756
  // we will need to go make checks on the top of sync loop before writing as it might
@@ -821,13 +815,7 @@ export class BackfillSync extends (EventEmitter as {new (): BackfillSyncEmitter}
821
815
 
822
816
  // If any of the block's proposer signature fail, we can't trust this peer at all
823
817
  if (verifiedBlocks.length > 0) {
824
- await verifyBlockProposerSignature(
825
- this.chain.config,
826
- this.chain.index2pubkey,
827
- this.chain.bls,
828
- this.chain.getHeadState(),
829
- verifiedBlocks
830
- );
818
+ await verifyBlockProposerSignature(this.chain.config, this.chain.index2pubkey, this.chain.bls, verifiedBlocks);
831
819
 
832
820
  // This is bad, like super bad. Abort the backfill
833
821
  if (!nextAnchor)
@@ -1,11 +1,6 @@
1
1
  import {BeaconConfig} from "@lodestar/config";
2
2
  import {GENESIS_SLOT} from "@lodestar/params";
3
- import {
4
- CachedBeaconStateAllForks,
5
- ISignatureSet,
6
- Index2PubkeyCache,
7
- getBlockProposerSignatureSet,
8
- } from "@lodestar/state-transition";
3
+ import {ISignatureSet, Index2PubkeyCache, getBlockProposerSignatureSet} from "@lodestar/state-transition";
9
4
  import {Root, SignedBeaconBlock, Slot, ssz} from "@lodestar/types";
10
5
  import {IBlsVerifier} from "../../chain/bls/index.js";
11
6
  import {BackfillSyncError, BackfillSyncErrorCode} from "./errors.js";
@@ -49,14 +44,12 @@ export async function verifyBlockProposerSignature(
49
44
  config: BeaconConfig,
50
45
  index2pubkey: Index2PubkeyCache,
51
46
  bls: IBlsVerifier,
52
- state: CachedBeaconStateAllForks,
53
47
  blocks: SignedBeaconBlock[]
54
48
  ): Promise<void> {
55
49
  if (blocks.length === 1 && blocks[0].message.slot === GENESIS_SLOT) return;
56
50
  const signatures = blocks.reduce((sigs: ISignatureSet[], block) => {
57
51
  // genesis block doesn't have valid signature
58
- if (block.message.slot !== GENESIS_SLOT)
59
- sigs.push(getBlockProposerSignatureSet(config, index2pubkey, state, block));
52
+ if (block.message.slot !== GENESIS_SLOT) sigs.push(getBlockProposerSignatureSet(config, index2pubkey, block));
60
53
  return sigs;
61
54
  }, []);
62
55
 
@@ -1,8 +0,0 @@
1
- import { PubkeyIndexMap } from "@chainsafe/pubkey-index-map";
2
- import { routes } from "@lodestar/api";
3
- import { BeaconConfig } from "@lodestar/config";
4
- import { CachedBeaconStateAllForks } from "@lodestar/state-transition";
5
- import { ValidatorIndex } from "@lodestar/types";
6
- export type AttestationsRewards = routes.beacon.AttestationsRewards;
7
- export declare function computeAttestationsRewards(config: BeaconConfig, pubkey2index: PubkeyIndexMap, state: CachedBeaconStateAllForks, validatorIds?: (ValidatorIndex | string)[]): Promise<AttestationsRewards>;
8
- //# sourceMappingURL=attestationsRewards.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"attestationsRewards.d.ts","sourceRoot":"","sources":["../../../src/chain/rewards/attestationsRewards.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAC,MAAM,EAAC,MAAM,eAAe,CAAC;AACrC,OAAO,EAAC,YAAY,EAAC,MAAM,kBAAkB,CAAC;AAc9C,OAAO,EACL,yBAAyB,EAU1B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAC,cAAc,EAAC,MAAM,iBAAiB,CAAC;AAG/C,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC;AASpE,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,cAAc,EAC5B,KAAK,EAAE,yBAAyB,EAChC,YAAY,CAAC,EAAE,CAAC,cAAc,GAAG,MAAM,CAAC,EAAE,GACzC,OAAO,CAAC,mBAAmB,CAAC,CAyB9B"}