From 47444f896efa6d17443df23371389a986a65882b Mon Sep 17 00:00:00 2001 From: Mohammad Kermani Date: Sat, 29 Jun 2024 11:53:01 +0000 Subject: [PATCH 1/7] fix(utils): append unused format parameters --- packages/utils/lib/logger/format.ts | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/utils/lib/logger/format.ts b/packages/utils/lib/logger/format.ts index f113116..a651058 100644 --- a/packages/utils/lib/logger/format.ts +++ b/packages/utils/lib/logger/format.ts @@ -43,15 +43,19 @@ const formatters = { const format = (str: string, ...args: any[]) => { let j = 0; - return str.replace(/%([a-z])/gi, (match, f: keyof typeof formatters) => { - if (formatters[f]) { - return formatters[f](args[j++]); - } - if (f) { - return utilFormat(`%${f}`, args[j++]); - } - return match; - }); + const formatted = str.replace( + /%([a-z])/gi, + (match, f: keyof typeof formatters) => { + if (formatters[f]) { + return formatters[f](args[j++]); + } + if (f) { + return utilFormat(`%${f}`, args[j++]); + } + return match; + }, + ); + return `${formatted} ${args.slice(j).join(' ')}`.trimEnd(); }; export default format; From 44c6d3e10b65faa0b4b8b1ac104ce60d1e6a69c0 Mon Sep 17 00:00:00 2001 From: Mohammad Kermani Date: Wed, 14 Aug 2024 13:28:17 +0000 Subject: [PATCH 2/7] refactor(rosenet-node, rosenet-relay): switch from `mplex` to `yamux` Based on the docs, `mplex` is going to be deprecated in favor of `yamux`. --- .changeset/modern-hairs-scream.md | 5 ++++ .changeset/tame-queens-study.md | 6 +++++ package-lock.json | 25 +++++++++++++++++++ .../rosenet-node/lib/createRoseNetNode.ts | 4 +-- packages/rosenet-node/package.json | 2 +- .../rosenet-relay/lib/createRoseNetRelay.ts | 4 +-- packages/rosenet-relay/package.json | 2 +- 7 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 .changeset/modern-hairs-scream.md create mode 100644 .changeset/tame-queens-study.md diff --git a/.changeset/modern-hairs-scream.md b/.changeset/modern-hairs-scream.md new file mode 100644 index 0000000..12042f0 --- /dev/null +++ b/.changeset/modern-hairs-scream.md @@ -0,0 +1,5 @@ +--- +'@rosen-bridge/rosenet-utils': patch +--- + +Append unused format parameters to format function diff --git a/.changeset/tame-queens-study.md b/.changeset/tame-queens-study.md new file mode 100644 index 0000000..66ff1b0 --- /dev/null +++ b/.changeset/tame-queens-study.md @@ -0,0 +1,6 @@ +--- +'@rosen-bridge/rosenet-relay': minor +'@rosen-bridge/rosenet-node': minor +--- + +Switch from mplex to yamux for multiplexing diff --git a/package-lock.json b/package-lock.json index a182aad..2ad1be2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -645,6 +645,20 @@ "npm": ">=7.0.0" } }, + "node_modules/@chainsafe/libp2p-yamux": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@chainsafe/libp2p-yamux/-/libp2p-yamux-6.0.2.tgz", + "integrity": "sha512-S5OkLHqYhEVMQQ4BTgnRANEIbGTQhaC23glCgBwGdeoTRtMpIozwDiPfljFLCm0RYWdCRJw9oFztO95KUHjptA==", + "dependencies": { + "@libp2p/interface": "^1.1.3", + "@libp2p/utils": "^5.2.5", + "get-iterator": "^2.0.1", + "it-foreach": "^2.0.6", + "it-pipe": "^3.0.1", + "it-pushable": "^3.2.3", + "uint8arraylist": "^2.4.8" + } + }, "node_modules/@chainsafe/netmask": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@chainsafe/netmask/-/netmask-2.0.0.tgz", @@ -5656,6 +5670,14 @@ "resolved": "https://registry.npmjs.org/it-first/-/it-first-3.0.4.tgz", "integrity": "sha512-FtQl84iTNxN5EItP/JgL28V2rzNMkCzTUlNoj41eVdfix2z1DBuLnBqZ0hzYhGGa1rMpbQf0M7CQSA2adlrLJg==" }, + "node_modules/it-foreach": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/it-foreach/-/it-foreach-2.1.1.tgz", + "integrity": "sha512-ID4Gxnavk/LVQLQESAQ9hR6dR63Ih6X+8VdxEktX8rpz2dCGAbZpey/eljTNbMfV2UKXHiu6UsneoNBZuac97g==", + "dependencies": { + "it-peekable": "^3.0.0" + } + }, "node_modules/it-length-prefixed": { "version": "9.0.4", "resolved": "https://registry.npmjs.org/it-length-prefixed/-/it-length-prefixed-9.0.4.tgz", @@ -9380,6 +9402,7 @@ "dependencies": { "@chainsafe/libp2p-gossipsub": "^12.0.0", "@chainsafe/libp2p-noise": "^15.0.0", + "@chainsafe/libp2p-yamux": "^6.0.2", "@libp2p/bootstrap": "^10.0.15", "@libp2p/circuit-relay-v2": "^1.0.15", "@libp2p/identify": "^1.0.14", @@ -9664,6 +9687,7 @@ "dependencies": { "@chainsafe/libp2p-gossipsub": "^12.0.0", "@chainsafe/libp2p-noise": "^15.0.0", + "@chainsafe/libp2p-yamux": "^6.0.2", "@libp2p/circuit-relay-v2": "^1.0.15", "@libp2p/identify": "^1.0.14", "@libp2p/interface": "^1.1.3", @@ -10065,6 +10089,7 @@ } }, "tests/scaling-large-messages": { + "name": "@rosenet-tests/scaling-large-messages", "version": "0.0.0", "license": "GPL-3.0", "dependencies": { diff --git a/packages/rosenet-node/lib/createRoseNetNode.ts b/packages/rosenet-node/lib/createRoseNetNode.ts index 458059d..6b8ccad 100644 --- a/packages/rosenet-node/lib/createRoseNetNode.ts +++ b/packages/rosenet-node/lib/createRoseNetNode.ts @@ -4,7 +4,7 @@ import { bootstrap } from '@libp2p/bootstrap'; import { circuitRelayTransport } from '@libp2p/circuit-relay-v2'; import { identify } from '@libp2p/identify'; import { PeerId } from '@libp2p/interface'; -import { mplex } from '@libp2p/mplex'; +import { yamux } from '@chainsafe/libp2p-yamux'; import { pubsubPeerDiscovery } from '@libp2p/pubsub-peer-discovery'; import { tcp } from '@libp2p/tcp'; import map from 'it-map'; @@ -95,7 +95,7 @@ const createRoseNetNode = async ({ denyDialPeer: isPeerUnauthorized, }), }, - streamMuxers: [mplex()], + streamMuxers: [yamux()], peerDiscovery: [ bootstrap({ list: config.relayMultiaddrs, diff --git a/packages/rosenet-node/package.json b/packages/rosenet-node/package.json index 39be0d3..171b287 100644 --- a/packages/rosenet-node/package.json +++ b/packages/rosenet-node/package.json @@ -37,10 +37,10 @@ "dependencies": { "@chainsafe/libp2p-gossipsub": "^12.0.0", "@chainsafe/libp2p-noise": "^15.0.0", + "@chainsafe/libp2p-yamux": "^6.0.2", "@libp2p/bootstrap": "^10.0.15", "@libp2p/circuit-relay-v2": "^1.0.15", "@libp2p/identify": "^1.0.14", - "@libp2p/mplex": "^10.0.15", "@libp2p/peer-id": "^4.0.6", "@libp2p/pubsub-peer-discovery": "^10.0.2", "@libp2p/tcp": "^9.0.15", diff --git a/packages/rosenet-relay/lib/createRoseNetRelay.ts b/packages/rosenet-relay/lib/createRoseNetRelay.ts index 031b33b..ab435be 100644 --- a/packages/rosenet-relay/lib/createRoseNetRelay.ts +++ b/packages/rosenet-relay/lib/createRoseNetRelay.ts @@ -3,7 +3,7 @@ import { noise } from '@chainsafe/libp2p-noise'; import { circuitRelayServer } from '@libp2p/circuit-relay-v2'; import { identify } from '@libp2p/identify'; import { PeerId } from '@libp2p/interface'; -import { mplex } from '@libp2p/mplex'; +import { yamux } from '@chainsafe/libp2p-yamux'; import { pubsubPeerDiscovery } from '@libp2p/pubsub-peer-discovery'; import { tcp } from '@libp2p/tcp'; import { createLibp2p } from 'libp2p'; @@ -63,7 +63,7 @@ const createRoseNetRelay = async ({ denyInboundRelayedConnection: () => true, denyDialPeer: isPeerUnauthorized, }, - streamMuxers: [mplex()], + streamMuxers: [yamux()], services: { circuitRelay: circuitRelayServer({ reservations: { diff --git a/packages/rosenet-relay/package.json b/packages/rosenet-relay/package.json index 03d20bb..ef7cfa9 100644 --- a/packages/rosenet-relay/package.json +++ b/packages/rosenet-relay/package.json @@ -35,10 +35,10 @@ "dependencies": { "@chainsafe/libp2p-gossipsub": "^12.0.0", "@chainsafe/libp2p-noise": "^15.0.0", + "@chainsafe/libp2p-yamux": "^6.0.2", "@libp2p/circuit-relay-v2": "^1.0.15", "@libp2p/identify": "^1.0.14", "@libp2p/interface": "^1.1.3", - "@libp2p/mplex": "^10.0.15", "@libp2p/pubsub-peer-discovery": "^10.0.2", "@libp2p/tcp": "^9.0.15", "@rosen-bridge/logger-interface": "^0.2.0", From 8f842b95835043ee6bc41e8f5427d592578d0a49 Mon Sep 17 00:00:00 2001 From: Mohammad Kermani Date: Sun, 18 Aug 2024 08:21:42 +0000 Subject: [PATCH 3/7] refactor(rosenet-node, rosenet-relay): disable `runOnTransientConnection` Running Gossipsub on relayed connections adds a considerable network overhead to relays. --- packages/rosenet-node/lib/createRoseNetNode.ts | 1 - packages/rosenet-relay/lib/createRoseNetRelay.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/rosenet-node/lib/createRoseNetNode.ts b/packages/rosenet-node/lib/createRoseNetNode.ts index 6b8ccad..0e785a1 100644 --- a/packages/rosenet-node/lib/createRoseNetNode.ts +++ b/packages/rosenet-node/lib/createRoseNetNode.ts @@ -110,7 +110,6 @@ const createRoseNetNode = async ({ identify: identify(), pubsub: gossipsub({ allowPublishToZeroPeers: true, - runOnTransientConnection: true, }), }, logger: libp2pLoggerFactory(logger, config.debug?.libp2pComponents ?? []), diff --git a/packages/rosenet-relay/lib/createRoseNetRelay.ts b/packages/rosenet-relay/lib/createRoseNetRelay.ts index ab435be..f948540 100644 --- a/packages/rosenet-relay/lib/createRoseNetRelay.ts +++ b/packages/rosenet-relay/lib/createRoseNetRelay.ts @@ -75,7 +75,6 @@ const createRoseNetRelay = async ({ }), pubsub: gossipsub({ allowPublishToZeroPeers: true, - runOnTransientConnection: true, }), identify: identify(), }, From d392e11e64b5e43b9a194e10ff31760716e0fd0b Mon Sep 17 00:00:00 2001 From: Mohammad Kermani Date: Sun, 18 Aug 2024 12:01:03 +0330 Subject: [PATCH 4/7] refactor(rosenet-relay): add `subscribe` to the public API Because `runOnTransientConnection` is disabled, relays should actively participate in the protocol as bootstrappers. --- packages/rosenet-relay/lib/createRoseNetRelay.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/rosenet-relay/lib/createRoseNetRelay.ts b/packages/rosenet-relay/lib/createRoseNetRelay.ts index f948540..431046f 100644 --- a/packages/rosenet-relay/lib/createRoseNetRelay.ts +++ b/packages/rosenet-relay/lib/createRoseNetRelay.ts @@ -92,6 +92,15 @@ const createRoseNetRelay = async ({ return { start: async () => node.start(), + subscribe: async (topic: string, handler: (message: string) => void) => { + node.services.pubsub.subscribe(topic); + node.services.pubsub.addEventListener('message', (event) => { + if (event.detail.topic === topic) { + const textDecoder = new TextDecoder(); + handler(textDecoder.decode(event.detail.data)); + } + }); + }, }; }; From d7f66e7374409767f7f319c325a48423f0e53ff8 Mon Sep 17 00:00:00 2001 From: Mohammad Kermani Date: Sun, 18 Aug 2024 12:02:33 +0330 Subject: [PATCH 5/7] refactor(rosenet-relay): make relays only gossip As Gossipsub bootstrappers, the relays should only gossip without keeping full-message connections with other nodes. --- packages/rosenet-relay/lib/createRoseNetRelay.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/rosenet-relay/lib/createRoseNetRelay.ts b/packages/rosenet-relay/lib/createRoseNetRelay.ts index 431046f..40585bd 100644 --- a/packages/rosenet-relay/lib/createRoseNetRelay.ts +++ b/packages/rosenet-relay/lib/createRoseNetRelay.ts @@ -75,6 +75,10 @@ const createRoseNetRelay = async ({ }), pubsub: gossipsub({ allowPublishToZeroPeers: true, + D: 0, + Dlo: 0, + Dhi: 0, + Dout: 0, }), identify: identify(), }, From c1e300832011b219c2838b090738b3168524b4ec Mon Sep 17 00:00:00 2001 From: Mohammad Kermani Date: Sun, 18 Aug 2024 12:18:17 +0330 Subject: [PATCH 6/7] feat(rosenet-node, rosenet-relay): limit relays count for nodes Connecting to a lot of relays can significantly affect pubsub network traffic. For 40 nodes, 3 relay per node seems a good balance between traffic, delivery and performance. This number may change in the future, though. Also prevent relays from broadcasting their addresses over discovery network. If not disable, it totally negates the point of limiting relays count to 3. --- packages/rosenet-node/lib/createRoseNetNode.ts | 12 +++++++++--- packages/rosenet-node/lib/utils/sample.ts | 13 +++++++++++++ packages/rosenet-relay/lib/createRoseNetRelay.ts | 2 +- 3 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 packages/rosenet-node/lib/utils/sample.ts diff --git a/packages/rosenet-node/lib/createRoseNetNode.ts b/packages/rosenet-node/lib/createRoseNetNode.ts index 0e785a1..d1f5ad5 100644 --- a/packages/rosenet-node/lib/createRoseNetNode.ts +++ b/packages/rosenet-node/lib/createRoseNetNode.ts @@ -23,6 +23,7 @@ import addressService from './address/address-service'; import streamService from './stream/stream-service'; import { decode, encode } from './utils/codec'; +import sample from './utils/sample'; import RoseNetNodeError from './errors/RoseNetNodeError'; @@ -61,6 +62,11 @@ const createRoseNetNode = async ({ const announceMultiaddr = await addressService.getAnnounceMultiaddr(port); logger.info(`${announceMultiaddr} set as announce multiaddr`); + const sampledRelayMultiaddrs = sample( + config.relayMultiaddrs, + RELAYS_COUNT_TO_CONNECT, + ); + const node = await createLibp2p({ peerId, transports: [ @@ -72,13 +78,13 @@ const createRoseNetNode = async ({ addresses: { listen: [ `/ip4/0.0.0.0/tcp/${port}`, - ...config.relayMultiaddrs.map( + ...sampledRelayMultiaddrs.map( (multiaddr) => `${multiaddr}/p2p-circuit`, ), ], announce: [ announceMultiaddr, - ...config.relayMultiaddrs.map( + ...sampledRelayMultiaddrs.map( (multiaddr) => `${multiaddr}/p2p-circuit`, ), ], @@ -98,7 +104,7 @@ const createRoseNetNode = async ({ streamMuxers: [yamux()], peerDiscovery: [ bootstrap({ - list: config.relayMultiaddrs, + list: sampledRelayMultiaddrs, }), pubsubPeerDiscovery(), ], diff --git a/packages/rosenet-node/lib/utils/sample.ts b/packages/rosenet-node/lib/utils/sample.ts new file mode 100644 index 0000000..f986386 --- /dev/null +++ b/packages/rosenet-node/lib/utils/sample.ts @@ -0,0 +1,13 @@ +/** + * Sample `size` elements from `array` randomly + * @param array + * @param size + */ +const sample = (array: T[], size: number): T[] => + array + .map((value) => ({ value, sort: Math.random() })) + .sort((a, b) => a.sort - b.sort) + .map(({ value }) => value) + .slice(0, size); + +export default sample; diff --git a/packages/rosenet-relay/lib/createRoseNetRelay.ts b/packages/rosenet-relay/lib/createRoseNetRelay.ts index 40585bd..2caad00 100644 --- a/packages/rosenet-relay/lib/createRoseNetRelay.ts +++ b/packages/rosenet-relay/lib/createRoseNetRelay.ts @@ -82,7 +82,7 @@ const createRoseNetRelay = async ({ }), identify: identify(), }, - peerDiscovery: [pubsubPeerDiscovery()], + peerDiscovery: [pubsubPeerDiscovery({ listenOnly: true })], nodeInfo: { name: 'rosenet-relay', version: packageJson.version, From 3142e08c90ef2dfa8c5d03b24caa15945fdce474 Mon Sep 17 00:00:00 2001 From: Mohammad Kermani Date: Sun, 18 Aug 2024 12:24:45 +0330 Subject: [PATCH 7/7] chore: add multiple changesets --- .changeset/cool-snakes-perform.md | 6 ++++++ .changeset/empty-lobsters-pump.md | 5 +++++ .changeset/long-hornets-swim.md | 5 +++++ .changeset/wet-tomatoes-nail.md | 6 ++++++ 4 files changed, 22 insertions(+) create mode 100644 .changeset/cool-snakes-perform.md create mode 100644 .changeset/empty-lobsters-pump.md create mode 100644 .changeset/long-hornets-swim.md create mode 100644 .changeset/wet-tomatoes-nail.md diff --git a/.changeset/cool-snakes-perform.md b/.changeset/cool-snakes-perform.md new file mode 100644 index 0000000..e573b74 --- /dev/null +++ b/.changeset/cool-snakes-perform.md @@ -0,0 +1,6 @@ +--- +'@rosen-bridge/rosenet-relay': minor +'@rosen-bridge/rosenet-node': minor +--- + +Limit node connections to relay to 3 to prevent network traffic issues diff --git a/.changeset/empty-lobsters-pump.md b/.changeset/empty-lobsters-pump.md new file mode 100644 index 0000000..09bfc8d --- /dev/null +++ b/.changeset/empty-lobsters-pump.md @@ -0,0 +1,5 @@ +--- +'@rosen-bridge/rosenet-relay': minor +--- + +Add `subscribe` function for subscribing to a pubsub topic diff --git a/.changeset/long-hornets-swim.md b/.changeset/long-hornets-swim.md new file mode 100644 index 0000000..d11259b --- /dev/null +++ b/.changeset/long-hornets-swim.md @@ -0,0 +1,5 @@ +--- +'@rosen-bridge/rosenet-relay': minor +--- + +Configuare relays as Gossipsub bootstrappers diff --git a/.changeset/wet-tomatoes-nail.md b/.changeset/wet-tomatoes-nail.md new file mode 100644 index 0000000..e36423e --- /dev/null +++ b/.changeset/wet-tomatoes-nail.md @@ -0,0 +1,6 @@ +--- +'@rosen-bridge/rosenet-relay': minor +'@rosen-bridge/rosenet-node': minor +--- + +Prevent Gossipsub from running on transient connections