@lodestar/beacon-node 1.41.0-dev.85cdea6cc6 → 1.41.0-dev.92c37f2525

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 (34) hide show
  1. package/lib/chain/validation/attestation.d.ts.map +1 -1
  2. package/lib/chain/validation/attestation.js +7 -3
  3. package/lib/chain/validation/attestation.js.map +1 -1
  4. package/lib/network/discv5/utils.d.ts +1 -1
  5. package/lib/network/discv5/utils.d.ts.map +1 -1
  6. package/lib/network/discv5/utils.js +5 -4
  7. package/lib/network/discv5/utils.js.map +1 -1
  8. package/lib/network/gossip/gossipsub.d.ts.map +1 -1
  9. package/lib/network/gossip/gossipsub.js +9 -6
  10. package/lib/network/gossip/gossipsub.js.map +1 -1
  11. package/lib/network/libp2p/index.d.ts +1 -1
  12. package/lib/network/libp2p/index.d.ts.map +1 -1
  13. package/lib/network/libp2p/index.js +35 -17
  14. package/lib/network/libp2p/index.js.map +1 -1
  15. package/lib/network/metadata.d.ts +1 -0
  16. package/lib/network/metadata.d.ts.map +1 -1
  17. package/lib/network/metadata.js +1 -0
  18. package/lib/network/metadata.js.map +1 -1
  19. package/lib/network/options.d.ts +2 -0
  20. package/lib/network/options.d.ts.map +1 -1
  21. package/lib/network/options.js +3 -0
  22. package/lib/network/options.js.map +1 -1
  23. package/lib/network/peers/discover.d.ts +2 -0
  24. package/lib/network/peers/discover.d.ts.map +1 -1
  25. package/lib/network/peers/discover.js +41 -10
  26. package/lib/network/peers/discover.js.map +1 -1
  27. package/package.json +16 -15
  28. package/src/chain/validation/attestation.ts +7 -3
  29. package/src/network/discv5/utils.ts +5 -4
  30. package/src/network/gossip/gossipsub.ts +12 -7
  31. package/src/network/libp2p/index.ts +40 -18
  32. package/src/network/metadata.ts +1 -0
  33. package/src/network/options.ts +5 -1
  34. package/src/network/peers/discover.ts +46 -11
@@ -59,6 +59,7 @@ export enum DiscoveredPeerStatus {
59
59
  cached = "cached",
60
60
  dropped = "dropped",
61
61
  no_multiaddrs = "no_multiaddrs",
62
+ transport_incompatible = "transport_incompatible",
62
63
  peer_cooling_down = "peer_cooling_down",
63
64
  }
64
65
 
@@ -88,7 +89,8 @@ export type SubnetDiscvQueryMs = {
88
89
 
89
90
  type CachedENR = {
90
91
  peerId: PeerId;
91
- multiaddrTCP: Multiaddr;
92
+ multiaddrTCP?: Multiaddr;
93
+ multiaddrQUIC?: Multiaddr;
92
94
  subnets: Record<SubnetType, boolean[]>;
93
95
  addedUnixMs: number;
94
96
  // custodyGroups is null for pre-fulu
@@ -114,6 +116,7 @@ export class PeerDiscovery {
114
116
  attnets: new Map(),
115
117
  syncnets: new Map(),
116
118
  };
119
+ private transports: string[];
117
120
 
118
121
  private custodyGroupQueries: CustodyGroupQueries;
119
122
 
@@ -180,6 +183,17 @@ export class PeerDiscovery {
180
183
  }
181
184
  });
182
185
  }
186
+
187
+ // Transport tags vary by library: @libp2p/tcp uses '@libp2p/tcp', @chainsafe/libp2p-quic uses 'quic'
188
+ // Normalize to simple 'tcp' / 'quic' strings for matching
189
+ this.transports = libp2p.services.components.transportManager
190
+ .getTransports()
191
+ .map((t) => t[Symbol.toStringTag])
192
+ .map((tag) => {
193
+ if (tag?.includes("tcp")) return "tcp";
194
+ if (tag?.includes("quic")) return "quic";
195
+ return tag;
196
+ });
183
197
  }
184
198
 
185
199
  static async init(modules: PeerDiscoveryModules, opts: PeerDiscoveryOpts): Promise<PeerDiscovery> {
@@ -372,10 +386,15 @@ export class PeerDiscovery {
372
386
  return;
373
387
  }
374
388
 
389
+ // Select multiaddrs by protocol rather than index — libp2p discovery events
390
+ // don't guarantee ordering or number of addresses
391
+ const multiaddrTCP = multiaddrs.find((ma) => ma.toString().includes("/tcp/"));
392
+ const multiaddrQUIC = multiaddrs.find((ma) => ma.toString().includes("/quic-v1"));
393
+
375
394
  const attnets = zeroAttnets;
376
395
  const syncnets = zeroSyncnets;
377
396
 
378
- const status = this.handleDiscoveredPeer(id, multiaddrs[0], attnets, syncnets, undefined);
397
+ const status = this.handleDiscoveredPeer(id, multiaddrTCP, multiaddrQUIC, attnets, syncnets, undefined);
379
398
  this.logger.debug("Discovered peer via libp2p", {peer: prettyPrintPeerId(id), status});
380
399
  this.metrics?.discovery.discoveredStatus.inc({status});
381
400
  };
@@ -388,13 +407,15 @@ export class PeerDiscovery {
388
407
  this.randomNodeQuery.count++;
389
408
  }
