@lodestar/beacon-node 1.51.0-dev.09763aa8d2 → 1.51.0-dev.14a10bec65

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 (44) hide show
  1. package/lib/metrics/metrics/lodestar.d.ts +3 -0
  2. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  3. package/lib/metrics/metrics/lodestar.js +5 -0
  4. package/lib/metrics/metrics/lodestar.js.map +1 -1
  5. package/lib/network/core/networkCore.d.ts +2 -0
  6. package/lib/network/core/networkCore.d.ts.map +1 -1
  7. package/lib/network/core/networkCore.js +3 -0
  8. package/lib/network/core/networkCore.js.map +1 -1
  9. package/lib/network/core/networkCoreWorker.js +1 -0
  10. package/lib/network/core/networkCoreWorker.js.map +1 -1
  11. package/lib/network/core/networkCoreWorkerHandler.d.ts +2 -0
  12. package/lib/network/core/networkCoreWorkerHandler.d.ts.map +1 -1
  13. package/lib/network/core/networkCoreWorkerHandler.js +3 -0
  14. package/lib/network/core/networkCoreWorkerHandler.js.map +1 -1
  15. package/lib/network/core/types.d.ts +2 -0
  16. package/lib/network/core/types.d.ts.map +1 -1
  17. package/lib/network/interface.d.ts +2 -0
  18. package/lib/network/interface.d.ts.map +1 -1
  19. package/lib/network/network.d.ts +2 -0
  20. package/lib/network/network.d.ts.map +1 -1
  21. package/lib/network/network.js +3 -0
  22. package/lib/network/network.js.map +1 -1
  23. package/lib/network/peers/peerManager.d.ts +2 -1
  24. package/lib/network/peers/peerManager.d.ts.map +1 -1
  25. package/lib/network/peers/peerManager.js.map +1 -1
  26. package/lib/network/peers/utils/assertPeerRelevance.d.ts +9 -1
  27. package/lib/network/peers/utils/assertPeerRelevance.d.ts.map +1 -1
  28. package/lib/network/peers/utils/assertPeerRelevance.js +32 -21
  29. package/lib/network/peers/utils/assertPeerRelevance.js.map +1 -1
  30. package/lib/sync/sync.d.ts +7 -0
  31. package/lib/sync/sync.d.ts.map +1 -1
  32. package/lib/sync/sync.js +61 -3
  33. package/lib/sync/sync.js.map +1 -1
  34. package/package.json +16 -16
  35. package/src/metrics/metrics/lodestar.ts +5 -0
  36. package/src/network/core/networkCore.ts +5 -0
  37. package/src/network/core/networkCoreWorker.ts +1 -0
  38. package/src/network/core/networkCoreWorkerHandler.ts +4 -0
  39. package/src/network/core/types.ts +2 -0
  40. package/src/network/interface.ts +2 -0
  41. package/src/network/network.ts +5 -0
  42. package/src/network/peers/peerManager.ts +1 -1
  43. package/src/network/peers/utils/assertPeerRelevance.ts +39 -23
  44. package/src/sync/sync.ts +65 -4
package/src/sync/sync.ts CHANGED
@@ -1,13 +1,17 @@
1
1
  import {SLOTS_PER_EPOCH} from "@lodestar/params";
2
- import {Slot} from "@lodestar/types";
2
+ import {computeStartSlotAtEpoch} from "@lodestar/state-transition";
3
+ import {Slot, Status} from "@lodestar/types";
3
4
  import {Logger, toRootHex} from "@lodestar/utils";
4
5
  import {IBeaconChain} from "../chain/index.js";
5
- import {GENESIS_SLOT} from "../constants/constants.js";
6
+ import {GENESIS_EPOCH, GENESIS_SLOT} from "../constants/constants.js";
7
+ import {GoodByeReasonCode} from "../constants/index.js";
8
+ import {IBeaconDb} from "../db/index.js";
6
9
  import {ExecutionEngineState} from "../execution/index.js";
7
10
  import {Metrics} from "../metrics/index.js";
8
- import {INetwork, NetworkEvent, NetworkEventData} from "../network/index.js";
11
+ import {INetwork, NetworkEvent, NetworkEventData, PeerAction} from "../network/index.js";
9
12
  import {ClockEvent} from "../util/clock.js";
10
13
  import {isOptimisticBlock} from "../util/forkChoice.js";
14
+ import {PeerIdStr} from "../util/peerId.js";
11
15
  import {MIN_EPOCH_TO_START_GOSSIP} from "./constants.js";
12
16
  import {IBeaconSync, SyncChainDebugState, SyncModules, SyncState, SyncingStatus, syncStateMetric} from "./interface.js";
13
17
  import {SyncOptions} from "./options.js";
