@lodestar/beacon-node 1.38.0-dev.8475d71f09 → 1.38.0-dev.889b1c4475

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 (138) hide show
  1. package/README.md +1 -1
  2. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  3. package/lib/api/impl/beacon/state/utils.js +5 -3
  4. package/lib/api/impl/beacon/state/utils.js.map +1 -1
  5. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  6. package/lib/chain/blocks/verifyBlock.js +1 -21
  7. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  8. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +1 -6
  9. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  10. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +10 -131
  11. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  12. package/lib/chain/blocks/verifyBlocksSignatures.d.ts +2 -2
  13. package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
  14. package/lib/chain/blocks/verifyBlocksSignatures.js +2 -2
  15. package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
  16. package/lib/chain/chain.d.ts.map +1 -1
  17. package/lib/chain/chain.js +3 -13
  18. package/lib/chain/chain.js.map +1 -1
  19. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  20. package/lib/chain/forkChoice/index.js +3 -3
  21. package/lib/chain/forkChoice/index.js.map +1 -1
  22. package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
  23. package/lib/chain/opPools/aggregatedAttestationPool.js +3 -1
  24. package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
  25. package/lib/chain/options.d.ts +0 -4
  26. package/lib/chain/options.d.ts.map +1 -1
  27. package/lib/chain/options.js +0 -2
  28. package/lib/chain/options.js.map +1 -1
  29. package/lib/chain/prepareNextSlot.js +1 -1
  30. package/lib/chain/prepareNextSlot.js.map +1 -1
  31. package/lib/chain/produceBlock/produceBlockBody.d.ts +2 -21
  32. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  33. package/lib/chain/produceBlock/produceBlockBody.js +24 -87
  34. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  35. package/lib/chain/rewards/syncCommitteeRewards.d.ts +2 -2
  36. package/lib/chain/rewards/syncCommitteeRewards.d.ts.map +1 -1
  37. package/lib/chain/rewards/syncCommitteeRewards.js +1 -2
  38. package/lib/chain/rewards/syncCommitteeRewards.js.map +1 -1
  39. package/lib/chain/validation/attesterSlashing.js +2 -2
  40. package/lib/chain/validation/attesterSlashing.js.map +1 -1
  41. package/lib/chain/validation/blobSidecar.d.ts.map +1 -1
  42. package/lib/chain/validation/blobSidecar.js +2 -2
  43. package/lib/chain/validation/blobSidecar.js.map +1 -1
  44. package/lib/chain/validation/block.d.ts.map +1 -1
  45. package/lib/chain/validation/block.js +3 -3
  46. package/lib/chain/validation/block.js.map +1 -1
  47. package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
  48. package/lib/chain/validation/dataColumnSidecar.js +2 -2
  49. package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
  50. package/lib/chain/validation/proposerSlashing.js +1 -1
  51. package/lib/chain/validation/proposerSlashing.js.map +1 -1
  52. package/lib/chain/validation/signatureSets/contributionAndProof.d.ts +2 -2
  53. package/lib/chain/validation/signatureSets/contributionAndProof.d.ts.map +1 -1
  54. package/lib/chain/validation/signatureSets/contributionAndProof.js +2 -3
  55. package/lib/chain/validation/signatureSets/contributionAndProof.js.map +1 -1
  56. package/lib/chain/validation/signatureSets/syncCommittee.d.ts +2 -2
  57. package/lib/chain/validation/signatureSets/syncCommittee.d.ts.map +1 -1
  58. package/lib/chain/validation/signatureSets/syncCommittee.js +2 -2
  59. package/lib/chain/validation/signatureSets/syncCommittee.js.map +1 -1
  60. package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.d.ts +2 -2
  61. package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.d.ts.map +1 -1
  62. package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.js +3 -3
  63. package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.js.map +1 -1
  64. package/lib/chain/validation/syncCommittee.js +1 -1
  65. package/lib/chain/validation/syncCommittee.js.map +1 -1
  66. package/lib/chain/validation/syncCommitteeContributionAndProof.d.ts.map +1 -1
  67. package/lib/chain/validation/syncCommitteeContributionAndProof.js +4 -3
  68. package/lib/chain/validation/syncCommitteeContributionAndProof.js.map +1 -1
  69. package/lib/chain/validation/voluntaryExit.js +1 -1
  70. package/lib/chain/validation/voluntaryExit.js.map +1 -1
  71. package/lib/eth1/index.d.ts +2 -17
  72. package/lib/eth1/index.d.ts.map +1 -1
  73. package/lib/eth1/index.js +0 -50
  74. package/lib/eth1/index.js.map +1 -1
  75. package/lib/eth1/interface.d.ts +1 -39
  76. package/lib/eth1/interface.d.ts.map +1 -1
  77. package/lib/execution/engine/http.d.ts +4 -12
  78. package/lib/execution/engine/http.d.ts.map +1 -1
  79. package/lib/execution/engine/http.js +4 -12
  80. package/lib/execution/engine/http.js.map +1 -1
  81. package/lib/execution/engine/mock.d.ts +2 -6
  82. package/lib/execution/engine/mock.d.ts.map +1 -1
  83. package/lib/execution/engine/mock.js +3 -14
  84. package/lib/execution/engine/mock.js.map +1 -1
  85. package/lib/metrics/metrics/lodestar.d.ts +0 -14
  86. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  87. package/lib/metrics/metrics/lodestar.js +0 -44
  88. package/lib/metrics/metrics/lodestar.js.map +1 -1
  89. package/lib/network/gossip/encoding.d.ts.map +1 -1
  90. package/lib/network/gossip/encoding.js +17 -7
  91. package/lib/network/gossip/encoding.js.map +1 -1
  92. package/lib/node/notifier.d.ts.map +1 -1
  93. package/lib/node/notifier.js +6 -22
  94. package/lib/node/notifier.js.map +1 -1
  95. package/lib/sync/backfill/backfill.d.ts.map +1 -1
  96. package/lib/sync/backfill/backfill.js +4 -2
  97. package/lib/sync/backfill/backfill.js.map +1 -1
  98. package/lib/sync/backfill/verify.d.ts +2 -2
  99. package/lib/sync/backfill/verify.d.ts.map +1 -1
  100. package/lib/sync/backfill/verify.js +3 -3
  101. package/lib/sync/backfill/verify.js.map +1 -1
  102. package/package.json +15 -16
  103. package/src/api/impl/beacon/state/utils.ts +5 -3
  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 +3 -14
  108. package/src/chain/forkChoice/index.ts +2 -3
  109. package/src/chain/opPools/aggregatedAttestationPool.ts +5 -1
  110. package/src/chain/options.ts +0 -6
  111. package/src/chain/prepareNextSlot.ts +1 -1
  112. package/src/chain/produceBlock/produceBlockBody.ts +25 -120
  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/network/gossip/encoding.ts +19 -7
  131. package/src/node/notifier.ts +7 -29
  132. package/src/sync/backfill/backfill.ts +9 -2
  133. package/src/sync/backfill/verify.ts +8 -2
  134. package/lib/eth1/eth1MergeBlockTracker.d.ts +0 -65
  135. package/lib/eth1/eth1MergeBlockTracker.d.ts.map +0 -1
  136. package/lib/eth1/eth1MergeBlockTracker.js +0 -262
  137. package/lib/eth1/eth1MergeBlockTracker.js.map +0 -1
  138. package/src/eth1/eth1MergeBlockTracker.ts +0 -328