390
409
  const peerId = enr.peerId;
391
- // tcp multiaddr is known to be be present, checked inside the worker
410
+ // At least one transport is known to be present, checked inside the worker
392
411
  const multiaddrTCP = enr.getLocationMultiaddr(ENRKey.tcp);
393
- if (!multiaddrTCP) {
394
- this.logger.warn("Discv5 worker sent enr without tcp multiaddr", {enr: enr.encodeTxt()});
412
+ const multiaddrQUIC = enr.getLocationMultiaddr(ENRKey.quic);
413
+ if (!multiaddrTCP && !multiaddrQUIC) {
414
+ this.logger.warn("Discv5 worker sent enr without any transport multiaddr", {enr: enr.encodeTxt()});
395
415
  this.metrics?.discovery.discoveredStatus.inc({status: DiscoveredPeerStatus.no_multiaddrs});
396
416
  return;
397
417
  }
418
+
398
419
  // Are this fields mandatory?
399
420
  const attnetsBytes = enr.kvs.get(ENRKey.attnets); // 64 bits
400
421
  const syncnetsBytes = enr.kvs.get(ENRKey.syncnets); // 4 bits
@@ -414,7 +435,7 @@ export class PeerDiscovery {
414
435
  const syncnets = syncnetsBytes ? deserializeEnrSubnets(syncnetsBytes, SYNC_COMMITTEE_SUBNET_COUNT) : zeroSyncnets;
415
436
  const custodyGroupCount = custodyGroupCountBytes ? bytesToInt(custodyGroupCountBytes, "be") : undefined;
416
437
 
417
- const status = this.handleDiscoveredPeer(peerId, multiaddrTCP, attnets, syncnets, custodyGroupCount);
438
+ const status = this.handleDiscoveredPeer(peerId, multiaddrTCP, multiaddrQUIC, attnets, syncnets, custodyGroupCount);
418
439
  this.logger.debug("Discovered peer via discv5", {
419
440
  peer: prettyPrintPeerId(peerId),
420
441
  status,
@@ -428,7 +449,8 @@ export class PeerDiscovery {
428
449
  */
429
450
  private handleDiscoveredPeer(
430
451
  peerId: PeerId,
431
- multiaddrTCP: Multiaddr,
452
+ multiaddrTCP: Multiaddr | undefined,
453
+ multiaddrQUIC: Multiaddr | undefined,
432
454
  attnets: boolean[],
433
455
  syncnets: boolean[],
434
456
  custodySubnetCount?: number
@@ -454,6 +476,13 @@ export class PeerDiscovery {
454
476
  return DiscoveredPeerStatus.already_connected;
455
477
  }
456
478
 
479
+ // ignore peers if they don't share any transport with us
480
+ const hasTcpMatch = this.transports.includes("tcp") && multiaddrTCP;
481
+ const hasQuicMatch = this.transports.includes("quic") && multiaddrQUIC;
482
+ if (!hasTcpMatch && !hasQuicMatch) {
483
+ return DiscoveredPeerStatus.transport_incompatible;
484
+ }
485
+
457
486
  // Ignore dialing peers
458
487
  if (
459
488
  this.libp2p.services.components.connectionManager
@@ -469,6 +498,7 @@ export class PeerDiscovery {
469
498
  const cachedPeer: CachedENR = {
470
499
  peerId,
471
500
  multiaddrTCP,
501
+ multiaddrQUIC,
472
502
  subnets: {attnets, syncnets},
473
503
  addedUnixMs: Date.now(),
474
504
  // for pre-fulu, custodyGroups is null
@@ -566,19 +596,24 @@ export class PeerDiscovery {
566
596
  // are not successful.
567
597
  this.peersToConnect = Math.max(this.peersToConnect - 1, 0);
568
598
 
569
- const {peerId, multiaddrTCP} = cachedPeer;
599
+ const {peerId, multiaddrTCP, multiaddrQUIC} = cachedPeer;
570
600
 
571
601
  // Must add the multiaddrs array to the address book before dialing
572
602
  // https://github.com/libp2p/js-libp2p/blob/aec8e3d3bb1b245051b60c2a890550d262d5b062/src/index.js#L638
573
- const peer = await this.libp2p.peerStore.merge(peerId, {multiaddrs: [multiaddrTCP]});
603
+ const peer = await this.libp2p.peerStore.merge(peerId, {
604
+ multiaddrs: [multiaddrQUIC, multiaddrTCP].filter(Boolean) as Multiaddr[],
605
+ });
574
606
  if (peer.addresses.length === 0) {
575
607
  this.metrics?.discovery.notDialReason.inc({reason: NotDialReason.no_multiaddrs});
576
608
  return;
577
609
  }
578
610
 
579
- // Note: PeerDiscovery adds the multiaddrTCP beforehand
611
+ // Note: PeerDiscovery adds the multiaddrs beforehand
580
612
  const peerIdShort = prettyPrintPeerId(peerId);
581
- this.logger.debug("Dialing discovered peer", {peer: peerIdShort});
613
+ this.logger.debug("Dialing discovered peer", {
614
+ peer: peerIdShort,
615
+ addresses: peer.addresses.map((a) => a.multiaddr.toString()).join(", "),
616
+ });
582
617
 
583
618
  this.metrics?.discovery.dialAttempts.inc();
584
619
  const timer = this.metrics?.discovery.dialTime.startTimer();