@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
@@ -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: {
@@ -6,7 +6,6 @@ import {
6
6
  computeEpochAtSlot,
7
7
  computeStartSlotAtEpoch,
8
8
  isExecutionCachedStateType,
9
- isMergeTransitionComplete,
10
9
  } from "@lodestar/state-transition";
11
10
  import {Epoch} from "@lodestar/types";
12
11
  import {ErrorAborted, Logger, prettyBytes, prettyBytesShort, sleep} from "@lodestar/utils";
@@ -36,7 +35,6 @@ export async function runNodeNotifier(modules: NodeNotifierModules): Promise<voi
36
35
  const {network, chain, sync, config, logger, signal} = modules;
37
36
 
38
37
  const headSlotTimeSeries = new TimeSeries({maxPoints: 10});
39
- const tdTimeSeries = new TimeSeries({maxPoints: 50});
40
38
 
41
39
  const SLOTS_PER_SYNC_COMMITTEE_PERIOD = SLOTS_PER_EPOCH * EPOCHS_PER_SYNC_COMMITTEE_PERIOD;
42
40
  let hasLowPeerCount = false;
@@ -87,21 +85,6 @@ export async function runNodeNotifier(modules: NodeNotifierModules): Promise<voi
87
85
  const executionInfo = getHeadExecutionInfo(config, clockEpoch, headState, headInfo);
88
86
  const finalizedCheckpointRow = `finalized: ${prettyBytes(finalizedRoot)}:${finalizedEpoch}`;
89
87
 
90
- // Log in TD progress in separate line to not clutter regular status update.
91
- // This line will only exist between BELLATRIX_FORK_EPOCH and TTD, a window of some days / weeks max.
92
- // Notifier log lines must be kept at a reasonable max width otherwise it's very hard to read
93
- const tdProgress = chain.eth1.getTDProgress();
94
- if (tdProgress !== null && !tdProgress.ttdHit) {
95
- tdTimeSeries.addPoint(tdProgress.tdDiffScaled, tdProgress.timestamp);
96
-
97
- const timestampTDD = tdTimeSeries.computeY0Point();
98
- // It is possible to get ttd estimate with an error at imminent merge
99
- const secToTTD = Math.max(Math.floor(timestampTDD - Date.now() / 1000), 0);
100
- const timeLeft = Number.isFinite(secToTTD) ? prettyTimeDiffSec(secToTTD) : "?";
101
-
102
- logger.info(`TTD in ${timeLeft} current TD ${tdProgress.td} / ${tdProgress.ttd}`);
103
- }
104
-
105
88
  let nodeState: string[];
106
89
  switch (sync.state) {
107
90
  case SyncState.SyncingFinalized:
@@ -188,18 +171,13 @@ function getHeadExecutionInfo(
188
171
 
189
172
  // Add execution status to notifier only if head is on/post bellatrix
190
173
  if (isExecutionCachedStateType(headState)) {
191
- if (isMergeTransitionComplete(headState)) {
192
- const executionPayloadHashInfo =
193
- headInfo.executionStatus !== ExecutionStatus.PreMerge ? headInfo.executionPayloadBlockHash : "empty";
194
- const executionPayloadNumberInfo =
195
- headInfo.executionStatus !== ExecutionStatus.PreMerge ? headInfo.executionPayloadNumber : NaN;
196
- return [
197
- `exec-block: ${executionStatusStr}(${executionPayloadNumberInfo} ${prettyBytesShort(
198
- executionPayloadHashInfo
199
- )})`,
200
- ];
201
- }
202
- return [`exec-block: ${executionStatusStr}`];
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
+ ];
203
181
  }
204
182
 
205
183
  return [];
@@ -750,7 +750,9 @@ 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(this.chain.bls, this.chain.getHeadState(), [anchorBlock]);
753
+ await verifyBlockProposerSignature(this.chain.index2pubkey, this.chain.bls, this.chain.getHeadState(), [
754
+ anchorBlock,
755
+ ]);
754
756
 
755
757
  // We can write to the disk if this is ahead of prevFinalizedCheckpointBlock otherwise
756
758
  // we will need to go make checks on the top of sync loop before writing as it might
@@ -815,7 +817,12 @@ export class BackfillSync extends (EventEmitter as {new (): BackfillSyncEmitter}
815
817
 
816
818
  // If any of the block's proposer signature fail, we can't trust this peer at all
817
819
  if (verifiedBlocks.length > 0) {
818
- await verifyBlockProposerSignature(this.chain.bls, this.chain.getHeadState(), verifiedBlocks);
820
+ await verifyBlockProposerSignature(
821
+ this.chain.index2pubkey,
822
+ this.chain.bls,
823
+ this.chain.getHeadState(),
824
+ verifiedBlocks
825
+ );
819
826
 
820
827
  // This is bad, like super bad. Abort the backfill
821
828
  if (!nextAnchor)
@@ -1,6 +1,11 @@
1
1
  import {BeaconConfig} from "@lodestar/config";
2
2
  import {GENESIS_SLOT} from "@lodestar/params";
3
- import {CachedBeaconStateAllForks, ISignatureSet, getBlockProposerSignatureSet} from "@lodestar/state-transition";
3
+ import {
4
+ CachedBeaconStateAllForks,
5
+ ISignatureSet,
6
+ Index2PubkeyCache,
7
+ getBlockProposerSignatureSet,
8
+ } from "@lodestar/state-transition";
4
9
  import {Root, SignedBeaconBlock, Slot, ssz} from "@lodestar/types";
5
10
  import {IBlsVerifier} from "../../chain/bls/index.js";
6
11
  import {BackfillSyncError, BackfillSyncErrorCode} from "./errors.js";
@@ -41,6 +46,7 @@ export function verifyBlockSequence(
41
46
  }
42
47
 
43
48
  export async function verifyBlockProposerSignature(
49
+ index2pubkey: Index2PubkeyCache,
44
50
  bls: IBlsVerifier,
45
51
  state: CachedBeaconStateAllForks,
46
52
  blocks: SignedBeaconBlock[]
@@ -48,7 +54,7 @@ export async function verifyBlockProposerSignature(
48
54
  if (blocks.length === 1 && blocks[0].message.slot === GENESIS_SLOT) return;
49
55
  const signatures = blocks.reduce((sigs: ISignatureSet[], block) => {
50
56
  // genesis block doesn't have valid signature
51
- if (block.message.slot !== GENESIS_SLOT) sigs.push(getBlockProposerSignatureSet(state, block));
57
+ if (block.message.slot !== GENESIS_SLOT) sigs.push(getBlockProposerSignatureSet(index2pubkey, state, block));
52
58
  return sigs;
53
59
  }, []);
54
60
 
@@ -1,65 +0,0 @@
1
- import { ChainConfig } from "@lodestar/config";
2
- import { Logger } from "@lodestar/utils";
3
- import { Metrics } from "../metrics/index.js";
4
- import { EthJsonRpcBlockRaw, IEth1Provider, PowMergeBlock, TDProgress } from "./interface.js";
5
- export declare enum StatusCode {
6
- STOPPED = "STOPPED",
7
- SEARCHING = "SEARCHING",
8
- FOUND = "FOUND"
9
- }
10
- export type Eth1MergeBlockTrackerModules = {
11
- config: ChainConfig;
12
- logger: Logger;
13
- signal: AbortSignal;
14
- metrics: Metrics | null;
15
- };
16
- /**
17
- * Follows the eth1 chain to find a (or multiple?) merge blocks that cross the threshold of total terminal difficulty
18
- *
19
- * Finding the mergeBlock could be done in demand when proposing pre-merge blocks. However, that would slow block
20
- * production during the weeks between BELLATRIX_EPOCH and TTD.
21
- */
22
- export declare class Eth1MergeBlockTracker {
23
- private readonly eth1Provider;
24
- private readonly config;
25
- private readonly logger;
26
- private readonly metrics;
27
- private readonly blocksByHashCache;
28
- private readonly intervals;
29
- private status;
30
- private latestEth1Block;
31
- private getTerminalPowBlockFromEth1Promise;
32
- private readonly safeTDFactor;
33
- constructor({ config, logger, signal, metrics }: Eth1MergeBlockTrackerModules, eth1Provider: IEth1Provider);
34
- /**
35
- * Returns the most recent POW block that satisfies the merge block condition
36
- */
37
- getTerminalPowBlock(): Promise<PowMergeBlock | null>;
38
- getTDProgress(): TDProgress | null;
39
- /**
40
- * Get a POW block by hash checking the local cache first
41
- */
42
- getPowBlock(powBlockHash: string): Promise<PowMergeBlock | null>;
43
- /**
44
- * Should only start polling for mergeBlock if:
45
- * - after BELLATRIX_FORK_EPOCH
46
- * - Beacon node synced
47
- * - head state not isMergeTransitionComplete
48
- */
49
- startPollingMergeBlock(): void;
50
- private close;
51
- private getTerminalPowBlockFromEth1;
52
- /**
53
- * **internal** + **unsafe** since it can create multiple backward searches that overload the eth1 client.
54
- * Must be called in a wrapper to ensure that there's only once concurrent call to this fn.
55
- */
56
- private internalGetTerminalPowBlockFromEth1;
57
- private cacheBlock;
58
- }
59
- export declare function toPowBlock(block: EthJsonRpcBlockRaw): PowMergeBlock;
60
- /**
61
- * TTD values can be very large, for xDAI > 1e45. So scale down.
62
- * To be good, TTD should be rendered as a number < Number.MAX_TD_RENDER_VALUE ~= 9e15
63
- */
64
- export declare function getSafeTDFactor(ttd: bigint): bigint;
65
- //# sourceMappingURL=eth1MergeBlockTracker.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"eth1MergeBlockTracker.d.ts","sourceRoot":"","sources":["../../src/eth1/eth1MergeBlockTracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EAAC,MAAM,EAA2B,MAAM,iBAAiB,CAAC;AAEjE,OAAO,EAAC,OAAO,EAAC,MAAM,qBAAqB,CAAC;AAE5C,OAAO,EAAC,kBAAkB,EAAE,aAAa,EAAE,aAAa,EAA0B,UAAU,EAAC,MAAM,gBAAgB,CAAC;AAGpH,oBAAY,UAAU;IACpB,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,KAAK,UAAU;CAChB;AAkBD,MAAM,MAAM,4BAA4B,GAAG;IACzC,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CACzB,CAAC;AAIF;;;;;GAKG;AACH,qBAAa,qBAAqB;IAe9B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAd/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IAEzC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAqC;IACvE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwB;IAElD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,eAAe,CAAuC;IAC9D,OAAO,CAAC,kCAAkC,CAA8C;IACxF,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAGpC,EAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAC,EAAE,4BAA4B,EAC9C,YAAY,EAAE,aAAa;IAiC9C;;OAEG;IACG,mBAAmB,IAAI,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAe1D,aAAa,IAAI,UAAU,GAAG,IAAI;IAsBlC;;OAEG;IACG,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAkBtE;;;;;OAKG;IACH,sBAAsB,IAAI,IAAI;IAsB9B,OAAO,CAAC,KAAK;YAIC,2BAA2B;IA4CzC;;;OAGG;YACW,mCAAmC;IA6DjD,OAAO,CAAC,UAAU;CAInB;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,kBAAkB,GAAG,aAAa,CAQnE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAWnD"}
@@ -1,262 +0,0 @@
1
- import { pruneSetToMax, toRootHex } from "@lodestar/utils";
2
- import { ZERO_HASH_HEX } from "../constants/index.js";
3
- import { enumToIndexMap } from "../util/enum.js";
4
- import { dataToRootHex, quantityToBigint, quantityToNum } from "./provider/utils.js";
5
- export var StatusCode;
6
- (function (StatusCode) {
7
- StatusCode["STOPPED"] = "STOPPED";
8
- StatusCode["SEARCHING"] = "SEARCHING";
9
- StatusCode["FOUND"] = "FOUND";
10
- })(StatusCode || (StatusCode = {}));
11
- /** For metrics, index order = declaration order of StatusCode */
12
- const statusCodeIdx = enumToIndexMap(StatusCode);
13
- /**
14
- * Bounds `blocksByHashCache` cache, imposing a max distance between highest and lowest block numbers.
15
- * In case of extreme forking the cache might grow unbounded.
16
- */
17
- const MAX_CACHE_POW_BLOCKS = 1024;
18
- const MAX_TD_RENDER_VALUE = Number.MAX_SAFE_INTEGER;
19
- // get_pow_block_at_total_difficulty
20
- /**
21
- * Follows the eth1 chain to find a (or multiple?) merge blocks that cross the threshold of total terminal difficulty
22
- *
23
- * Finding the mergeBlock could be done in demand when proposing pre-merge blocks. However, that would slow block
24
- * production during the weeks between BELLATRIX_EPOCH and TTD.
25
- */
26
- export class Eth1MergeBlockTracker {
27
- eth1Provider;
28
- config;
29
- logger;
30
- metrics;
31
- blocksByHashCache = new Map();
32
- intervals = [];
33
- status;
34
- latestEth1Block = null;
35
- getTerminalPowBlockFromEth1Promise = null;
36
- safeTDFactor;
37
- constructor({ config, logger, signal, metrics }, eth1Provider) {
38
- this.eth1Provider = eth1Provider;
39
- this.config = config;
40
- this.logger = logger;
41
- this.metrics = metrics;
42
- this.status = { code: StatusCode.STOPPED };
43
- signal.addEventListener("abort", () => this.close(), { once: true });
44
- this.safeTDFactor = getSafeTDFactor(this.config.TERMINAL_TOTAL_DIFFICULTY);
45
- const scaledTTD = this.config.TERMINAL_TOTAL_DIFFICULTY / this.safeTDFactor;
46
- // Only run metrics if necessary
47
- if (metrics) {
48
- // TTD can't be dynamically changed during execution, register metric once
49
- metrics.eth1.eth1MergeTTD.set(Number(scaledTTD));
50
- metrics.eth1.eth1MergeTDFactor.set(Number(this.safeTDFactor));
51
- metrics.eth1.eth1MergeStatus.addCollect(() => {
52
- // Set merge ttd, merge status and merge block status
53
- metrics.eth1.eth1MergeStatus.set(statusCodeIdx[this.status.code]);
54
- if (this.latestEth1Block !== null) {
55
- // Set latestBlock stats
56
- metrics.eth1.eth1LatestBlockNumber.set(this.latestEth1Block.number);
57
- metrics.eth1.eth1LatestBlockTD.set(Number(this.latestEth1Block.totalDifficulty / this.safeTDFactor));
58
- metrics.eth1.eth1LatestBlockTimestamp.set(this.latestEth1Block.timestamp);
59
- }
60
- });
61
- }
62
- }
63
- /**
64
- * Returns the most recent POW block that satisfies the merge block condition
65
- */
66
- async getTerminalPowBlock() {
67
- switch (this.status.code) {
68
- case StatusCode.STOPPED:
69
- // If not module is not polling fetch the mergeBlock explicitly
70
- return this.getTerminalPowBlockFromEth1();
71
- case StatusCode.SEARCHING:
72
- // Assume that polling would have found the block
73
- return null;
74
- case StatusCode.FOUND:
75
- return this.status.mergeBlock;
76
- }
77
- }
78
- getTDProgress() {
79
- if (this.latestEth1Block === null) {
80
- return this.latestEth1Block;
81
- }
82
- const tdDiff = this.config.TERMINAL_TOTAL_DIFFICULTY - this.latestEth1Block.totalDifficulty;
83
- if (tdDiff > BigInt(0)) {
84
- return {
85
- ttdHit: false,
86
- tdFactor: this.safeTDFactor,
87
- tdDiffScaled: Number((tdDiff / this.safeTDFactor)),
88
- ttd: this.config.TERMINAL_TOTAL_DIFFICULTY,
89
- td: this.latestEth1Block.totalDifficulty,
90
- timestamp: this.latestEth1Block.timestamp,
91
- };
92
- }
93
- return {
94
- ttdHit: true,
95
- };
96
- }
97
- /**
98
- * Get a POW block by hash checking the local cache first
99
- */
100
- async getPowBlock(powBlockHash) {
101
- // Check cache first
102
- const cachedBlock = this.blocksByHashCache.get(powBlockHash);
103
- if (cachedBlock) {
104
- return cachedBlock;
105
- }
106
- // Fetch from node
107
- const blockRaw = await this.eth1Provider.getBlockByHash(powBlockHash);
108
- if (blockRaw) {
109
- const block = toPowBlock(blockRaw);
110
- this.cacheBlock(block);
111
- return block;
112
- }
113
- return null;
114
- }
115
- /**
116
- * Should only start polling for mergeBlock if:
117
- * - after BELLATRIX_FORK_EPOCH
118
- * - Beacon node synced
119
- * - head state not isMergeTransitionComplete
120
- */
121
- startPollingMergeBlock() {
122
- if (this.status.code !== StatusCode.STOPPED) {
123
- return;
124
- }
125
- this.status = { code: StatusCode.SEARCHING };
126
- this.logger.info("Starting search for terminal POW block", {
127
- TERMINAL_TOTAL_DIFFICULTY: this.config.TERMINAL_TOTAL_DIFFICULTY,
128
- });
129
- const interval = setInterval(() => {
130
- // Preemptively try to find merge block and cache it if found.
131
- // Future callers of getTerminalPowBlock() will re-use the cached found mergeBlock.
132
- this.getTerminalPowBlockFromEth1().catch((e) => {
133
- this.logger.error("Error on findMergeBlock", {}, e);
134
- this.metrics?.eth1.eth1PollMergeBlockErrors.inc();
135
- });
136
- }, this.config.SECONDS_PER_ETH1_BLOCK * 1000);
137
- this.intervals.push(interval);
138
- }
139
- close() {
140
- this.intervals.forEach(clearInterval);
141
- }
142
- async getTerminalPowBlockFromEth1() {
143
- if (!this.getTerminalPowBlockFromEth1Promise) {
144
- this.getTerminalPowBlockFromEth1Promise = this.internalGetTerminalPowBlockFromEth1()
145
- .then((mergeBlock) => {
146
- // Persist found merge block here to affect both caller paths:
147
- // - internal searcher
148
- // - external caller if STOPPED
149
- if (mergeBlock && this.status.code !== StatusCode.FOUND) {
150
- if (this.status.code === StatusCode.SEARCHING) {
151
- this.close();
152
- }
153
- this.logger.info("Terminal POW block found!", {
154
- hash: mergeBlock.blockHash,
155
- number: mergeBlock.number,
156
- totalDifficulty: mergeBlock.totalDifficulty,
157
- });
158
- this.status = { code: StatusCode.FOUND, mergeBlock };
159
- this.metrics?.eth1.eth1MergeBlockDetails.set({
160
- terminalBlockHash: mergeBlock.blockHash,
161
- // Convert all number/bigints to string labels
162
- terminalBlockNumber: mergeBlock.number.toString(10),
163
- terminalBlockTD: mergeBlock.totalDifficulty.toString(10),
164
- }, 1);
165
- }
166
- return mergeBlock;
167
- })
168
- .finally(() => {
169
- this.getTerminalPowBlockFromEth1Promise = null;
170
- });
171
- }
172
- else {
173
- // This should no happen, since getTerminalPowBlockFromEth1() should resolve faster than SECONDS_PER_ETH1_BLOCK.
174
- // else something is wrong: the el-cl comms are two slow, or the backsearch got stuck in a deep search.
175
- this.metrics?.eth1.getTerminalPowBlockPromiseCacheHit.inc();
176
- }
177
- return this.getTerminalPowBlockFromEth1Promise;
178
- }
179
- /**
180
- * **internal** + **unsafe** since it can create multiple backward searches that overload the eth1 client.
181
- * Must be called in a wrapper to ensure that there's only once concurrent call to this fn.
182
- */
183
- async internalGetTerminalPowBlockFromEth1() {
184
- // Search merge block by hash
185
- // Terminal block hash override takes precedence over terminal total difficulty
186
- const terminalBlockHash = toRootHex(this.config.TERMINAL_BLOCK_HASH);
187
- if (terminalBlockHash !== ZERO_HASH_HEX) {
188
- const block = await this.getPowBlock(terminalBlockHash);
189
- if (block) {
190
- return block;
191
- }
192
- // if a TERMINAL_BLOCK_HASH other than ZERO_HASH is configured and we can't find it, return NONE
193
- return null;
194
- }
195
- // Search merge block by TTD
196
- const latestBlockRaw = await this.eth1Provider.getBlockByNumber("latest");
197
- if (!latestBlockRaw) {
198
- throw Error("getBlockByNumber('latest') returned null");
199
- }
200
- let block = toPowBlock(latestBlockRaw);
201
- this.latestEth1Block = { ...block, timestamp: quantityToNum(latestBlockRaw.timestamp) };
202
- this.cacheBlock(block);
203
- // This code path to look backwards for the merge block is only necessary if:
204
- // - The network has not yet found the merge block
205
- // - There are descendants of the merge block in the eth1 chain
206
- // For the search below to require more than a few hops, multiple block proposers in a row must fail to detect
207
- // an existing merge block. Such situation is extremely unlikely, so this search is left un-optimized. Since
208
- // this class can start eagerly looking for the merge block when not necessary, startPollingMergeBlock() should
209
- // only be called when there is certainty that a mergeBlock search is necessary.
210
- while (true) {
211
- if (block.totalDifficulty < this.config.TERMINAL_TOTAL_DIFFICULTY) {
212
- // TTD not reached yet
213
- return null;
214
- }
215
- // else block.totalDifficulty >= this.config.TERMINAL_TOTAL_DIFFICULTY
216
- // Potential mergeBlock! Must find the first block that passes TTD
217
- // Allow genesis block to reach TTD https://github.com/ethereum/consensus-specs/pull/2719
218
- if (block.parentHash === ZERO_HASH_HEX) {
219
- return block;
220
- }
221
- const parent = await this.getPowBlock(block.parentHash);
222
- if (!parent) {
223
- throw Error(`Unknown parent of block with TD>TTD ${block.parentHash}`);
224
- }
225
- this.metrics?.eth1.eth1ParentBlocksFetched.inc();
226
- // block.td > TTD && parent.td < TTD => block is mergeBlock
227
- if (parent.totalDifficulty < this.config.TERMINAL_TOTAL_DIFFICULTY) {
228
- // Is terminal total difficulty block AND has verified block -> parent relationship
229
- return block;
230
- }
231
- block = parent;
232
- }
233
- }
234
- cacheBlock(block) {
235
- this.blocksByHashCache.set(block.blockHash, block);
236
- pruneSetToMax(this.blocksByHashCache, MAX_CACHE_POW_BLOCKS);
237
- }
238
- }
239
- export function toPowBlock(block) {
240
- // Validate untrusted data from API
241
- return {
242
- number: quantityToNum(block.number),
243
- blockHash: dataToRootHex(block.hash),
244
- parentHash: dataToRootHex(block.parentHash),
245
- totalDifficulty: quantityToBigint(block.totalDifficulty),
246
- };
247
- }
248
- /**
249
- * TTD values can be very large, for xDAI > 1e45. So scale down.
250
- * To be good, TTD should be rendered as a number < Number.MAX_TD_RENDER_VALUE ~= 9e15
251
- */
252
- export function getSafeTDFactor(ttd) {
253
- const safeIntegerMult = ttd / BigInt(MAX_TD_RENDER_VALUE);
254
- // TTD < MAX_TD_RENDER_VALUE, no need to scale down
255
- if (safeIntegerMult === BigInt(0)) {
256
- return BigInt(1);
257
- }
258
- // Return closest power of 10 to ensure TD < max
259
- const safeIntegerMultDigits = safeIntegerMult.toString(10).length;
260
- return BigInt(10) ** BigInt(safeIntegerMultDigits);
261
- }
262
- //# sourceMappingURL=eth1MergeBlockTracker.js.map