@@ -19,6 +23,7 @@ export class BeaconSync implements IBeaconSync {
19
23
  private readonly logger: Logger;
20
24
  private readonly network: INetwork;
21
25
  private readonly chain: IBeaconChain;
26
+ private readonly db: IBeaconDb;
22
27
  private readonly metrics: Metrics | null;
23
28
  private readonly opts: SyncOptions;
24
29
 
@@ -30,10 +35,11 @@ export class BeaconSync implements IBeaconSync {
30
35
  private readonly slotImportTolerance: Slot;
31
36
 
32
37
  constructor(opts: SyncOptions, modules: SyncModules) {
33
- const {config, chain, metrics, network, logger} = modules;
38
+ const {config, chain, db, metrics, network, logger} = modules;
34
39
  this.opts = opts;
35
40
  this.network = network;
36
41
  this.chain = chain;
42
+ this.db = db;
37
43
  this.metrics = metrics;
38
44
  this.logger = logger;
39
45
  this.rangeSync = new RangeSync(modules, opts);
@@ -192,6 +198,11 @@ export class BeaconSync implements IBeaconSync {
192
198
  */
193
199
  private addPeer = (data: NetworkEventData[NetworkEvent.peerConnected]): void => {
194
200
  const localStatus = this.chain.getStatus();
201
+ // Genesis and equal finalized epochs are already checked by assertPeerRelevance in the network worker
202
+ if (data.status.finalizedEpoch > GENESIS_EPOCH && data.status.finalizedEpoch < localStatus.finalizedEpoch) {
203
+ void this.verifyPastFinalizedCheckpoint(data.peer, data.status);
204
+ }
205
+
195
206
  const syncType = getPeerSyncType(localStatus, data.status, this.chain.forkChoice, this.slotImportTolerance);
196
207
  this.logger.verbose("Peer sync type classified", {
197
208
  peer: data.peer,
@@ -216,6 +227,56 @@ export class BeaconSync implements IBeaconSync {
216
227
  this.updateSyncState();
217
228
  };
218
229
 
230
+ /**
231
+ * A behind peer's finalized checkpoint must be the canonical block in effect at the start slot of its epoch
232
+ */
233
+ async verifyPastFinalizedCheckpoint(peer: PeerIdStr, remote: Status): Promise<void> {
234
+ const startSlot = computeStartSlotAtEpoch(remote.finalizedEpoch);
235
+ const root = toRootHex(remote.finalizedRoot);
236
+ try {
237
+ let reason: string | null = null;
238
+ // After a finality jump, finalized blocks stay in fork choice until the archiver migrates them.
239
+ // Fork choice is pruned only after archiving, so a miss here means the db already has this range.
240
+ const canonicalBlock = this.chain.forkChoice.getCanonicalBlockClosestLteSlot(startSlot);
241
+ if (canonicalBlock !== null) {
242
+ if (canonicalBlock.blockRoot === root) return;
243
+ reason = "finalized_root_not_canonical";
244
+ } else {
245
+ const slot = await this.db.blockArchive.getSlotByRoot(remote.finalizedRoot);
246
+ if (slot !== null && slot > startSlot) {
247
+ reason = "finalized_root_after_epoch_start";
248
+ } else if (slot !== startSlot) {
249
+ const childSlot = await this.db.blockArchive.getSlotByParentRoot(remote.finalizedRoot);
250
+ if (childSlot !== null) {
251
+ if (childSlot <= startSlot) reason = "finalized_root_not_in_effect_at_epoch_start";
252
+ } else if (slot === null && startSlot > this.chain.earliestAvailableSlot) {
253
+ // childSlot == null too, neither the root nor a child is canonical
254
+ // or they are canonical and both pruned but peer's finalized epoch starts after earliestAvailableSlot
255
+ reason = "unknown_finalized_root";
256
+ }
257
+ }
258
+ }
259
+
260
+ if (reason !== null) {
261
+ this.logger.debug("Peer finalized checkpoint not in our chain", {
262
+ peer,
263
+ finalizedEpoch: remote.finalizedEpoch,
264
+ root,
265
+ reason,
266
+ });
267
+ this.metrics?.syncPeerFinalizedCheckpointMismatch.inc({reason});
268
+ this.network.reportPeer(peer, PeerAction.Fatal, "PeerFinalizedCheckpointMismatch");
269
+ await this.network.goodbyeAndDisconnect(peer, GoodByeReasonCode.IRRELEVANT_NETWORK);
270
+ }
271
+ } catch (e) {
272
+ this.logger.debug(
273
+ "Error verifying peer finalized checkpoint",
274
+ {peer, finalizedEpoch: remote.finalizedEpoch, root},
275
+ e as Error
276
+ );
277
+ }
278
+ }
279
+
219
280
  /**
220
281
  * Must be called by libp2p when a peer is removed from the peer manager
221
282
  */