@lodestar/beacon-node 1.38.0 → 1.39.0-dev.3bf4734ba9

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 (137) hide show
  1. package/lib/api/impl/beacon/state/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/state/index.js +4 -5
  3. package/lib/api/impl/beacon/state/index.js.map +1 -1
  4. package/lib/api/impl/validator/index.js +1 -1
  5. package/lib/api/impl/validator/index.js.map +1 -1
  6. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  7. package/lib/chain/blocks/verifyBlock.js +1 -21
  8. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  9. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +1 -6
  10. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  11. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +10 -131
  12. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  13. package/lib/chain/blocks/verifyBlocksSignatures.d.ts +2 -2
  14. package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
  15. package/lib/chain/blocks/verifyBlocksSignatures.js +2 -2
  16. package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
  17. package/lib/chain/chain.d.ts.map +1 -1
  18. package/lib/chain/chain.js +4 -14
  19. package/lib/chain/chain.js.map +1 -1
  20. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  21. package/lib/chain/forkChoice/index.js +3 -3
  22. package/lib/chain/forkChoice/index.js.map +1 -1
  23. package/lib/chain/options.d.ts +0 -4
  24. package/lib/chain/options.d.ts.map +1 -1
  25. package/lib/chain/options.js +0 -2
  26. package/lib/chain/options.js.map +1 -1
  27. package/lib/chain/prepareNextSlot.js +1 -1
  28. package/lib/chain/prepareNextSlot.js.map +1 -1
  29. package/lib/chain/produceBlock/produceBlockBody.d.ts +2 -21
  30. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  31. package/lib/chain/produceBlock/produceBlockBody.js +24 -87
  32. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  33. package/lib/chain/rewards/attestationsRewards.d.ts +3 -3
  34. package/lib/chain/rewards/attestationsRewards.d.ts.map +1 -1
  35. package/lib/chain/rewards/attestationsRewards.js +4 -4
  36. package/lib/chain/rewards/attestationsRewards.js.map +1 -1
  37. package/lib/chain/rewards/syncCommitteeRewards.d.ts +2 -2
  38. package/lib/chain/rewards/syncCommitteeRewards.d.ts.map +1 -1
  39. package/lib/chain/rewards/syncCommitteeRewards.js +1 -2
  40. package/lib/chain/rewards/syncCommitteeRewards.js.map +1 -1
  41. package/lib/chain/validation/attesterSlashing.js +2 -2
  42. package/lib/chain/validation/attesterSlashing.js.map +1 -1
  43. package/lib/chain/validation/blobSidecar.d.ts.map +1 -1
  44. package/lib/chain/validation/blobSidecar.js +2 -2
  45. package/lib/chain/validation/blobSidecar.js.map +1 -1
  46. package/lib/chain/validation/block.d.ts.map +1 -1
  47. package/lib/chain/validation/block.js +3 -3
  48. package/lib/chain/validation/block.js.map +1 -1
  49. package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
  50. package/lib/chain/validation/dataColumnSidecar.js +2 -2
  51. package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
  52. package/lib/chain/validation/proposerSlashing.js +1 -1
  53. package/lib/chain/validation/proposerSlashing.js.map +1 -1
  54. package/lib/chain/validation/signatureSets/contributionAndProof.d.ts +2 -2
  55. package/lib/chain/validation/signatureSets/contributionAndProof.d.ts.map +1 -1
  56. package/lib/chain/validation/signatureSets/contributionAndProof.js +2 -3
  57. package/lib/chain/validation/signatureSets/contributionAndProof.js.map +1 -1
  58. package/lib/chain/validation/signatureSets/syncCommittee.d.ts +2 -2
  59. package/lib/chain/validation/signatureSets/syncCommittee.d.ts.map +1 -1
  60. package/lib/chain/validation/signatureSets/syncCommittee.js +2 -2
  61. package/lib/chain/validation/signatureSets/syncCommittee.js.map +1 -1
  62. package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.d.ts +2 -2
  63. package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.d.ts.map +1 -1
  64. package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.js +3 -3
  65. package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.js.map +1 -1
  66. package/lib/chain/validation/syncCommittee.js +1 -1
  67. package/lib/chain/validation/syncCommittee.js.map +1 -1
  68. package/lib/chain/validation/syncCommitteeContributionAndProof.d.ts.map +1 -1
  69. package/lib/chain/validation/syncCommitteeContributionAndProof.js +4 -3
  70. package/lib/chain/validation/syncCommitteeContributionAndProof.js.map +1 -1
  71. package/lib/chain/validation/voluntaryExit.js +1 -1
  72. package/lib/chain/validation/voluntaryExit.js.map +1 -1
  73. package/lib/eth1/index.d.ts +2 -17
  74. package/lib/eth1/index.d.ts.map +1 -1
  75. package/lib/eth1/index.js +0 -50
  76. package/lib/eth1/index.js.map +1 -1
  77. package/lib/eth1/interface.d.ts +1 -39
  78. package/lib/eth1/interface.d.ts.map +1 -1
  79. package/lib/execution/engine/http.d.ts +4 -12
  80. package/lib/execution/engine/http.d.ts.map +1 -1
  81. package/lib/execution/engine/http.js +4 -12
  82. package/lib/execution/engine/http.js.map +1 -1
  83. package/lib/execution/engine/mock.d.ts +2 -6
  84. package/lib/execution/engine/mock.d.ts.map +1 -1
  85. package/lib/execution/engine/mock.js +3 -14
  86. package/lib/execution/engine/mock.js.map +1 -1
  87. package/lib/metrics/metrics/lodestar.d.ts +0 -14
  88. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  89. package/lib/metrics/metrics/lodestar.js +0 -44
  90. package/lib/metrics/metrics/lodestar.js.map +1 -1
  91. package/lib/node/notifier.d.ts.map +1 -1
  92. package/lib/node/notifier.js +6 -22
  93. package/lib/node/notifier.js.map +1 -1
  94. package/lib/sync/backfill/backfill.d.ts.map +1 -1
  95. package/lib/sync/backfill/backfill.js +4 -2
  96. package/lib/sync/backfill/backfill.js.map +1 -1
  97. package/lib/sync/backfill/verify.d.ts +2 -2
  98. package/lib/sync/backfill/verify.d.ts.map +1 -1
  99. package/lib/sync/backfill/verify.js +3 -3
  100. package/lib/sync/backfill/verify.js.map +1 -1
  101. package/package.json +14 -15
  102. package/src/api/impl/beacon/state/index.ts +4 -5
  103. package/src/api/impl/validator/index.ts +1 -1
  104. package/src/chain/blocks/verifyBlock.ts +2 -24
  105. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +11 -170
  106. package/src/chain/blocks/verifyBlocksSignatures.ts +3 -2
  107. package/src/chain/chain.ts +4 -15
  108. package/src/chain/forkChoice/index.ts +2 -3
  109. package/src/chain/options.ts +0 -6
  110. package/src/chain/prepareNextSlot.ts +1 -1
  111. package/src/chain/produceBlock/produceBlockBody.ts +25 -120
  112. package/src/chain/rewards/attestationsRewards.ts +6 -5
  113. package/src/chain/rewards/syncCommitteeRewards.ts +2 -2
  114. package/src/chain/validation/attesterSlashing.ts +2 -2
  115. package/src/chain/validation/blobSidecar.ts +10 -2
  116. package/src/chain/validation/block.ts +2 -3
  117. package/src/chain/validation/dataColumnSidecar.ts +6 -1
  118. package/src/chain/validation/proposerSlashing.ts +1 -1
  119. package/src/chain/validation/signatureSets/contributionAndProof.ts +3 -2
  120. package/src/chain/validation/signatureSets/syncCommittee.ts +3 -1
  121. package/src/chain/validation/signatureSets/syncCommitteeSelectionProof.ts +4 -2
  122. package/src/chain/validation/syncCommittee.ts +1 -1
  123. package/src/chain/validation/syncCommitteeContributionAndProof.ts +4 -5
  124. package/src/chain/validation/voluntaryExit.ts +1 -1
  125. package/src/eth1/index.ts +2 -65
  126. package/src/eth1/interface.ts +1 -45
  127. package/src/execution/engine/http.ts +4 -12
  128. package/src/execution/engine/mock.ts +3 -15
  129. package/src/metrics/metrics/lodestar.ts +0 -52
  130. package/src/node/notifier.ts +7 -29
  131. package/src/sync/backfill/backfill.ts +9 -2
  132. package/src/sync/backfill/verify.ts +8 -2
  133. package/lib/eth1/eth1MergeBlockTracker.d.ts +0 -65
  134. package/lib/eth1/eth1MergeBlockTracker.d.ts.map +0 -1
  135. package/lib/eth1/eth1MergeBlockTracker.js +0 -262
  136. package/lib/eth1/eth1MergeBlockTracker.js.map +0 -1
  137. package/src/eth1/eth1MergeBlockTracker.ts +0 -328
