Skip to content

Commit d37bdb0

Browse files
authored
chore: upgrade to js-libp2p 2.0 (#7077)
* chore: upgrade to js-libp2p 2.0 * chore: bump libp2p versions * chore: fix up yarn lock * chore: fix some tests * chore: fix connection map * feat: gossipsub v1.2 * chore: bump libp2p * chore: tweak idontwantMinDataSize * chore: bump libp2p deps
1 parent 911a3f5 commit d37bdb0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+754
-599
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
"https-browserify": "^1.0.0",
6161
"jsdom": "^23.0.1",
6262
"lerna": "^7.3.0",
63-
"libp2p": "1.4.3",
63+
"libp2p": "2.1.7",
6464
"mocha": "^10.2.0",
6565
"node-gyp": "^9.4.0",
6666
"npm-run-all": "^4.1.5",

packages/beacon-node/package.json

+17-18
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,10 @@
9696
"dependencies": {
9797
"@chainsafe/as-sha256": "^0.5.0",
9898
"@chainsafe/blst": "^2.0.3",
99-
"@chainsafe/discv5": "^9.0.0",
100-
"@chainsafe/enr": "^3.0.0",
101-
"@chainsafe/libp2p-gossipsub": "^13.0.0",
102-
"@chainsafe/libp2p-identify": "^1.0.0",
103-
"@chainsafe/libp2p-noise": "^15.0.0",
99+
"@chainsafe/discv5": "^10.0.1",
100+
"@chainsafe/enr": "^4.0.1",
101+
"@chainsafe/libp2p-gossipsub": "^14.1.0",
102+
"@chainsafe/libp2p-noise": "^16.0.0",
104103
"@chainsafe/persistent-merkle-tree": "^0.8.0",
105104
"@chainsafe/prometheus-gc-stats": "^1.0.0",
106105
"@chainsafe/ssz": "^0.17.1",
@@ -111,15 +110,15 @@
111110
"@fastify/cors": "^10.0.1",
112111
"@fastify/swagger": "^9.0.0",
113112
"@fastify/swagger-ui": "^5.0.1",
114-
"@libp2p/bootstrap": "^10.0.21",
115-
"@libp2p/identify": "^1.0.20",
116-
"@libp2p/interface": "^1.3.0",
117-
"@libp2p/mdns": "^10.0.21",
118-
"@libp2p/mplex": "^10.0.21",
119-
"@libp2p/peer-id": "^4.1.0",
120-
"@libp2p/peer-id-factory": "^4.1.0",
121-
"@libp2p/prometheus-metrics": "^3.0.21",
122-
"@libp2p/tcp": "9.0.23",
113+
"@libp2p/bootstrap": "^11.0.4",
114+
"@libp2p/crypto": "^5.0.4",
115+
"@libp2p/identify": "^3.0.4",
116+
"@libp2p/interface": "^2.1.2",
117+
"@libp2p/mdns": "^11.0.4",
118+
"@libp2p/mplex": "^11.0.4",
119+
"@libp2p/peer-id": "^5.0.4",
120+
"@libp2p/prometheus-metrics": "^4.1.2",
121+
"@libp2p/tcp": "10.0.4",
123122
"@lodestar/api": "^1.22.0",
124123
"@lodestar/config": "^1.22.0",
125124
"@lodestar/db": "^1.22.0",
@@ -134,15 +133,15 @@
134133
"@lodestar/validator": "^1.22.0",
135134
"@multiformats/multiaddr": "^12.1.3",
136135
"c-kzg": "^2.1.2",
137-
"datastore-core": "^9.1.1",
138-
"datastore-level": "^10.1.1",
136+
"datastore-core": "^10.0.0",
137+
"datastore-level": "^11.0.0",
139138
"deepmerge": "^4.3.1",
140139
"fastify": "^5.0.0",
141-
"interface-datastore": "^8.2.7",
140+
"interface-datastore": "^8.3.0",
142141
"it-all": "^3.0.4",
143142
"it-pipe": "^3.0.1",
144143
"jwt-simple": "0.5.6",
145-
"libp2p": "1.4.3",
144+
"libp2p": "2.1.7",
146145
"multiformats": "^11.0.1",
147146
"prom-client": "^15.1.0",
148147
"qs": "^6.11.1",

packages/beacon-node/src/network/core/networkCore.ts

+11-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Connection, PeerId} from "@libp2p/interface";
1+
import {Connection, PrivateKey} from "@libp2p/interface";
22
import {multiaddr} from "@multiformats/multiaddr";
33
import {PublishOpts} from "@chainsafe/libp2p-gossipsub/types";
44
import {PeerScoreStatsDump} from "@chainsafe/libp2p-gossipsub/dist/src/score/peer-score.js";
@@ -55,7 +55,7 @@ type Mods = {
5555
export type BaseNetworkInit = {
5656
opts: NetworkOptions;
5757
config: BeaconConfig;
58-
peerId: PeerId;
58+
privateKey: PrivateKey;
5959
peerStoreDir: string | undefined;
6060
logger: LoggerNode;
6161
metricsRegistry: RegistryMetricCreator | null;
@@ -126,7 +126,7 @@ export class NetworkCore implements INetworkCore {
126126
static async init({
127127
opts,
128128
config,
129-
peerId,
129+
privateKey,
130130
peerStoreDir,
131131
logger,
132132
metricsRegistry,
@@ -136,7 +136,7 @@ export class NetworkCore implements INetworkCore {
136136
activeValidatorCount,
137137
initialStatus,
138138
}: BaseNetworkInit): Promise<NetworkCore> {
139-
const libp2p = await createNodeJsLibp2p(peerId, opts, {
139+
const libp2p = await createNodeJsLibp2p(privateKey, opts, {
140140
peerStoreDir,
141141
metrics: Boolean(metricsRegistry),
142142
metricsRegistry: metricsRegistry ?? undefined,
@@ -200,8 +200,9 @@ export class NetworkCore implements INetworkCore {
200200

201201
const peerManager = await PeerManager.init(
202202
{
203+
privateKey,
203204
libp2p,
204-
gossip: gossip,
205+
gossip,
205206
reqResp,
206207
attnetsService,
207208
syncnetsService,
@@ -359,7 +360,11 @@ export class NetworkCore implements INetworkCore {
359360
}
360361

361362
getConnectionsByPeer(): Map<string, Connection[]> {
362-
return getConnectionsMap(this.libp2p);
363+
const m = new Map<string, Connection[]>();
364+
for (const [k, v] of getConnectionsMap(this.libp2p).entries()) {
365+
m.set(k, v.value);
366+
}
367+
return m;
363368
}
364369

365370
async getConnectedPeers(): Promise<PeerIdStr[]> {

packages/beacon-node/src/network/core/networkCoreWorker.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import path from "node:path";
33
import worker from "node:worker_threads";
44
import type {ModuleThread} from "@chainsafe/threads";
55
import {expose} from "@chainsafe/threads/worker";
6-
import {createFromProtobuf} from "@libp2p/peer-id-factory";
6+
import {privateKeyFromProtobuf} from "@libp2p/crypto/keys";
7+
import {peerIdFromPrivateKey} from "@libp2p/peer-id";
78
import {chainConfigFromJson, createBeaconConfig} from "@lodestar/config";
89
import {getNodeLogger} from "@lodestar/logger/node";
910
import {RegistryMetricCreator, collectNodeJSMetrics} from "../../metrics/index.js";
@@ -32,7 +33,8 @@ if (!workerData) throw Error("workerData must be defined");
3233
if (!parentPort) throw Error("parentPort must be defined");
3334

3435
const config = createBeaconConfig(chainConfigFromJson(workerData.chainConfigJson), workerData.genesisValidatorsRoot);
35-
const peerId = await createFromProtobuf(workerData.peerIdProto);
36+
const privateKey = privateKeyFromProtobuf(workerData.privateKeyProto);
37+
const peerId = peerIdFromPrivateKey(privateKey);
3638

3739
// TODO: Pass options from main thread for logging
3840
// TODO: Logging won't be visible in file loggers
@@ -92,7 +94,7 @@ if (networkCoreWorkerMetrics) {
9294
const core = await NetworkCore.init({
9395
opts: workerData.opts,
9496
config,
95-
peerId,
97+
privateKey,
9698
peerStoreDir: workerData.peerStoreDir,
9799
logger,
98100
metricsRegistry: metricsRegister,

packages/beacon-node/src/network/core/networkCoreWorkerHandler.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import workerThreads from "node:worker_threads";
33
import {PeerScoreStatsDump} from "@chainsafe/libp2p-gossipsub/dist/src/score/peer-score.js";
44
import {PublishOpts} from "@chainsafe/libp2p-gossipsub/types";
55
import {ModuleThread, Thread, Worker, spawn} from "@chainsafe/threads";
6-
import {PeerId, Secp256k1PeerId} from "@libp2p/interface";
7-
import {exportToProtobuf} from "@libp2p/peer-id-factory";
6+
import {PrivateKey} from "@libp2p/interface";
7+
import {privateKeyToProtobuf} from "@libp2p/crypto/keys";
88
import {routes} from "@lodestar/api";
99
import {BeaconConfig, chainConfigToJson} from "@lodestar/config";
1010
import type {LoggerNode} from "@lodestar/logger/node";
@@ -44,7 +44,7 @@ export type WorkerNetworkCoreInitModules = {
4444
opts: WorkerNetworkCoreOpts;
4545
config: BeaconConfig;
4646
logger: LoggerNode;
47-
peerId: PeerId;
47+
privateKey: PrivateKey;
4848
events: NetworkEventBus;
4949
metrics: Metrics | null;
5050
getReqRespHandler: GetReqRespHandlerFn;
@@ -103,14 +103,14 @@ export class WorkerNetworkCore implements INetworkCore {
103103
}
104104

105105
static async init(modules: WorkerNetworkCoreInitModules): Promise<WorkerNetworkCore> {
106-
const {opts, config, peerId} = modules;
106+
const {opts, config, privateKey} = modules;
107107
const {genesisTime, peerStoreDir, activeValidatorCount, localMultiaddrs, metricsEnabled, initialStatus} = opts;
108108

109109
const workerData: NetworkWorkerData = {
110110
opts,
111111
chainConfigJson: chainConfigToJson(config),
112112
genesisValidatorsRoot: config.genesisValidatorsRoot,
113-
peerIdProto: exportToProtobuf(peerId as Secp256k1PeerId),
113+
privateKeyProto: privateKeyToProtobuf(privateKey),
114114
localMultiaddrs,
115115
metricsEnabled,
116116
peerStoreDir,

packages/beacon-node/src/network/core/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export type NetworkWorkerData = {
7878
genesisTime: number;
7979
activeValidatorCount: number;
8080
initialStatus: phase0.Status;
81-
peerIdProto: Uint8Array;
81+
privateKeyProto: Uint8Array;
8282
localMultiaddrs: string[];
8383
metricsEnabled: boolean;
8484
peerStoreDir?: string;

packages/beacon-node/src/network/discv5/index.ts

+6-8
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import EventEmitter from "node:events";
2-
import {PeerId, Secp256k1PeerId} from "@libp2p/interface";
2+
import {privateKeyToProtobuf} from "@libp2p/crypto/keys";
3+
import {PrivateKey} from "@libp2p/interface";
34
import {StrictEventEmitter} from "strict-event-emitter-types";
4-
import {exportToProtobuf} from "@libp2p/peer-id-factory";
5-
import {createPrivateKeyFromPeerId, ENR, ENRData, SignableENR} from "@chainsafe/enr";
5+
import {ENR, ENRData, SignableENR} from "@chainsafe/enr";
66
import {spawn, Thread, Worker} from "@chainsafe/threads";
77
import {chainConfigFromJson, chainConfigToJson, BeaconConfig} from "@lodestar/config";
88
import {LoggerNode} from "@lodestar/logger/node";
99
import {NetworkCoreMetrics} from "../core/metrics.js";
1010
import {Discv5WorkerApi, Discv5WorkerData, LodestarDiscv5Opts} from "./types.js";
1111

1212
export type Discv5Opts = {
13-
peerId: PeerId;
13+
privateKey: PrivateKey;
1414
discv5: LodestarDiscv5Opts;
1515
logger: LoggerNode;
1616
config: BeaconConfig;
@@ -25,7 +25,6 @@ export type Discv5Events = {
2525
* Wrapper class abstracting the details of discv5 worker instantiation and message-passing
2626
*/
2727
export class Discv5Worker extends (EventEmitter as {new (): StrictEventEmitter<EventEmitter, Discv5Events>}) {
28-
private readonly keypair;
2928
private readonly subscription: {unsubscribe: () => void};
3029
private closed = false;
3130

@@ -35,14 +34,13 @@ export class Discv5Worker extends (EventEmitter as {new (): StrictEventEmitter<E
3534
) {
3635
super();
3736

38-
this.keypair = createPrivateKeyFromPeerId(this.opts.peerId);
3937
this.subscription = workerApi.discovered().subscribe((enrObj) => this.onDiscovered(enrObj));
4038
}
4139

4240
static async init(opts: Discv5Opts): Promise<Discv5Worker> {
4341
const workerData: Discv5WorkerData = {
4442
enr: opts.discv5.enr,
45-
peerIdProto: exportToProtobuf(opts.peerId as Secp256k1PeerId),
43+
privateKeyProto: privateKeyToProtobuf(opts.privateKey),
4644
bindAddrs: opts.discv5.bindAddrs,
4745
config: opts.discv5.config ?? {},
4846
bootEnrs: opts.discv5.bootEnrs,
@@ -80,7 +78,7 @@ export class Discv5Worker extends (EventEmitter as {new (): StrictEventEmitter<E
8078

8179
async enr(): Promise<SignableENR> {
8280
const obj = await this.workerApi.enr();
83-
return new SignableENR(obj.kvs, obj.seq, this.keypair.privateKey);
81+
return new SignableENR(obj.kvs, obj.seq, this.opts.privateKey.raw);
8482
}
8583

8684
setEnrValue(key: string, value: Uint8Array): Promise<void> {

packages/beacon-node/src/network/discv5/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export type LodestarDiscv5Opts = {
3131
/** discv5 worker constructor data */
3232
export interface Discv5WorkerData {
3333
enr: string;
34-
peerIdProto: Uint8Array;
34+
privateKeyProto: Uint8Array;
3535
bindAddrs: BindAddrs;
3636
config: Discv5Config;
3737
bootEnrs: string[];

packages/beacon-node/src/network/discv5/worker.ts

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import worker from "node:worker_threads";
22
import path from "node:path";
33
import fs from "node:fs";
4-
import {createFromProtobuf} from "@libp2p/peer-id-factory";
54
import {Multiaddr, multiaddr} from "@multiformats/multiaddr";
65
import {expose} from "@chainsafe/threads/worker";
76
import {Observable, Subject} from "@chainsafe/threads/observable";
87
import {Discv5} from "@chainsafe/discv5";
9-
import {createPrivateKeyFromPeerId, ENR, ENRData, SignableENR, SignableENRData} from "@chainsafe/enr";
8+
import {ENR, ENRData, SignableENR, SignableENRData} from "@chainsafe/enr";
9+
import {privateKeyFromProtobuf} from "@libp2p/crypto/keys";
10+
import {peerIdFromPrivateKey} from "@libp2p/peer-id";
1011
import {createBeaconConfig} from "@lodestar/config";
1112
import {getNodeLogger} from "@lodestar/logger/node";
1213
import {Gauge} from "@lodestar/utils";
@@ -42,15 +43,15 @@ if (workerData.metrics) {
4243
});
4344
}
4445

45-
const peerId = await createFromProtobuf(workerData.peerIdProto);
46-
const keypair = createPrivateKeyFromPeerId(peerId);
46+
const privateKey = privateKeyFromProtobuf(workerData.privateKeyProto);
47+
const peerId = peerIdFromPrivateKey(privateKey);
4748

4849
const config = createBeaconConfig(workerData.chainConfig, workerData.genesisValidatorsRoot);
4950

5051
// Initialize discv5
5152
const discv5 = Discv5.create({
52-
enr: SignableENR.decodeTxt(workerData.enr, keypair.privateKey),
53-
peerId,
53+
enr: SignableENR.decodeTxt(workerData.enr, privateKey.raw),
54+
privateKey,
5455
bindAddrs: {
5556
ip4: (workerData.bindAddrs.ip4 ? multiaddr(workerData.bindAddrs.ip4) : undefined) as Multiaddr,
5657
ip6: workerData.bindAddrs.ip6 ? multiaddr(workerData.bindAddrs.ip6) : undefined,

packages/beacon-node/src/network/gossip/gossipsub.ts

+4
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ export class Eth2Gossipsub extends GossipSub {
135135
// if this is false, only publish to mesh peers. If there is not enough GOSSIP_D mesh peers,
136136
// publish to some more topic peers to make sure we always publish to at least GOSSIP_D peers
137137
floodPublish: !opts?.disableFloodPublish,
138+
// Only send IDONTWANT messages if the message size is larger than this
139+
// This should be large enough to not send IDONTWANT for "small" messages
140+
// See https://github.com/ChainSafe/lodestar/pull/7077#issuecomment-2383679472
141+
idontwantMinDataSize: 16829,
138142
});
139143
this.scoreParams = scoreParams;
140144
this.config = config;

packages/beacon-node/src/network/interface.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ import {
1212
PeerRouting,
1313
PeerStore,
1414
Upgrader,
15+
PrivateKey,
1516
} from "@libp2p/interface";
1617
import type {AddressManager, ConnectionManager, Registrar, TransportManager} from "@libp2p/interface-internal";
1718
import type {Datastore} from "interface-datastore";
18-
import {Identify} from "@chainsafe/libp2p-identify";
19+
import {Identify} from "@libp2p/identify";
1920
import {
2021
LightClientFinalityUpdate,
2122
LightClientOptimisticUpdate,
@@ -93,6 +94,7 @@ export interface INetwork extends INetworkCorePublic {
9394

9495
export type LodestarComponents = {
9596
peerId: PeerId;
97+
privateKey: PrivateKey;
9698
nodeInfo: NodeInfo;
9799
logger: ComponentLogger;
98100
events: TypedEventTarget<Libp2pEvents>;

packages/beacon-node/src/network/libp2p/index.ts

+10-11
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import {PeerId} from "@libp2p/interface";
1+
import {PrivateKey} from "@libp2p/interface";
22
import {Registry} from "prom-client";
33
import {ENR} from "@chainsafe/enr";
4-
// TODO: We should use this fork until https://github.com/libp2p/js-libp2p/pull/2387
5-
import {identify} from "@chainsafe/libp2p-identify";
4+
import {identify} from "@libp2p/identify";
65
import {bootstrap} from "@libp2p/bootstrap";
76
import {mdns} from "@libp2p/mdns";
87
import {createLibp2p} from "libp2p";
@@ -34,7 +33,7 @@ export async function getDiscv5Multiaddrs(bootEnrs: string[]): Promise<string[]>
3433
}
3534

3635
export async function createNodeJsLibp2p(
37-
peerId: PeerId,
36+
privateKey: PrivateKey,
3837
networkOpts: Partial<NetworkOptions> = {},
3938
nodeJsLibp2pOpts: NodeJsLibp2pOpts = {}
4039
): Promise<Libp2p> {
@@ -65,12 +64,12 @@ export async function createNodeJsLibp2p(
6564
}
6665

6766
return createLibp2p({
68-
peerId,
67+
privateKey,
6968
addresses: {
7069
listen: localMultiaddrs,
7170
announce: [],
7271
},
73-
connectionEncryption: [noise()],
72+
connectionEncrypters: [noise()],
7473
// Reject connections when the server's connection count gets high
7574
transports: [
7675
tcp({
@@ -99,15 +98,14 @@ export async function createNodeJsLibp2p(
9998
maxParallelDials: 100,
10099
maxPeerAddrsToDial: 4,
101100
dialTimeout: 30_000,
102-
103-
// Rely entirely on lodestar's peer manager to prune connections
104-
//maxConnections: options.maxConnections,
105-
// DOCS: There is no way to turn off autodial other than setting minConnections to 0
106-
minConnections: 0,
107101
// the maximum number of pending connections libp2p will accept before it starts rejecting incoming connections.
108102
// make it the same to backlog option above
109103
maxIncomingPendingConnections: 5,
110104
},
105+
// rely on lodestar's peer manager to ping peers
106+
connectionMonitor: {
107+
enabled: false,
108+
},
111109
datastore,
112110
services: {
113111
identify: identify({
@@ -118,6 +116,7 @@ export async function createNodeJsLibp2p(
118116
// and passing it here directly causes problems downstream, not to mention is slowwww
119117
components: (components: LodestarComponents) => ({
120118
peerId: components.peerId,
119+
privateKey: components.privateKey,
121120
nodeInfo: components.nodeInfo,
122121
logger: components.logger,
123122
events: components.events,

0 commit comments

Comments
 (0)