@@ -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
  }
@@ -1,6 +1,6 @@
1
1
  import {BeaconConfig} from "@lodestar/config";
2
2
  import {CachedBeaconStateAllForks} from "@lodestar/state-transition";
3
- import {Root, RootHex, phase0} from "@lodestar/types";
3
+ import {phase0} from "@lodestar/types";
4
4
 
5
5
  export type EthJsonRpcBlockRaw = {
6
6
  /** the block number. null when its pending block. `"0x1b4"` */
@@ -47,22 +47,6 @@ export type Eth1DataAndDeposits = {
47
47
  export interface IEth1ForBlockProduction {
48
48
  getEth1DataAndDeposits(state: CachedBeaconStateAllForks): Promise<Eth1DataAndDeposits>;
49
49
 
50
- /** Returns the most recent POW block that satisfies the merge block condition */
51
- getTerminalPowBlock(): Promise<Root | null>;
52
- /** Get a POW block by hash checking the local cache first */
53
- getPowBlock(powBlockHash: string): Promise<PowMergeBlock | null>;
54
-
55
- /** Get current TD progress for log notifier */
56
- getTDProgress(): TDProgress | null;
57
-
58
- /**
59
- * Should only start polling for mergeBlock if:
60
- * - after BELLATRIX_FORK_EPOCH
61
- * - Beacon node synced
62
- * - head state not isMergeTransitionComplete
63
- */
64
- startPollingMergeBlock(): void;
65
-
66
50
  isPollingEth1Data(): boolean;
67
51
 
68
52
  /**
@@ -78,34 +62,6 @@ export type Eth1Block = {
78
62
  timestamp: number;
79
63
  };
80
64
 
81
- export type PowMergeBlock = {
82
- number: number;
83
- blockHash: RootHex;
84
- parentHash: RootHex;
85
- totalDifficulty: bigint;
86
- };
87
-
88
- export type PowMergeBlockTimestamp = PowMergeBlock & {
89
- /** in seconds */
90
- timestamp: number;
91
- };
92
-
93
- export type TDProgress =
94
- | {
95
- ttdHit: false;
96
- /** Power of ten by which tdDiffScaled is scaled down */
97
- tdFactor: bigint;
98
- /** (TERMINAL_TOTAL_DIFFICULTY - block.totalDifficulty) / tdFactor */
99
- tdDiffScaled: number;
100
- /** TERMINAL_TOTAL_DIFFICULTY */
101
- ttd: bigint;
102
- /** totalDifficulty of latest fetched eth1 block */
103
- td: bigint;
104
- /** timestamp in sec of latest fetched eth1 block */
105
- timestamp: number;
106
- }
107
- | {ttdHit: true};
108
-
109
65
  export type BatchDepositEvents = {
110
66
  depositEvents: phase0.DepositEvent[];
111
67
  blockNumber: number;
@@ -194,15 +194,12 @@ export class ExecutionEngineHttp implements IExecutionEngine {
194
194
  * 1. {status: INVALID_BLOCK_HASH, latestValidHash: null, validationError:
195
195
  * errorMessage | null} if the blockHash validation has failed
196
196
  *
197
- * 2. {status: INVALID_TERMINAL_BLOCK, latestValidHash: null, validationError:
198
- * errorMessage | null} if terminal block conditions are not satisfied
199
- *
200
- * 3. {status: SYNCING, latestValidHash: null, validationError: null} if the payload
197
+ * 2. {status: SYNCING, latestValidHash: null, validationError: null} if the payload
201
198
  * extends the canonical chain and requisite data for its validation is missing
202
199
  * with the payload status obtained from the Payload validation process if the payload
203
200
  * has been fully validated while processing the call
204
201
  *
205
- * 4. {status: ACCEPTED, latestValidHash: null, validationError: null} if the
202
+ * 3. {status: ACCEPTED, latestValidHash: null, validationError: null} if the
206
203
  * following conditions are met:
207
204
  * i) the blockHash of the payload is valid
208
205
  * ii) the payload doesn't extend the canonical chain
@@ -330,16 +327,11 @@ export class ExecutionEngineHttp implements IExecutionEngine {
330
327
  * errorMessage | null}, payloadId: null}
331
328
  * obtained from the Payload validation process if the payload is deemed INVALID
332
329
  *
333
- * 3. {payloadStatus: {status: INVALID_TERMINAL_BLOCK, latestValidHash: null,
334
- * validationError: errorMessage | null}, payloadId: null}
335
- * either obtained from the Payload validation process or as a result of validating a
336
- * PoW block referenced by forkchoiceState.headBlockHash
337
- *
338
- * 4. {payloadStatus: {status: VALID, latestValidHash: forkchoiceState.headBlockHash,
330
+ * 3. {payloadStatus: {status: VALID, latestValidHash: forkchoiceState.headBlockHash,
339
331
  * validationError: null}, payloadId: null}
340
332
  * if the payload is deemed VALID and a build process hasn't been started
341
333
  *
342
- * 5. {payloadStatus: {status: VALID, latestValidHash: forkchoiceState.headBlockHash,
334
+ * 4. {payloadStatus: {status: VALID, latestValidHash: forkchoiceState.headBlockHash,
343
335
  * validationError: null}, payloadId: buildProcessId}
344
336
  * if the payload is deemed VALID and the build process has begun.
345
337
  *
@@ -9,7 +9,7 @@ import {
9
9
  ForkSeq,
10
10
  } from "@lodestar/params";
11
11
  import {ExecutionPayload, RootHex, bellatrix, deneb, ssz} from "@lodestar/types";
12
- import {fromHex, toHex, toRootHex} from "@lodestar/utils";
12
+ import {fromHex, toRootHex} from "@lodestar/utils";
13
13
  import {ZERO_HASH_HEX} from "../../constants/index.js";
14
14
  import {quantityToNum} from "../../eth1/provider/utils.js";
15
15
  import {INTEROP_BLOCK_HASH} from "../../node/utils/interop/state.js";
@@ -70,7 +70,7 @@ export class ExecutionEngineMockBackend implements JsonRpcBackend {
70
70
  finalizedBlockHash = ZERO_HASH_HEX;
71
71
  readonly payloadIdCache = new PayloadIdCache();
72
72
 
73
- /** Known valid blocks, both pre-merge and post-merge */
73
+ /** Known valid blocks */
74
74
  private readonly validBlocks = new Map<RootHex, ExecutionBlock>();
75
75
  /** Preparing payloads to be retrieved via engine_getPayloadV1 */
76
76
  private readonly preparingPayloads = new Map<number, PreparedPayload>();
@@ -135,18 +135,6 @@ export class ExecutionEngineMockBackend implements JsonRpcBackend {
135
135
  return [] as ExecutionPayloadBodyRpc[];
136
136
  }
137
137
 
138
- /**
139
- * Mock manipulator to add more known blocks to this mock.
140
- */
141
- addPowBlock(powBlock: bellatrix.PowBlock): void {
142
- this.validBlocks.set(toHex(powBlock.blockHash), {
143
- parentHash: toHex(powBlock.parentHash),
144
- blockHash: toHex(powBlock.blockHash),
145
- timestamp: 0,
146
- blockNumber: 0,
147
- });
148
- }
149
-
150
138
  /**
151
139
  * Mock manipulator to add predefined responses before execution engine client calls
152
140
  */
@@ -258,7 +246,7 @@ export class ExecutionEngineMockBackend implements JsonRpcBackend {
258
246
  // section of the EIP. Additionally, if this validation fails, client software MUST NOT update the forkchoice
259
247
  // state and MUST NOT begin a payload build process.
260
248
  //
261
- // > TODO
249
+ // > N/A: All networks have completed the merge transition
262
250
 
263
251
  // 4. Before updating the forkchoice state, client software MUST ensure the validity of the payload referenced by
264
252
  // forkchoiceState.headBlockHash, and MAY validate the payload while processing the call. The validation process
@@ -1668,58 +1668,6 @@ export function createLodestarMetrics(
1668
1668
  name: "lodestar_eth1_logs_batch_size_dynamic",
1669
1669
  help: "Dynamic batch size to fetch deposit logs",
1670
1670
  }),
1671
-
1672
- // Merge Search info
1673
- eth1MergeStatus: register.gauge({
1674
- name: "lodestar_eth1_merge_status",
1675
- help: "Eth1 Merge Status 0 PRE_MERGE 1 SEARCHING 2 FOUND 3 POST_MERGE",
1676
- }),
1677
- eth1MergeTDFactor: register.gauge({
1678
- name: "lodestar_eth1_merge_td_factor",
1679
- help: "TTD set for the merge",
1680
- }),
1681
- eth1MergeTTD: register.gauge({
1682
- name: "lodestar_eth1_merge_ttd",
1683
- help: "TTD set for the merge scaled down by td_factor",
1684
- }),
1685
-
1686
- eth1PollMergeBlockErrors: register.gauge({
1687
- name: "lodestar_eth1_poll_merge_block_errors_total",
1688
- help: "Total count of errors polling merge block",
1689
- }),
1690
- getTerminalPowBlockPromiseCacheHit: register.gauge({
1691
- name: "lodestar_eth1_get_terminal_pow_block_promise_cache_hit_total",
1692
- help: "Total count of skipped runs in poll merge block, because a previous promise existed",
1693
- }),
1694
- eth1ParentBlocksFetched: register.gauge({
1695
- name: "lodestar_eth1_parent_blocks_fetched_total",
1696
- help: "Total count of parent blocks fetched searching for merge block",
1697
- }),
1698
-
1699
- // Latest block details
1700
- eth1LatestBlockTD: register.gauge({
1701
- name: "lodestar_eth1_latest_block_ttd",
1702
- help: "Eth1 latest Block td scaled down by td_factor",
1703
- }),
1704
- eth1LatestBlockNumber: register.gauge({
1705
- name: "lodestar_eth1_latest_block_number",
1706
- help: "Eth1 latest block number",
1707
- }),
1708
- eth1LatestBlockTimestamp: register.gauge({
1709
- name: "lodestar_eth1_latest_block_timestamp",
1710
- help: "Eth1 latest block timestamp",
1711
- }),
1712
-
1713
- // Merge details
1714
- eth1MergeBlockDetails: register.gauge<{
1715
- terminalBlockHash: string;
1716
- terminalBlockNumber: string;
1717
- terminalBlockTD: string;
1718
- }>({
1719
- name: "lodestar_eth1_merge_block_details",
1720
- help: "If found then 1 with terminal block details",
1721
- labelNames: ["terminalBlockHash", "terminalBlockNumber", "terminalBlockTD"],
1722
- }),
1723
1671
  },
1724
1672
 
1725
1673
  eth1HttpClient: {
@@ -1,10 +1,10 @@
1
1
  import {Message} from "@libp2p/interface";
2
2
  // snappyjs is better for compression for smaller payloads
3
- import {compress, uncompress} from "snappyjs";
4
3
  import xxhashFactory from "xxhash-wasm";
5
4
  import {digest} from "@chainsafe/as-sha256";
6
5
  import {RPC} from "@chainsafe/libp2p-gossipsub/message";
7
6
  import {DataTransform} from "@chainsafe/libp2p-gossipsub/types";
7
+ import snappyWasm from "@chainsafe/snappy-wasm";
8
8
  import {ForkName} from "@lodestar/params";
9
9
  import {intToBytes} from "@lodestar/utils";
10
10
  import {MESSAGE_DOMAIN_VALID_SNAPPY} from "./constants.js";
@@ -17,6 +17,10 @@ const xxhash = await xxhashFactory();
17
17
  // Use salt to prevent msgId from being mined for collisions
18
18
  const h64Seed = BigInt(Math.floor(Math.random() * 1e9));
19
19
 
20
+ // create singleton snappy encoder + decoder
21
+ const encoder = new snappyWasm.Encoder();
22
+ const decoder = new snappyWasm.Decoder();
23
+
20
24
  // Shared buffer to convert msgId to string
21
25
  const sharedMsgIdBuf = Buffer.alloc(20);
22
26
 
@@ -82,11 +86,12 @@ export class DataTransformSnappy implements DataTransform {
82
86
  * - `outboundTransform()`: compress snappy payload
83
87
  */
84
88
  inboundTransform(topicStr: string, data: Uint8Array): Uint8Array {
85
- const uncompressedData = uncompress(data, this.maxSizePerMessage);
89
+ // check uncompressed data length before we actually decompress
90
+ const uncompressedDataLength = snappyWasm.decompress_len(data);
91
+ if (uncompressedDataLength > this.maxSizePerMessage) {
92
+ throw Error(`ssz_snappy decoded data length ${uncompressedDataLength} > ${this.maxSizePerMessage}`);
93
+ }
86
94
 
87
- // check uncompressed data length before we extract beacon block root, slot or
88
- // attestation data at later steps
89
- const uncompressedDataLength = uncompressedData.length;
90
95
  const topic = this.gossipTopicCache.getTopic(topicStr);
91
96
  const sszType = getGossipSSZType(topic);
92
97
  this.metrics?.dataTransform.inbound.inc({type: topic.type});
@@ -98,6 +103,10 @@ export class DataTransformSnappy implements DataTransform {
98
103
  throw Error(`ssz_snappy decoded data length ${uncompressedDataLength} > ${sszType.maxSize}`);
99
104
  }
100
105
 
106
+ // Only after sanity length checks, we can decompress the data
107
+ // Using Buffer.alloc() instead of Buffer.allocUnsafe() to mitigate high GC pressure observed in some environments
108
+ const uncompressedData = Buffer.alloc(uncompressedDataLength);
109
+ decoder.decompress_into(data, uncompressedData);
101
110
  return uncompressedData;
102
111
  }
103
112
 
@@ -111,7 +120,10 @@ export class DataTransformSnappy implements DataTransform {
111
120
  if (data.length > this.maxSizePerMessage) {
112
121
  throw Error(`ssz_snappy encoded data length ${data.length} > ${this.maxSizePerMessage}`);
113
122
  }
114
- // No need to parse topic, everything is snappy compressed
115
- return compress(data);
123
+
124
+ // Using Buffer.alloc() instead of Buffer.allocUnsafe() to mitigate high GC pressure observed in some environments
125
+ const compressedData = Buffer.alloc(snappyWasm.max_compress_len(data.length));
126
+ const compressedLen = encoder.compress_into(data, compressedData);
127
+ return compressedData.subarray(0, compressedLen);
116
128
  }
117
129
  }