Skip to content

Commit

Permalink
chore: upgrade to js-libp2p 2.0 (#7077)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
wemeetagain authored and philknows committed Oct 18, 2024
1 parent ea8fc00 commit c01ff83
Show file tree
Hide file tree
Showing 41 changed files with 754 additions and 599 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"https-browserify": "^1.0.0",
"jsdom": "^23.0.1",
"lerna": "^7.3.0",
"libp2p": "1.4.3",
"libp2p": "2.1.7",
"mocha": "^10.2.0",
"node-gyp": "^9.4.0",
"npm-run-all": "^4.1.5",
Expand Down
35 changes: 17 additions & 18 deletions packages/beacon-node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,10 @@
"dependencies": {
"@chainsafe/as-sha256": "^0.5.0",
"@chainsafe/blst": "^2.0.3",
"@chainsafe/discv5": "^9.0.0",
"@chainsafe/enr": "^3.0.0",
"@chainsafe/libp2p-gossipsub": "^13.0.0",
"@chainsafe/libp2p-identify": "^1.0.0",
"@chainsafe/libp2p-noise": "^15.0.0",
"@chainsafe/discv5": "^10.0.1",
"@chainsafe/enr": "^4.0.1",
"@chainsafe/libp2p-gossipsub": "^14.1.0",
"@chainsafe/libp2p-noise": "^16.0.0",
"@chainsafe/persistent-merkle-tree": "^0.8.0",
"@chainsafe/prometheus-gc-stats": "^1.0.0",
"@chainsafe/ssz": "^0.17.1",
Expand All @@ -111,15 +110,15 @@
"@fastify/cors": "^10.0.1",
"@fastify/swagger": "^9.0.0",
"@fastify/swagger-ui": "^5.0.1",
"@libp2p/bootstrap": "^10.0.21",
"@libp2p/identify": "^1.0.20",
"@libp2p/interface": "^1.3.0",
"@libp2p/mdns": "^10.0.21",
"@libp2p/mplex": "^10.0.21",
"@libp2p/peer-id": "^4.1.0",
"@libp2p/peer-id-factory": "^4.1.0",
"@libp2p/prometheus-metrics": "^3.0.21",
"@libp2p/tcp": "9.0.23",
"@libp2p/bootstrap": "^11.0.4",
"@libp2p/crypto": "^5.0.4",
"@libp2p/identify": "^3.0.4",
"@libp2p/interface": "^2.1.2",
"@libp2p/mdns": "^11.0.4",
"@libp2p/mplex": "^11.0.4",
"@libp2p/peer-id": "^5.0.4",
"@libp2p/prometheus-metrics": "^4.1.2",
"@libp2p/tcp": "10.0.4",
"@lodestar/api": "^1.22.0",
"@lodestar/config": "^1.22.0",
"@lodestar/db": "^1.22.0",
Expand All @@ -134,15 +133,15 @@
"@lodestar/validator": "^1.22.0",
"@multiformats/multiaddr": "^12.1.3",
"c-kzg": "^2.1.2",
"datastore-core": "^9.1.1",
"datastore-level": "^10.1.1",
"datastore-core": "^10.0.0",
"datastore-level": "^11.0.0",
"deepmerge": "^4.3.1",
"fastify": "^5.0.0",
"interface-datastore": "^8.2.7",
"interface-datastore": "^8.3.0",
"it-all": "^3.0.4",
"it-pipe": "^3.0.1",
"jwt-simple": "0.5.6",
"libp2p": "1.4.3",
"libp2p": "2.1.7",
"multiformats": "^11.0.1",
"prom-client": "^15.1.0",
"qs": "^6.11.1",
Expand Down
17 changes: 11 additions & 6 deletions packages/beacon-node/src/network/core/networkCore.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Connection, PeerId} from "@libp2p/interface";
import {Connection, PrivateKey} from "@libp2p/interface";
import {multiaddr} from "@multiformats/multiaddr";
import {PublishOpts} from "@chainsafe/libp2p-gossipsub/types";
import {PeerScoreStatsDump} from "@chainsafe/libp2p-gossipsub/dist/src/score/peer-score.js";
Expand Down Expand Up @@ -55,7 +55,7 @@ type Mods = {
export type BaseNetworkInit = {
opts: NetworkOptions;
config: BeaconConfig;
peerId: PeerId;
privateKey: PrivateKey;
peerStoreDir: string | undefined;
logger: LoggerNode;
metricsRegistry: RegistryMetricCreator | null;
Expand Down Expand Up @@ -126,7 +126,7 @@ export class NetworkCore implements INetworkCore {
static async init({
opts,
config,
peerId,
privateKey,
peerStoreDir,
logger,
metricsRegistry,
Expand All @@ -136,7 +136,7 @@ export class NetworkCore implements INetworkCore {
activeValidatorCount,
initialStatus,
}: BaseNetworkInit): Promise<NetworkCore> {
const libp2p = await createNodeJsLibp2p(peerId, opts, {
const libp2p = await createNodeJsLibp2p(privateKey, opts, {
peerStoreDir,
metrics: Boolean(metricsRegistry),
metricsRegistry: metricsRegistry ?? undefined,
Expand Down Expand Up @@ -200,8 +200,9 @@ export class NetworkCore implements INetworkCore {

const peerManager = await PeerManager.init(
{
privateKey,
libp2p,
gossip: gossip,
gossip,
reqResp,
attnetsService,
syncnetsService,
Expand Down Expand Up @@ -359,7 +360,11 @@ export class NetworkCore implements INetworkCore {
}

getConnectionsByPeer(): Map<string, Connection[]> {
return getConnectionsMap(this.libp2p);
const m = new Map<string, Connection[]>();
for (const [k, v] of getConnectionsMap(this.libp2p).entries()) {
m.set(k, v.value);
}
return m;
}

async getConnectedPeers(): Promise<PeerIdStr[]> {
Expand Down
8 changes: 5 additions & 3 deletions packages/beacon-node/src/network/core/networkCoreWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import path from "node:path";
import worker from "node:worker_threads";
import type {ModuleThread} from "@chainsafe/threads";
import {expose} from "@chainsafe/threads/worker";
import {createFromProtobuf} from "@libp2p/peer-id-factory";
import {privateKeyFromProtobuf} from "@libp2p/crypto/keys";
import {peerIdFromPrivateKey} from "@libp2p/peer-id";
import {chainConfigFromJson, createBeaconConfig} from "@lodestar/config";
import {getNodeLogger} from "@lodestar/logger/node";
import {RegistryMetricCreator, collectNodeJSMetrics} from "../../metrics/index.js";
Expand Down Expand Up @@ -32,7 +33,8 @@ if (!workerData) throw Error("workerData must be defined");
if (!parentPort) throw Error("parentPort must be defined");

const config = createBeaconConfig(chainConfigFromJson(workerData.chainConfigJson), workerData.genesisValidatorsRoot);
const peerId = await createFromProtobuf(workerData.peerIdProto);
const privateKey = privateKeyFromProtobuf(workerData.privateKeyProto);
const peerId = peerIdFromPrivateKey(privateKey);

// TODO: Pass options from main thread for logging
// TODO: Logging won't be visible in file loggers
Expand Down Expand Up @@ -92,7 +94,7 @@ if (networkCoreWorkerMetrics) {
const core = await NetworkCore.init({
opts: workerData.opts,
config,
peerId,
privateKey,
peerStoreDir: workerData.peerStoreDir,
logger,
metricsRegistry: metricsRegister,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import workerThreads from "node:worker_threads";
import {PeerScoreStatsDump} from "@chainsafe/libp2p-gossipsub/dist/src/score/peer-score.js";
import {PublishOpts} from "@chainsafe/libp2p-gossipsub/types";
import {ModuleThread, Thread, Worker, spawn} from "@chainsafe/threads";
import {PeerId, Secp256k1PeerId} from "@libp2p/interface";
import {exportToProtobuf} from "@libp2p/peer-id-factory";
import {PrivateKey} from "@libp2p/interface";
import {privateKeyToProtobuf} from "@libp2p/crypto/keys";
import {routes} from "@lodestar/api";
import {BeaconConfig, chainConfigToJson} from "@lodestar/config";
import type {LoggerNode} from "@lodestar/logger/node";
Expand Down Expand Up @@ -44,7 +44,7 @@ export type WorkerNetworkCoreInitModules = {
opts: WorkerNetworkCoreOpts;
config: BeaconConfig;
logger: LoggerNode;
peerId: PeerId;
privateKey: PrivateKey;
events: NetworkEventBus;
metrics: Metrics | null;
getReqRespHandler: GetReqRespHandlerFn;
Expand Down Expand Up @@ -103,14 +103,14 @@ export class WorkerNetworkCore implements INetworkCore {
}

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

const workerData: NetworkWorkerData = {
opts,
chainConfigJson: chainConfigToJson(config),
genesisValidatorsRoot: config.genesisValidatorsRoot,
peerIdProto: exportToProtobuf(peerId as Secp256k1PeerId),
privateKeyProto: privateKeyToProtobuf(privateKey),
localMultiaddrs,
metricsEnabled,
peerStoreDir,
Expand Down
2 changes: 1 addition & 1 deletion packages/beacon-node/src/network/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export type NetworkWorkerData = {
genesisTime: number;
activeValidatorCount: number;
initialStatus: phase0.Status;
peerIdProto: Uint8Array;
privateKeyProto: Uint8Array;
localMultiaddrs: string[];
metricsEnabled: boolean;
peerStoreDir?: string;
Expand Down
14 changes: 6 additions & 8 deletions packages/beacon-node/src/network/discv5/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import EventEmitter from "node:events";
import {PeerId, Secp256k1PeerId} from "@libp2p/interface";
import {privateKeyToProtobuf} from "@libp2p/crypto/keys";
import {PrivateKey} from "@libp2p/interface";
import {StrictEventEmitter} from "strict-event-emitter-types";
import {exportToProtobuf} from "@libp2p/peer-id-factory";
import {createPrivateKeyFromPeerId, ENR, ENRData, SignableENR} from "@chainsafe/enr";
import {ENR, ENRData, SignableENR} from "@chainsafe/enr";
import {spawn, Thread, Worker} from "@chainsafe/threads";
import {chainConfigFromJson, chainConfigToJson, BeaconConfig} from "@lodestar/config";
import {LoggerNode} from "@lodestar/logger/node";
import {NetworkCoreMetrics} from "../core/metrics.js";
import {Discv5WorkerApi, Discv5WorkerData, LodestarDiscv5Opts} from "./types.js";

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

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

this.keypair = createPrivateKeyFromPeerId(this.opts.peerId);
this.subscription = workerApi.discovered().subscribe((enrObj) => this.onDiscovered(enrObj));
}

static async init(opts: Discv5Opts): Promise<Discv5Worker> {
const workerData: Discv5WorkerData = {
enr: opts.discv5.enr,
peerIdProto: exportToProtobuf(opts.peerId as Secp256k1PeerId),
privateKeyProto: privateKeyToProtobuf(opts.privateKey),
bindAddrs: opts.discv5.bindAddrs,
config: opts.discv5.config ?? {},
bootEnrs: opts.discv5.bootEnrs,
Expand Down Expand Up @@ -80,7 +78,7 @@ export class Discv5Worker extends (EventEmitter as {new (): StrictEventEmitter<E

async enr(): Promise<SignableENR> {
const obj = await this.workerApi.enr();
return new SignableENR(obj.kvs, obj.seq, this.keypair.privateKey);
return new SignableENR(obj.kvs, obj.seq, this.opts.privateKey.raw);
}

setEnrValue(key: string, value: Uint8Array): Promise<void> {
Expand Down
2 changes: 1 addition & 1 deletion packages/beacon-node/src/network/discv5/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export type LodestarDiscv5Opts = {
/** discv5 worker constructor data */
export interface Discv5WorkerData {
enr: string;
peerIdProto: Uint8Array;
privateKeyProto: Uint8Array;
bindAddrs: BindAddrs;
config: Discv5Config;
bootEnrs: string[];
Expand Down
13 changes: 7 additions & 6 deletions packages/beacon-node/src/network/discv5/worker.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import worker from "node:worker_threads";
import path from "node:path";
import fs from "node:fs";
import {createFromProtobuf} from "@libp2p/peer-id-factory";
import {Multiaddr, multiaddr} from "@multiformats/multiaddr";
import {expose} from "@chainsafe/threads/worker";
import {Observable, Subject} from "@chainsafe/threads/observable";
import {Discv5} from "@chainsafe/discv5";
import {createPrivateKeyFromPeerId, ENR, ENRData, SignableENR, SignableENRData} from "@chainsafe/enr";
import {ENR, ENRData, SignableENR, SignableENRData} from "@chainsafe/enr";
import {privateKeyFromProtobuf} from "@libp2p/crypto/keys";
import {peerIdFromPrivateKey} from "@libp2p/peer-id";
import {createBeaconConfig} from "@lodestar/config";
import {getNodeLogger} from "@lodestar/logger/node";
import {Gauge} from "@lodestar/utils";
Expand Down Expand Up @@ -42,15 +43,15 @@ if (workerData.metrics) {
});
}

const peerId = await createFromProtobuf(workerData.peerIdProto);
const keypair = createPrivateKeyFromPeerId(peerId);
const privateKey = privateKeyFromProtobuf(workerData.privateKeyProto);
const peerId = peerIdFromPrivateKey(privateKey);

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

// Initialize discv5
const discv5 = Discv5.create({
enr: SignableENR.decodeTxt(workerData.enr, keypair.privateKey),
peerId,
enr: SignableENR.decodeTxt(workerData.enr, privateKey.raw),
privateKey,
bindAddrs: {
ip4: (workerData.bindAddrs.ip4 ? multiaddr(workerData.bindAddrs.ip4) : undefined) as Multiaddr,
ip6: workerData.bindAddrs.ip6 ? multiaddr(workerData.bindAddrs.ip6) : undefined,
Expand Down
4 changes: 4 additions & 0 deletions packages/beacon-node/src/network/gossip/gossipsub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ export class Eth2Gossipsub extends GossipSub {
// if this is false, only publish to mesh peers. If there is not enough GOSSIP_D mesh peers,
// publish to some more topic peers to make sure we always publish to at least GOSSIP_D peers
floodPublish: !opts?.disableFloodPublish,
// Only send IDONTWANT messages if the message size is larger than this
// This should be large enough to not send IDONTWANT for "small" messages
// See https://github.com/ChainSafe/lodestar/pull/7077#issuecomment-2383679472
idontwantMinDataSize: 16829,
});
this.scoreParams = scoreParams;
this.config = config;
Expand Down
4 changes: 3 additions & 1 deletion packages/beacon-node/src/network/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ import {
PeerRouting,
PeerStore,
Upgrader,
PrivateKey,
} from "@libp2p/interface";
import type {AddressManager, ConnectionManager, Registrar, TransportManager} from "@libp2p/interface-internal";
import type {Datastore} from "interface-datastore";
import {Identify} from "@chainsafe/libp2p-identify";
import {Identify} from "@libp2p/identify";
import {
LightClientFinalityUpdate,
LightClientOptimisticUpdate,
Expand Down Expand Up @@ -93,6 +94,7 @@ export interface INetwork extends INetworkCorePublic {

export type LodestarComponents = {
peerId: PeerId;
privateKey: PrivateKey;
nodeInfo: NodeInfo;
logger: ComponentLogger;
events: TypedEventTarget<Libp2pEvents>;
Expand Down
21 changes: 10 additions & 11 deletions packages/beacon-node/src/network/libp2p/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import {PeerId} from "@libp2p/interface";
import {PrivateKey} from "@libp2p/interface";
import {Registry} from "prom-client";
import {ENR} from "@chainsafe/enr";
// TODO: We should use this fork until https://github.com/libp2p/js-libp2p/pull/2387
import {identify} from "@chainsafe/libp2p-identify";
import {identify} from "@libp2p/identify";
import {bootstrap} from "@libp2p/bootstrap";
import {mdns} from "@libp2p/mdns";
import {createLibp2p} from "libp2p";
Expand Down Expand Up @@ -34,7 +33,7 @@ export async function getDiscv5Multiaddrs(bootEnrs: string[]): Promise<string[]>
}

export async function createNodeJsLibp2p(
peerId: PeerId,
privateKey: PrivateKey,
networkOpts: Partial<NetworkOptions> = {},
nodeJsLibp2pOpts: NodeJsLibp2pOpts = {}
): Promise<Libp2p> {
Expand Down Expand Up @@ -65,12 +64,12 @@ export async function createNodeJsLibp2p(
}

return createLibp2p({
peerId,
privateKey,
addresses: {
listen: localMultiaddrs,
announce: [],
},
connectionEncryption: [noise()],
connectionEncrypters: [noise()],
// Reject connections when the server's connection count gets high
transports: [
tcp({
Expand Down Expand Up @@ -99,15 +98,14 @@ export async function createNodeJsLibp2p(
maxParallelDials: 100,
maxPeerAddrsToDial: 4,
dialTimeout: 30_000,

// Rely entirely on lodestar's peer manager to prune connections
//maxConnections: options.maxConnections,
// DOCS: There is no way to turn off autodial other than setting minConnections to 0
minConnections: 0,
// the maximum number of pending connections libp2p will accept before it starts rejecting incoming connections.
// make it the same to backlog option above
maxIncomingPendingConnections: 5,
},
// rely on lodestar's peer manager to ping peers
connectionMonitor: {
enabled: false,
},
datastore,
services: {
identify: identify({
Expand All @@ -118,6 +116,7 @@ export async function createNodeJsLibp2p(
// and passing it here directly causes problems downstream, not to mention is slowwww
components: (components: LodestarComponents) => ({
peerId: components.peerId,
privateKey: components.privateKey,
nodeInfo: components.nodeInfo,
logger: components.logger,
events: components.events,
Expand Down
Loading

0 comments on commit c01ff83

Please sign in to comment.