@@ -17,10 +17,8 @@ import {
17
17
  CachedBeaconStateCapella,
18
18
  CachedBeaconStateExecutions,
19
19
  computeTimeAtSlot,
20
- getCurrentEpoch,
21
20
  getExpectedWithdrawals,
22
21
  getRandaoMix,
23
- isMergeTransitionComplete,
24
22
  } from "@lodestar/state-transition";
25
23
  import {
26
24
  BLSPubkey,
@@ -44,12 +42,9 @@ import {
44
42
  deneb,
45
43
  electra,
46
44
  fulu,
47
- ssz,
48
- sszTypesFor,
49
45
  } from "@lodestar/types";
50
46
  import {Logger, sleep, toHex, toPubkeyHex, toRootHex} from "@lodestar/utils";
51
- import {ZERO_HASH, ZERO_HASH_HEX} from "../../constants/index.js";
52
- import {IEth1ForBlockProduction} from "../../eth1/index.js";
47
+ import {ZERO_HASH_HEX} from "../../constants/index.js";
53
48
  import {numToQuantity} from "../../eth1/provider/utils.js";
54
49
  import {
55
50
  IExecutionBuilder,
@@ -337,14 +332,6 @@ export async function produceBlockBody<T extends BlockType>(
337
332
  feeRecipient
338
333
  );
339
334
 
340
- if (prepareRes.isPremerge) {
341
- return {
342
- ...prepareRes,
343
- executionPayload: sszTypesFor(fork).ExecutionPayload.defaultValue(),
344
- executionPayloadValue: BigInt(0),
345
- };
346
- }
347
-
348
335
  const {prepType, payloadId} = prepareRes;
349
336
  Object.assign(logMeta, {executionPayloadPrepType: prepType});
350
337
 
@@ -366,37 +353,14 @@ export async function produceBlockBody<T extends BlockType>(
366
353
 
367
354
  return {...prepareRes, ...payloadRes};
368
355
  })().catch((e) => {
369
- // catch payload fetch here, because there is still a recovery path possible if we
370
- // are pre-merge. We don't care the same for builder segment as the execution block
371
- // will takeover if the builder flow was activated and errors
372
356
  this.metrics?.blockPayload.payloadFetchErrors.inc();
373
-
374
- if (!isMergeTransitionComplete(currentState as CachedBeaconStateBellatrix)) {
375
- this.logger?.warn(
376
- "Fetch payload from the execution failed, however since we are still pre-merge proceeding with an empty one.",
377
- {},
378
- e as Error
379
- );
380
- // ok we don't have an execution payload here, so we can assign an empty one
381
- // if pre-merge
382
- return {
383
- isPremerge: true as const,
384
- executionPayload: sszTypesFor(fork).ExecutionPayload.defaultValue(),
385
- executionPayloadValue: BigInt(0),
386
- };
387
- }
388
- // since merge transition is complete, we need a valid payload even if with an
389
- // empty (transactions) one. defaultValue isn't gonna cut it!
390
357
  throw e;
391
358
  });
392
359
 
393
360
  const [engineRes, commonBlockBody] = await Promise.all([enginePromise, commonBlockBodyPromise]);
394
361
  blockBody = Object.assign({}, commonBlockBody) as AssembledBodyType<BlockType.Blinded>;
395
362
 
396
- if (engineRes.isPremerge) {
397
- (blockBody as BeaconBlockBody<ForkPostBellatrix & ForkPreGloas>).executionPayload = engineRes.executionPayload;
398
- executionPayloadValue = engineRes.executionPayloadValue;
399
- } else {
363
+ {
400
364
  const {prepType, payloadId, executionPayload, blobsBundle, executionRequests} = engineRes;
401
365
  shouldOverrideBuilder = engineRes.shouldOverrideBuilder;
402
366
 
@@ -504,15 +468,10 @@ export async function produceBlockBody<T extends BlockType>(
504
468
  }
505
469
 
506
470
  /**
507
- * Produce ExecutionPayload for pre-merge, merge, and post-merge.
508
- *
509
- * Expects `eth1MergeBlockFinder` to be actively searching for blocks well in advance to being called.
510
- *
511
- * @returns PayloadId = pow block found, null = pow NOT found
471
+ * Produce ExecutionPayload for post-merge.
512
472
  */
513
473
  export async function prepareExecutionPayload(
514
474
  chain: {
515
- eth1: IEth1ForBlockProduction;
516
475
  executionEngine: IExecutionEngine;
517
476
  config: ChainForkConfig;
518
477
  },
@@ -523,14 +482,8 @@ export async function prepareExecutionPayload(
523
482
  finalizedBlockHash: RootHex,
524
483
  state: CachedBeaconStateExecutions,
525
484
  suggestedFeeRecipient: string
526
- ): Promise<{isPremerge: true} | {isPremerge: false; prepType: PayloadPreparationType; payloadId: PayloadId}> {
527
- const parentHashRes = await getExecutionPayloadParentHash(chain, state);
528
- if (parentHashRes.isPremerge) {
529
- // Return null only if the execution is pre-merge
530
- return {isPremerge: true};
531
- }
532
-
533
- const {parentHash} = parentHashRes;
485
+ ): Promise<{prepType: PayloadPreparationType; payloadId: PayloadId}> {
486
+ const parentHash = state.latestExecutionPayloadHeader.blockHash;
534
487
  const timestamp = computeTimeAtSlot(chain.config, state.slot, state.genesisTime);
535
488
  const prevRandao = getRandaoMix(state, state.epochCtx.epoch);
536
489
 
@@ -586,12 +539,11 @@ export async function prepareExecutionPayload(
586
539
  // We are only returning payloadId here because prepareExecutionPayload is also called from
587
540
  // prepareNextSlot, which is an advance call to execution engine to start building payload
588
541
  // Actual payload isn't produced till getPayload is called.
589
- return {isPremerge: false, payloadId, prepType};
542
+ return {payloadId, prepType};
590
543
  }
591
544
 
592
545
  async function prepareExecutionPayloadHeader(
593
546
  chain: {
594
- eth1: IEth1ForBlockProduction;
595
547
  executionBuilder?: IExecutionBuilder;
596
548
  config: ChainForkConfig;
597
549
  },
@@ -608,53 +560,13 @@ async function prepareExecutionPayloadHeader(
608
560
  throw Error("executionBuilder required");
609
561
  }
610
562
 
611
- const parentHashRes = await getExecutionPayloadParentHash(chain, state);
612
- if (parentHashRes.isPremerge) {
613
- throw Error("External builder disabled pre-merge");
614
- }
615
-
616
- const {parentHash} = parentHashRes;
563
+ const parentHash = state.latestExecutionPayloadHeader.blockHash;
617
564
  return chain.executionBuilder.getHeader(fork, state.slot, parentHash, proposerPubKey);
618
565
  }
619
566
 
620
- export async function getExecutionPayloadParentHash(
621
- chain: {
622
- eth1: IEth1ForBlockProduction;
623
- config: ChainForkConfig;
624
- },
625
- state: CachedBeaconStateExecutions
626
- ): Promise<{isPremerge: true} | {isPremerge: false; parentHash: Root}> {
627
- // Use different POW block hash parent for block production based on merge status.
628
- // Returned value of null == using an empty ExecutionPayload value
629
- if (isMergeTransitionComplete(state)) {
630
- // Post-merge, normal payload
631
- return {isPremerge: false, parentHash: state.latestExecutionPayloadHeader.blockHash};
632
- }
633
-
634
- if (
635
- !ssz.Root.equals(chain.config.TERMINAL_BLOCK_HASH, ZERO_HASH) &&
636
- getCurrentEpoch(state) < chain.config.TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
637
- ) {
638
- throw new Error(
639
- `InvalidMergeTBH epoch: expected >= ${
640
- chain.config.TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
641
- }, actual: ${getCurrentEpoch(state)}`
642
- );
643
- }
644
-
645
- const terminalPowBlockHash = await chain.eth1.getTerminalPowBlock();
646
- if (terminalPowBlockHash === null) {
647
- // Pre-merge, no prepare payload call is needed
648
- return {isPremerge: true};
649
- }
650
- // Signify merge via producing on top of the last PoW block
651
- return {isPremerge: false, parentHash: terminalPowBlockHash};
652
- }
653
-
654
- export async function getPayloadAttributesForSSE(
567
+ export function getPayloadAttributesForSSE(
655
568
  fork: ForkPostBellatrix,
656
569
  chain: {
657
- eth1: IEth1ForBlockProduction;
658
570
  config: ChainForkConfig;
659
571
  },
660
572
  {
@@ -663,30 +575,23 @@ export async function getPayloadAttributesForSSE(
663
575
  parentBlockRoot,
664
576
  feeRecipient,
665
577
  }: {prepareState: CachedBeaconStateExecutions; prepareSlot: Slot; parentBlockRoot: Root; feeRecipient: string}
666
- ): Promise<SSEPayloadAttributes> {
667
- const parentHashRes = await getExecutionPayloadParentHash(chain, prepareState);
668
-
669
- if (!parentHashRes.isPremerge) {
670
- const {parentHash} = parentHashRes;
671
- const payloadAttributes = preparePayloadAttributes(fork, chain, {
672
- prepareState,
673
- prepareSlot,
674
- parentBlockRoot,
675
- feeRecipient,
676
- });
677
-
678
- const ssePayloadAttributes: SSEPayloadAttributes = {
679
- proposerIndex: prepareState.epochCtx.getBeaconProposer(prepareSlot),
680
- proposalSlot: prepareSlot,
681
- parentBlockNumber: prepareState.latestExecutionPayloadHeader.blockNumber,
682
- parentBlockRoot,
683
- parentBlockHash: parentHash,
684
- payloadAttributes,
685
- };
686
- return ssePayloadAttributes;
687
- }
688
-
689
- throw Error("The execution is still pre-merge");
578
+ ): SSEPayloadAttributes {
579
+ const parentHash = prepareState.latestExecutionPayloadHeader.blockHash;
580
+ const payloadAttributes = preparePayloadAttributes(fork, chain, {
581
+ prepareState,
582
+ prepareSlot,
583
+ parentBlockRoot,
584
+ feeRecipient,
585
+ });
586
+ const ssePayloadAttributes: SSEPayloadAttributes = {
587
+ proposerIndex: prepareState.epochCtx.getBeaconProposer(prepareSlot),
588
+ proposalSlot: prepareSlot,
589
+ parentBlockNumber: prepareState.latestExecutionPayloadHeader.blockNumber,
590
+ parentBlockRoot,
591
+ parentBlockHash: parentHash,
592
+ payloadAttributes,
593
+ };
594
+ return ssePayloadAttributes;
690
595
  }
691
596
 
692
597
  function preparePayloadAttributes(
@@ -1,5 +1,5 @@
1
+ import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
1
2
  import {routes} from "@lodestar/api";
2
- import {BeaconConfig} from "@lodestar/config";
3
3
  import {
4
4
  EFFECTIVE_BALANCE_INCREMENT,
5
5
  ForkName,
@@ -25,7 +25,7 @@ import {
25
25
  hasMarkers,
26
26
  isInInactivityLeak,
27
27
  } from "@lodestar/state-transition";
28
- import {Epoch, ValidatorIndex} from "@lodestar/types";
28
+ import {ValidatorIndex} from "@lodestar/types";
29
29
  import {fromHex} from "@lodestar/utils";
30
30
 
31
31
  export type AttestationsRewards = routes.beacon.AttestationsRewards;
@@ -38,9 +38,8 @@ const defaultAttestationsReward = {head: 0, target: 0, source: 0, inclusionDelay
38
38
  const defaultAttestationsPenalty = {target: 0, source: 0};
39
39
 
40
40
  export async function computeAttestationsRewards(
41
- _epoch: Epoch,
41
+ pubkey2index: PubkeyIndexMap,
42
42
  state: CachedBeaconStateAllForks,
43
- _config: BeaconConfig,
44
43
  validatorIds?: (ValidatorIndex | string)[]
45
44
  ): Promise<AttestationsRewards> {
46
45
  const fork = state.config.getForkName(state.slot);
@@ -53,6 +52,7 @@ export async function computeAttestationsRewards(
53
52
 
54
53
  const [idealRewards, penalties] = computeIdealAttestationsRewardsAndPenaltiesAltair(stateAltair, transitionCache);
55
54
  const totalRewards = computeTotalAttestationsRewardsAltair(
55
+ pubkey2index,
56
56
  stateAltair,
57
57
  transitionCache,
58
58
  idealRewards,
@@ -139,6 +139,7 @@ function computeIdealAttestationsRewardsAndPenaltiesAltair(
139
139
 
140
140
  // Same calculation as `getRewardsAndPenaltiesAltair` but returns the breakdown of rewards instead of aggregated
141
141
  function computeTotalAttestationsRewardsAltair(
142
+ pubkey2index: PubkeyIndexMap,
142
143
  state: CachedBeaconStateAltair,
143
144
  transitionCache: EpochTransitionCache,
144
145
  idealRewards: IdealAttestationsReward[],
@@ -149,7 +150,7 @@ function computeTotalAttestationsRewardsAltair(
149
150
  const {flags} = transitionCache;
150
151
  const {epochCtx, config} = state;
151
152
  const validatorIndices = validatorIds
152
- .map((id) => (typeof id === "number" ? id : epochCtx.pubkey2index.get(fromHex(id))))
153
+ .map((id) => (typeof id === "number" ? id : pubkey2index.get(fromHex(id))))
153
154
  .filter((index) => index !== undefined); // Validator indices to include in the result
154
155
 
155
156
  const inactivityPenaltyDenominator = config.INACTIVITY_SCORE_BIAS * INACTIVITY_PENALTY_QUOTIENT_ALTAIR;
@@ -1,12 +1,13 @@
1
1
  import {routes} from "@lodestar/api";
2
2
  import {ForkName, SYNC_COMMITTEE_SIZE} from "@lodestar/params";
3
- import {CachedBeaconStateAllForks, CachedBeaconStateAltair} from "@lodestar/state-transition";
3
+ import {CachedBeaconStateAllForks, CachedBeaconStateAltair, Index2PubkeyCache} from "@lodestar/state-transition";
4
4
  import {BeaconBlock, ValidatorIndex, altair} from "@lodestar/types";
5
5
 
6
6
  export type SyncCommitteeRewards = routes.beacon.SyncCommitteeRewards;
7
7
  type BalanceRecord = {val: number}; // Use val for convenient way to increment/decrement balance
8
8
 
9
9
  export async function computeSyncCommitteeRewards(
10
+ index2pubkey: Index2PubkeyCache,
10
11
  block: BeaconBlock,
11
12
  preState: CachedBeaconStateAllForks,
12
13
  validatorIds: (ValidatorIndex | string)[] = []
@@ -18,7 +19,6 @@ export async function computeSyncCommitteeRewards(
18
19
 
19
20
  const altairBlock = block as altair.BeaconBlock;
20
21
  const preStateAltair = preState as CachedBeaconStateAltair;
21
- const {index2pubkey} = preStateAltair.epochCtx;
22
22
 
23
23
  // Bound syncCommitteeValidatorIndices in case it goes beyond SYNC_COMMITTEE_SIZE just to be safe
24
24
  const syncCommitteeValidatorIndices = preStateAltair.epochCtx.currentSyncCommitteeIndexed.validatorIndices.slice(
@@ -43,7 +43,7 @@ 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(state, attesterSlashing, false);
46
+ assertValidAttesterSlashing(chain.index2pubkey, state, attesterSlashing, false);
47
47
  } catch (e) {
48
48
  throw new AttesterSlashingError(GossipAction.REJECT, {
49
49
  code: AttesterSlashingErrorCode.INVALID,
@@ -51,7 +51,7 @@ export async function validateAttesterSlashing(
51
51
  });
52
52
  }
53
53
 
54
- const signatureSets = getAttesterSlashingSignatureSets(state, attesterSlashing);
54
+ const signatureSets = getAttesterSlashingSignatureSets(chain.index2pubkey, state, attesterSlashing);
55
55
  if (!(await chain.bls.verifySignatureSets(signatureSets, {batchable: true, priority: prioritizeBls}))) {
56
56
  throw new AttesterSlashingError(GossipAction.REJECT, {
57
57
  code: AttesterSlashingErrorCode.INVALID,
@@ -137,7 +137,11 @@ export async function validateGossipBlobSidecar(
137
137
  // [REJECT] The proposer signature, signed_beacon_block.signature, is valid with respect to the proposer_index pubkey.
138
138
  const signature = blobSidecar.signedBlockHeader.signature;
139
139
  if (!chain.seenBlockInputCache.isVerifiedProposerSignature(blobSlot, blockHex, signature)) {
140
- const signatureSet = getBlockHeaderProposerSignatureSetByParentStateSlot(blockState, blobSidecar.signedBlockHeader);
140
+ const signatureSet = getBlockHeaderProposerSignatureSetByParentStateSlot(
141
+ chain.index2pubkey,
142
+ blockState,
143
+ blobSidecar.signedBlockHeader
144
+ );
141
145
  // Don't batch so verification is not delayed
142
146
  if (!(await chain.bls.verifySignatureSets([signatureSet], {verifyOnMainThread: true}))) {
143
147
  throw new BlobSidecarGossipError(GossipAction.REJECT, {
@@ -240,7 +244,11 @@ export async function validateBlockBlobSidecars(
240
244
  const signature = firstSidecarSignedBlockHeader.signature;
241
245
  if (!chain.seenBlockInputCache.isVerifiedProposerSignature(blockSlot, blockRootHex, signature)) {
242
246
  const headState = await chain.getHeadState();
243
- const signatureSet = getBlockHeaderProposerSignatureSetByHeaderSlot(headState, firstSidecarSignedBlockHeader);
247
+ const signatureSet = getBlockHeaderProposerSignatureSetByHeaderSlot(
248
+ chain.index2pubkey,
249
+ headState,
250
+ firstSidecarSignedBlockHeader
251
+ );
244
252
 
245
253
  if (
246
254
  !(await chain.bls.verifySignatureSets([signatureSet], {
@@ -6,7 +6,6 @@ import {
6
6
  computeTimeAtSlot,
7
7
  getBlockProposerSignatureSet,
8
8
  isExecutionBlockBodyType,
9
- isExecutionEnabled,
10
9
  isExecutionStateType,
11
10
  } from "@lodestar/state-transition";
12
11
  import {SignedBeaconBlock, deneb} from "@lodestar/types";
@@ -140,7 +139,7 @@ export async function validateGossipBlock(
140
139
  if (fork === ForkName.bellatrix) {
141
140
  if (!isExecutionBlockBodyType(block.body)) throw Error("Not merge block type");
142
141
  const executionPayload = block.body.executionPayload;
143
- if (isExecutionStateType(blockState) && isExecutionEnabled(blockState, block)) {
142
+ if (isExecutionStateType(blockState)) {
144
143
  const expectedTimestamp = computeTimeAtSlot(config, blockSlot, chain.genesisTime);
145
144
  if (executionPayload.timestamp !== computeTimeAtSlot(config, blockSlot, chain.genesisTime)) {
146
145
  throw new BlockGossipError(GossipAction.REJECT, {
@@ -154,7 +153,7 @@ export async function validateGossipBlock(
154
153
 
155
154
  // [REJECT] The proposer signature, signed_beacon_block.signature, is valid with respect to the proposer_index pubkey.
156
155
  if (!chain.seenBlockInputCache.isVerifiedProposerSignature(blockSlot, blockRoot, signedBlock.signature)) {
157
- const signatureSet = getBlockProposerSignatureSet(blockState, signedBlock);
156
+ const signatureSet = getBlockProposerSignatureSet(chain.index2pubkey, blockState, signedBlock);
158
157
  // Don't batch so verification is not delayed
159
158
  if (!(await chain.bls.verifySignatureSets([signatureSet], {verifyOnMainThread: true}))) {
160
159
  throw new BlockGossipError(GossipAction.REJECT, {
@@ -135,6 +135,7 @@ 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.index2pubkey,
138
139
  blockState,
139
140
  dataColumnSidecar.signedBlockHeader
140
141
  );
@@ -336,7 +337,11 @@ export async function validateBlockDataColumnSidecars(
336
337
  const signature = firstSidecarSignedBlockHeader.signature;
337
338
  if (!chain.seenBlockInputCache.isVerifiedProposerSignature(slot, rootHex, signature)) {
338
339
  const headState = await chain.getHeadState();
339
- const signatureSet = getBlockHeaderProposerSignatureSetByHeaderSlot(headState, firstSidecarSignedBlockHeader);
340
+ const signatureSet = getBlockHeaderProposerSignatureSetByHeaderSlot(
341
+ chain.index2pubkey,
342
+ headState,
343
+ firstSidecarSignedBlockHeader
344
+ );
340
345
 
341
346
  if (
342
347
  !(await chain.bls.verifySignatureSets([signatureSet], {
@@ -44,7 +44,7 @@ async function validateProposerSlashing(
44
44
  });
45
45
  }
46
46
 
47
- const signatureSets = getProposerSlashingSignatureSets(state, proposerSlashing);
47
+ const signatureSets = getProposerSlashingSignatureSets(chain.index2pubkey, state, proposerSlashing);
48
48
  if (!(await chain.bls.verifySignatureSets(signatureSets, {batchable: true, priority: prioritizeBls}))) {
49
49
  throw new ProposerSlashingError(GossipAction.REJECT, {
50
50
  code: ProposerSlashingErrorCode.INVALID,
@@ -2,16 +2,17 @@ import {DOMAIN_CONTRIBUTION_AND_PROOF} from "@lodestar/params";
2
2
  import {
3
3
  CachedBeaconStateAllForks,
4
4
  ISignatureSet,
5
+ Index2PubkeyCache,
5
6
  SignatureSetType,
6
7
  computeSigningRoot,
7
8
  } from "@lodestar/state-transition";
8
9
  import {altair, ssz} from "@lodestar/types";
9
10
 
10
11
  export function getContributionAndProofSignatureSet(
12
+ index2pubkey: Index2PubkeyCache,
11
13
  state: CachedBeaconStateAllForks,
12
14
  signedContributionAndProof: altair.SignedContributionAndProof
13
15
  ): ISignatureSet {
14
- const {epochCtx} = state;
15
16
  const domain = state.config.getDomain(
16
17
  state.slot,
17
18
  DOMAIN_CONTRIBUTION_AND_PROOF,
@@ -20,7 +21,7 @@ export function getContributionAndProofSignatureSet(
20
21
  const signingData = signedContributionAndProof.message;
21
22
  return {
22
23
  type: SignatureSetType.single,
23
- pubkey: epochCtx.index2pubkey[signedContributionAndProof.message.aggregatorIndex],
24
+ pubkey: index2pubkey[signedContributionAndProof.message.aggregatorIndex],
24
25
  signingRoot: computeSigningRoot(ssz.altair.ContributionAndProof, signingData, domain),
25
26
  signature: signedContributionAndProof.signature,
26
27
  };
@@ -2,12 +2,14 @@ import {DOMAIN_SYNC_COMMITTEE} from "@lodestar/params";
2
2
  import {
3
3
  CachedBeaconStateAllForks,
4
4
  ISignatureSet,
5
+ Index2PubkeyCache,
5
6
  SignatureSetType,
6
7
  computeSigningRoot,
7
8
  } from "@lodestar/state-transition";
8
9
  import {altair, ssz} from "@lodestar/types";
9
10
 
10
11
  export function getSyncCommitteeSignatureSet(
12
+ index2pubkey: Index2PubkeyCache,
11
13
  state: CachedBeaconStateAllForks,
12
14
  syncCommittee: altair.SyncCommitteeMessage
13
15
  ): ISignatureSet {
@@ -15,7 +17,7 @@ export function getSyncCommitteeSignatureSet(
15
17
 
16
18
  return {
17
19
  type: SignatureSetType.single,
18
- pubkey: state.epochCtx.index2pubkey[syncCommittee.validatorIndex],
20
+ pubkey: index2pubkey[syncCommittee.validatorIndex],
19
21
  signingRoot: computeSigningRoot(ssz.Root, syncCommittee.beaconBlockRoot, domain),
20
22
  signature: syncCommittee.signature,
21
23
  };
@@ -2,16 +2,18 @@ import {DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF} from "@lodestar/params";
2
2
  import {
3
3
  CachedBeaconStateAllForks,
4
4
  ISignatureSet,
5
+ Index2PubkeyCache,
5
6
  SignatureSetType,
6
7
  computeSigningRoot,
7
8
  } from "@lodestar/state-transition";
8
9
  import {altair, ssz} from "@lodestar/types";
9
10
 
10
11
  export function getSyncCommitteeSelectionProofSignatureSet(
12
+ index2pubkey: Index2PubkeyCache,
11
13
  state: CachedBeaconStateAllForks,
12
14
  contributionAndProof: altair.ContributionAndProof
13
15
  ): ISignatureSet {
14
- const {epochCtx, config} = state;
16
+ const {config} = state;
15
17
  const slot = contributionAndProof.contribution.slot;
16
18
  const domain = config.getDomain(state.slot, DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF, slot);
17
19
  const signingData: altair.SyncAggregatorSelectionData = {
@@ -20,7 +22,7 @@ export function getSyncCommitteeSelectionProofSignatureSet(
20
22
  };
21
23
  return {
22
24
  type: SignatureSetType.single,
23
- pubkey: epochCtx.index2pubkey[contributionAndProof.aggregatorIndex],
25
+ pubkey: index2pubkey[contributionAndProof.aggregatorIndex],
24
26
  signingRoot: computeSigningRoot(ssz.altair.SyncAggregatorSelectionData, signingData, domain),
25
27
  signature: contributionAndProof.selectionProof,
26
28
  };
@@ -89,7 +89,7 @@ async function validateSyncCommitteeSigOnly(
89
89
  syncCommittee: altair.SyncCommitteeMessage,
90
90
  prioritizeBls = false
91
91
  ): Promise<void> {
92
- const signatureSet = getSyncCommitteeSignatureSet(headState, syncCommittee);
92
+ const signatureSet = getSyncCommitteeSignatureSet(chain.index2pubkey, headState, syncCommittee);
93
93
  if (!(await chain.bls.verifySignatureSets([signatureSet], {batchable: true, priority: prioritizeBls}))) {
94
94
  throw new SyncCommitteeError(GossipAction.REJECT, {
95
95
  code: SyncCommitteeErrorCode.INVALID_SIGNATURE,
@@ -21,6 +21,7 @@ export async function validateSyncCommitteeGossipContributionAndProof(
21
21
  const contributionAndProof = signedContributionAndProof.message;
22
22
  const {contribution, aggregatorIndex} = contributionAndProof;
23
23
  const {subcommitteeIndex, slot} = contribution;
24
+ const {index2pubkey} = chain;
24
25
 
25
26
  const headState = chain.getHeadState();
26
27
  validateGossipSyncCommitteeExceptSig(chain, headState, subcommitteeIndex, {
@@ -73,16 +74,14 @@ export async function validateSyncCommitteeGossipContributionAndProof(
73
74
  // i.e. state.validators[contribution_and_proof.aggregator_index].pubkey in get_sync_subcommittee_pubkeys(state, contribution.subcommittee_index).
74
75
  // > Checked in validateGossipSyncCommitteeExceptSig()
75
76
 
76
- const participantPubkeys = syncCommitteeParticipantIndices.map(
77
- (validatorIndex) => headState.epochCtx.index2pubkey[validatorIndex]
78
- );
77
+ const participantPubkeys = syncCommitteeParticipantIndices.map((validatorIndex) => index2pubkey[validatorIndex]);
79
78
  const signatureSets = [
80
79
  // [REJECT] The contribution_and_proof.selection_proof is a valid signature of the SyncAggregatorSelectionData
81
80
  // derived from the contribution by the validator with index contribution_and_proof.aggregator_index.
82
- getSyncCommitteeSelectionProofSignatureSet(headState, contributionAndProof),
81
+ getSyncCommitteeSelectionProofSignatureSet(index2pubkey, headState, contributionAndProof),
83
82
 
84
83
  // [REJECT] The aggregator signature, signed_contribution_and_proof.signature, is valid.
85
- getContributionAndProofSignatureSet(headState, signedContributionAndProof),
84
+ getContributionAndProofSignatureSet(index2pubkey, headState, signedContributionAndProof),
86
85
 
87
86
  // [REJECT] The aggregate signature is valid for the message beacon_block_root and aggregate pubkey derived from
88
87
  // the participation info in aggregation_bits for the subcommittee specified by the contribution.subcommittee_index.
@@ -59,7 +59,7 @@ async function validateVoluntaryExit(
59
59
  });
60
60
  }
61
61
 
62
- const signatureSet = getVoluntaryExitSignatureSet(state, voluntaryExit);
62
+ const signatureSet = getVoluntaryExitSignatureSet(chain.index2pubkey, state, 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,
package/src/eth1/index.ts CHANGED
@@ -1,9 +1,6 @@
1
1
  import {CachedBeaconStateAllForks} from "@lodestar/state-transition";
2
- import {Root} from "@lodestar/types";
3
- import {fromHex} from "@lodestar/utils";
4
2
  import {Eth1DepositDataTracker, Eth1DepositDataTrackerModules} from "./eth1DepositDataTracker.js";
5
- import {Eth1MergeBlockTracker, Eth1MergeBlockTrackerModules} from "./eth1MergeBlockTracker.js";
6
- import {Eth1DataAndDeposits, IEth1ForBlockProduction, IEth1Provider, PowMergeBlock, TDProgress} from "./interface.js";
3
+ import {Eth1DataAndDeposits, IEth1ForBlockProduction, IEth1Provider} from "./interface.js";
7
4
  import {Eth1Options} from "./options.js";
8
5
  import {Eth1Provider} from "./provider/eth1Provider.js";
9
6
  export {Eth1Provider};
@@ -23,23 +20,6 @@ export type {IEth1ForBlockProduction, IEth1Provider};
23
20
  //
24
21
  // - Fetch ALL deposit events from the deposit contract to build the deposit tree and validate future merkle proofs.
25
22
  // Then it must follow deposit events at a distance roughly similar to the `ETH1_FOLLOW_DISTANCE` parameter above.
26
- //
27
- // - [New bellatrix]: After BELLATRIX_FORK_EPOCH, it must fetch the block with hash
28
- // `state.eth1_data.block_hash` to compute `terminal_total_difficulty`. Note this may change with
29
- // https://github.com/ethereum/consensus-specs/issues/2603.
30
- //
31
- // - [New bellatrix]: On block production post BELLATRIX_FORK_EPOCH, pre merge, the beacon node must find the merge block
32
- // crossing the `terminal_total_difficulty` boundary and include it in the block. After the merge block production
33
- // will just use `execution_engine.assemble_block` without fetching individual blocks.
34
- //
35
- // - [New bellatrix]: Fork-choice must validate the merge block ensuring it crossed the `terminal_total_difficulty`
36
- // boundary, so it must fetch the POW block referenced in the merge block + its POW parent block.
37
- //
38
- // With the merge the beacon node has to follow the eth1 chain at two distances:
39
- // 1. At `ETH1_FOLLOW_DISTANCE` for eth1Data to be re-org safe
40
- // 2. At the head to get the first merge block, tolerating possible re-orgs
41
- //
42
- // Then both streams of blocks should not be merged since it's harder to guard against re-orgs from (2) to (1).
43
23
 
44
24
  export function initializeEth1ForBlockProduction(
45
25
  opts: Eth1Options,
@@ -59,12 +39,8 @@ export function initializeEth1ForBlockProduction(
59
39
 
60
40
  export class Eth1ForBlockProduction implements IEth1ForBlockProduction {
61
41
  private readonly eth1DepositDataTracker: Eth1DepositDataTracker | null;
62
- private readonly eth1MergeBlockTracker: Eth1MergeBlockTracker;
63
42
 
64
- constructor(
65
- opts: Eth1Options,
66
- modules: Eth1DepositDataTrackerModules & Eth1MergeBlockTrackerModules & {eth1Provider?: IEth1Provider}
67
- ) {
43
+ constructor(opts: Eth1Options, modules: Eth1DepositDataTrackerModules & {eth1Provider?: IEth1Provider}) {
68
44
  const eth1Provider =
69
45
  modules.eth1Provider ||
70
46
  new Eth1Provider(
@@ -77,8 +53,6 @@ export class Eth1ForBlockProduction implements IEth1ForBlockProduction {
77
53
  this.eth1DepositDataTracker = opts.disableEth1DepositDataTracker
78
54
  ? null
79
55
  : new Eth1DepositDataTracker(opts, modules, eth1Provider);
80
-
81
- this.eth1MergeBlockTracker = new Eth1MergeBlockTracker(modules, eth1Provider);
82
56
  }
83
57
 
84
58
  async getEth1DataAndDeposits(state: CachedBeaconStateAllForks): Promise<Eth1DataAndDeposits> {
@@ -88,23 +62,6 @@ export class Eth1ForBlockProduction implements IEth1ForBlockProduction {
88
62
  return this.eth1DepositDataTracker.getEth1DataAndDeposits(state);
89
63
  }
90
64
 
91
- async getTerminalPowBlock(): Promise<Root | null> {
92
- const block = await this.eth1MergeBlockTracker.getTerminalPowBlock();
93
- return block && fromHex(block.blockHash);
94
- }
95
-
96
- getPowBlock(powBlockHash: string): Promise<PowMergeBlock | null> {
97
- return this.eth1MergeBlockTracker.getPowBlock(powBlockHash);
98
- }
99
-
100
- getTDProgress(): TDProgress | null {
101
- return this.eth1MergeBlockTracker.getTDProgress();
102
- }
103
-
104
- startPollingMergeBlock(): void {
105
- this.eth1MergeBlockTracker.startPollingMergeBlock();
106
- }
107
-
108
65
  isPollingEth1Data(): boolean {
109
66
  return this.eth1DepositDataTracker?.isPollingEth1Data() ?? false;
110
67
  }
@@ -127,30 +84,10 @@ export class Eth1ForBlockProductionDisabled implements IEth1ForBlockProduction {
127
84
  return {eth1Data: state.eth1Data, deposits: []};
128
85
  }
129
86
 
130
- /**
131
- * Will miss the oportunity to propose the merge block but will still produce valid blocks
132
- */
133
- async getTerminalPowBlock(): Promise<Root | null> {
134
- return null;
135
- }
136
-
137
- /** Will not be able to validate the merge block */
138
- async getPowBlock(_powBlockHash: string): Promise<PowMergeBlock | null> {
139
- throw Error("eth1 must be enabled to verify merge block");
140
- }
141
-
142
- getTDProgress(): TDProgress | null {
143
- return null;
144
- }
145
-
146
87
  isPollingEth1Data(): boolean {
147
88
  return false;
148
89
  }
149
90
 
150
- startPollingMergeBlock(): void {
151
- // Ignore
152
- }
153
-
154
91
  stopPollingEth1Data(): void {
155
92
  // Ignore
156
93
  }