@lodestar/beacon-node 1.40.0-dev.787d0f5eee → 1.40.0-dev.7922561845
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.
- package/lib/chain/blocks/blockInput/blockInput.d.ts +28 -0
- package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.js +36 -1
- package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.js +8 -0
- package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +1 -2
- package/lib/chain/chain.js.map +1 -1
- package/lib/network/gossip/gossipsub.d.ts +19 -0
- package/lib/network/gossip/gossipsub.d.ts.map +1 -1
- package/lib/network/gossip/gossipsub.js +71 -0
- package/lib/network/gossip/gossipsub.js.map +1 -1
- package/lib/network/options.d.ts +6 -0
- package/lib/network/options.d.ts.map +1 -1
- package/lib/network/options.js.map +1 -1
- package/lib/network/processor/gossipHandlers.js +1 -1
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/package.json +15 -15
- package/src/chain/blocks/blockInput/blockInput.ts +45 -2
- package/src/chain/blocks/writeBlockInputToDb.ts +9 -0
- package/src/chain/chain.ts +1 -2
- package/src/network/gossip/gossipsub.ts +86 -1
- package/src/network/options.ts +6 -0
- package/src/network/processor/gossipHandlers.ts +1 -1
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import {peerIdFromString} from "@libp2p/peer-id";
|
|
2
|
+
import {multiaddr} from "@multiformats/multiaddr";
|
|
3
|
+
import {ENR} from "@chainsafe/enr";
|
|
1
4
|
import {GossipSub, GossipsubEvents} from "@chainsafe/libp2p-gossipsub";
|
|
2
5
|
import {MetricsRegister, TopicLabel, TopicStrToLabel} from "@chainsafe/libp2p-gossipsub/metrics";
|
|
3
6
|
import {PeerScoreParams} from "@chainsafe/libp2p-gossipsub/score";
|
|
4
|
-
import {SignaturePolicy, TopicStr} from "@chainsafe/libp2p-gossipsub/types";
|
|
7
|
+
import {AddrInfo, SignaturePolicy, TopicStr} from "@chainsafe/libp2p-gossipsub/types";
|
|
5
8
|
import {BeaconConfig, ForkBoundary} from "@lodestar/config";
|
|
6
9
|
import {ATTESTATION_SUBNET_COUNT, SLOTS_PER_EPOCH, SYNC_COMMITTEE_SUBNET_COUNT} from "@lodestar/params";
|
|
7
10
|
import {SubnetID} from "@lodestar/types";
|
|
@@ -55,6 +58,12 @@ export type Eth2GossipsubOpts = {
|
|
|
55
58
|
disableFloodPublish?: boolean;
|
|
56
59
|
skipParamsLog?: boolean;
|
|
57
60
|
disableLightClientServer?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Direct peers for GossipSub - these peers maintain permanent mesh connections without GRAFT/PRUNE.
|
|
63
|
+
* Supports multiaddr strings with peer ID (e.g., "/ip4/192.168.1.1/tcp/9000/p2p/16Uiu2HAmKLhW7...")
|
|
64
|
+
* or ENR strings (e.g., "enr:-IS4QHCYrYZbAKWCBRlAy5zzaDZXJBGkcnh4MHcBFZntXNFrdvJjX04jRzjzCBOo...")
|
|
65
|
+
*/
|
|
66
|
+
directPeers?: string[];
|
|
58
67
|
};
|
|
59
68
|
|
|
60
69
|
export type ForkBoundaryLabel = string;
|
|
@@ -97,6 +106,9 @@ export class Eth2Gossipsub extends GossipSub {
|
|
|
97
106
|
);
|
|
98
107
|
}
|
|
99
108
|
|
|
109
|
+
// Parse direct peers from multiaddr strings to AddrInfo objects
|
|
110
|
+
const directPeers = parseDirectPeers(opts.directPeers ?? [], logger);
|
|
111
|
+
|
|
100
112
|
// Gossipsub parameters defined here:
|
|
101
113
|
// https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/phase0/p2p-interface.md#the-gossip-domain-gossipsub
|
|
102
114
|
super(modules.libp2p.services.components, {
|
|
@@ -106,6 +118,7 @@ export class Eth2Gossipsub extends GossipSub {
|
|
|
106
118
|
Dlo: gossipsubDLow ?? GOSSIP_D_LOW,
|
|
107
119
|
Dhi: gossipsubDHigh ?? GOSSIP_D_HIGH,
|
|
108
120
|
Dlazy: 6,
|
|
121
|
+
directPeers,
|
|
109
122
|
heartbeatInterval: GOSSIPSUB_HEARTBEAT_INTERVAL,
|
|
110
123
|
fanoutTTL: 60 * 1000,
|
|
111
124
|
mcacheLength: 6,
|
|
@@ -381,3 +394,75 @@ function getForkBoundaryLabel(boundary: ForkBoundary): ForkBoundaryLabel {
|
|
|
381
394
|
|
|
382
395
|
return label;
|
|
383
396
|
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Parse direct peer strings into AddrInfo objects for GossipSub.
|
|
400
|
+
* Direct peers maintain permanent mesh connections without GRAFT/PRUNE negotiation.
|
|
401
|
+
*
|
|
402
|
+
* Supported formats:
|
|
403
|
+
* - Multiaddr with peer ID: `/ip4/192.168.1.1/tcp/9000/p2p/16Uiu2HAmKLhW7...`
|
|
404
|
+
* - ENR: `enr:-IS4QHCYrYZbAKWCBRlAy5zzaDZXJBGkcnh4MHcBFZntXNFrdvJjX04jRzjzCBOo...`
|
|
405
|
+
*
|
|
406
|
+
* For multiaddrs, the string must contain a /p2p/ component with the peer ID.
|
|
407
|
+
* For ENRs, the TCP multiaddr and peer ID are extracted from the encoded record.
|
|
408
|
+
*/
|
|
409
|
+
export function parseDirectPeers(directPeerStrs: string[], logger: Logger): AddrInfo[] {
|
|
410
|
+
const directPeers: AddrInfo[] = [];
|
|
411
|
+
|
|
412
|
+
for (const peerStr of directPeerStrs) {
|
|
413
|
+
// Check if this is an ENR (starts with "enr:")
|
|
414
|
+
if (peerStr.startsWith("enr:")) {
|
|
415
|
+
try {
|
|
416
|
+
const enr = ENR.decodeTxt(peerStr);
|
|
417
|
+
const peerId = enr.peerId;
|
|
418
|
+
|
|
419
|
+
// Get TCP multiaddr from ENR
|
|
420
|
+
const multiaddrTCP = enr.getLocationMultiaddr("tcp");
|
|
421
|
+
if (!multiaddrTCP) {
|
|
422
|
+
logger.warn("ENR does not contain TCP multiaddr", {enr: peerStr});
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
directPeers.push({
|
|
427
|
+
id: peerId,
|
|
428
|
+
addrs: [multiaddrTCP],
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
logger.info("Added direct peer from ENR", {peerId: peerId.toString(), addr: multiaddrTCP.toString()});
|
|
432
|
+
} catch (e) {
|
|
433
|
+
logger.warn("Failed to parse direct peer ENR", {enr: peerStr}, e as Error);
|
|
434
|
+
}
|
|
435
|
+
} else {
|
|
436
|
+
// Parse as multiaddr
|
|
437
|
+
try {
|
|
438
|
+
const ma = multiaddr(peerStr);
|
|
439
|
+
|
|
440
|
+
const peerIdStr = ma.getPeerId();
|
|
441
|
+
if (!peerIdStr) {
|
|
442
|
+
logger.warn("Direct peer multiaddr must contain /p2p/ component with peer ID", {multiaddr: peerStr});
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
try {
|
|
447
|
+
const peerId = peerIdFromString(peerIdStr);
|
|
448
|
+
|
|
449
|
+
// Get the address without the /p2p/ component
|
|
450
|
+
const addr = ma.decapsulate("/p2p/" + peerIdStr);
|
|
451
|
+
|
|
452
|
+
directPeers.push({
|
|
453
|
+
id: peerId,
|
|
454
|
+
addrs: [addr],
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
logger.info("Added direct peer", {peerId: peerIdStr, addr: addr.toString()});
|
|
458
|
+
} catch (e) {
|
|
459
|
+
logger.warn("Invalid peer ID in direct peer multiaddr", {multiaddr: peerStr, peerId: peerIdStr}, e as Error);
|
|
460
|
+
}
|
|
461
|
+
} catch (e) {
|
|
462
|
+
logger.warn("Failed to parse direct peer multiaddr", {multiaddr: peerStr}, e as Error);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
return directPeers;
|
|
468
|
+
}
|
package/src/network/options.ts
CHANGED
|
@@ -15,6 +15,12 @@ export interface NetworkOptions
|
|
|
15
15
|
Omit<Eth2GossipsubOpts, "disableLightClientServer"> {
|
|
16
16
|
localMultiaddrs: string[];
|
|
17
17
|
bootMultiaddrs?: string[];
|
|
18
|
+
/**
|
|
19
|
+
* Direct peers for GossipSub - these peers maintain permanent mesh connections without GRAFT/PRUNE.
|
|
20
|
+
* Format: multiaddr strings with peer ID, e.g., "/ip4/192.168.1.1/tcp/9000/p2p/16Uiu2HAmKLhW7..."
|
|
21
|
+
* Both peers must configure each other as direct peers for the feature to work properly.
|
|
22
|
+
*/
|
|
23
|
+
directPeers?: string[];
|
|
18
24
|
subscribeAllSubnets?: boolean;
|
|
19
25
|
mdns?: boolean;
|
|
20
26
|
connectToDiscv5Bootnodes?: boolean;
|
|
@@ -579,7 +579,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
579
579
|
break;
|
|
580
580
|
}
|
|
581
581
|
|
|
582
|
-
if (!blockInput.
|
|
582
|
+
if (!blockInput.hasComputedAllData()) {
|
|
583
583
|
// immediately attempt fetch of data columns from execution engine
|
|
584
584
|
chain.getBlobsTracker.triggerGetBlobs(blockInput);
|
|
585
585
|
// if we've received at least half of the columns, trigger reconstruction of the rest
|