From e5c6814f520595c39e579bd1f2b3153e1a4d09c2 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 11 Sep 2024 09:46:52 +0100 Subject: [PATCH] chore: add relay --- perf/README.md | 15 +- perf/impl/js-libp2p/v1.0-webrtc-16kb/index.js | 108 -- perf/impl/js-libp2p/v1.0-webrtc-16kb/perf | 12 +- .../impl/js-libp2p/v1.0-webrtc-256kb/index.js | 108 -- perf/impl/js-libp2p/v1.0-webrtc-256kb/perf | 12 +- .../impl/js-libp2p/v1.0-webrtc-256kb/relay.js | 39 - perf/relay/Makefile | 9 + .../relay.js => relay/index.js} | 9 +- perf/relay/package-lock.json | 1083 +++++++++++++++++ perf/relay/package.json | 17 + perf/relay/relay | 29 + perf/runner/src/index.ts | 191 +-- perf/runner/src/versions.ts | 7 - 13 files changed, 1263 insertions(+), 376 deletions(-) delete mode 100644 perf/impl/js-libp2p/v1.0-webrtc-16kb/index.js delete mode 100644 perf/impl/js-libp2p/v1.0-webrtc-256kb/index.js delete mode 100644 perf/impl/js-libp2p/v1.0-webrtc-256kb/relay.js create mode 100644 perf/relay/Makefile rename perf/{impl/js-libp2p/v1.0-webrtc-16kb/relay.js => relay/index.js} (83%) create mode 100644 perf/relay/package-lock.json create mode 100644 perf/relay/package.json create mode 100755 perf/relay/relay diff --git a/perf/README.md b/perf/README.md index b2e50d5b2..b11df8586 100644 --- a/perf/README.md +++ b/perf/README.md @@ -68,28 +68,21 @@ Given you have provisioned your infrastructure, you can now build and run the li - For a new version of an existing implementation, create a folder `impl//`. - In that folder include a `Makefile` that builds an executable and stores it next to the `Makefile` under the name `perf`. - Requirements for the executable: - - Running as a libp2p circuit relay server: - - The relay server must not exit as it will be closed by the test runner. - - Input via command line - - `--role relay` - - `--external-ip` the external IP the container is reachable on - - `--listen-port` the port to listen on - - The relay server should write the multiaddr it is dialable on to stdout - Running as a libp2p-perf server: - The perf server must not exit as it will be closed by the test runner. + - The executable must accept the command flag `--run-server` which indicates it's running as server. - Input via command line - - `--role listener` - `--external-ip` the external IP the container is reachable on - `--listen-port` the port to listen on - `--relay-address` if a relay was started as part of the test run, this is the multiadr it is listening on - `--transport` (see [`runner/versions.ts`](./runner/src/versions.ts#L7-L43) for possible variants) - `--platform` optionally specify what to run the code on (browsers, electron, etc) - - The listener should write the multiaddr it is dialable on to stdout + - The server should write the multiaddr it is dialable on to stdout to populate the `--server-address` option passed to the client + - If it does not `--server-address` will be set to a `host_ip:host_port` pair for the server - Running as a libp2p-perf client - Given that perf is a client driven set of benchmarks, the performance will be measured by the client. - Input via command line - - `--role dialer` - - `--listener-address` the multiaddr to dial to reach the listener + - `--server-address` the multiaddr to dial to reach the server - `--transport` (see [`runner/versions.ts`](./runner/src/versions.ts#L7-L43) for possible variants) - `--upload-bytes` number of bytes to upload per stream. - `--download-bytes` number of bytes to download per stream. diff --git a/perf/impl/js-libp2p/v1.0-webrtc-16kb/index.js b/perf/impl/js-libp2p/v1.0-webrtc-16kb/index.js deleted file mode 100644 index 716239add..000000000 --- a/perf/impl/js-libp2p/v1.0-webrtc-16kb/index.js +++ /dev/null @@ -1,108 +0,0 @@ -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { tcp } from '@libp2p/tcp' -import { multiaddr } from '@multiformats/multiaddr' -import { createLibp2p } from 'libp2p' -import { perf } from '@libp2p/perf' -import { parseArgs } from 'node:util' - -const argv = parseArgs({ - options: { - 'run-server': { - type: 'string', - default: 'false' - }, - 'server-address': { - type: 'string' - }, - transport: { - type: 'string', - default: 'tcp' - }, - 'upload-bytes': { - type: 'string', - default: '0' - }, - 'download-bytes': { - type: 'string', - default: '0' - } - } -}) - -/** - * @param {boolean} runServer - * @param {string} serverIpAddress - * @param {string} transport - * @param {number} uploadBytes - * @param {number} downloadBytes - */ -export async function main (runServer, serverIpAddress, transport, uploadBytes, downloadBytes) { - const { host, port } = splitHostPort(serverIpAddress) - - const config = { - transports: [ - tcp() - ], - streamMuxers: [ - yamux() - ], - connectionEncryption: [ - noise() - ], - connectionManager: { - minConnections: 0 - }, - services: { - perf: perf() - } - } - - if (runServer) { - Object.assign(config, { - addresses: { - listen: [ - // #TODO: right now we only support tcp - `/ip4/${host}/tcp/${port}` - ] - } - }) - } - - const node = await createLibp2p(config) - - await node.start() - - if (!runServer) { - for await (const output of node.services.perf.measurePerformance(multiaddr(`/ip4/${host}/tcp/${port}`), uploadBytes, downloadBytes)) { - // eslint-disable-next-line no-console - console.log(JSON.stringify(output)) - } - - await node.stop() - } -} - -/** - * @param {string} address - * @returns { host: string, port?: string } - */ -function splitHostPort (address) { - try { - const parts = address.split(':') - const host = parts[0] - const port = parts[1] - return { - host, - port - } - } catch (error) { - throw Error('Invalid server address') - } -} - -main(argv.values['run-server'] === 'true', argv.values['server-address'], argv.values.transport, Number(argv.values['upload-bytes']), Number(argv.values['download-bytes'])).catch((err) => { - // eslint-disable-next-line no-console - console.error(err) - process.exit(1) -}) diff --git a/perf/impl/js-libp2p/v1.0-webrtc-16kb/perf b/perf/impl/js-libp2p/v1.0-webrtc-16kb/perf index f06e640cd..f519e9a63 100755 --- a/perf/impl/js-libp2p/v1.0-webrtc-16kb/perf +++ b/perf/impl/js-libp2p/v1.0-webrtc-16kb/perf @@ -7,7 +7,7 @@ cleanup() { } trap cleanup EXIT TERM -role="" +role="dialer" platform="" # Parse named parameters manually @@ -21,7 +21,7 @@ for ((i = 1; i <= $#; i++)); do if [ "${!i}" == "--relay-address" ]; then export RELAY_ADDRESS="${@:i+1:1}" fi - if [ "${!i}" == "--listener-address" ]; then + if [ "${!i}" == "--server-address" ]; then export LISTENER_ADDRESS="${@:i+1:1}" fi if [ "${!i}" == "--upload-bytes" ]; then @@ -33,8 +33,8 @@ for ((i = 1; i <= $#; i++)); do if [ "${!i}" == "--transport" ]; then export TRANSPORT="${@:i+1:1}" fi - if [ "${!i}" == "--role" ]; then - role="${@:i+1:1}" + if [ "${!i}" == "--run-server" ]; then + role="listener" fi if [ "${!i}" == "--platform" ]; then platform="${@:i+1:1}" @@ -44,9 +44,7 @@ done cd $(dirname "$0") # start something -if [ "${role}" == "relay" ]; then - node relay.js & -elif [ "${role}" == "listener" ]; then +if [ "${role}" == "listener" ]; then if [ "${platform}" == "chromium" ] || [ "${platform}" == "firefox" ] || [ "${platform}" == "webkit" ]; then if [ $RELAY_ADDRESS == "" ]; then echo ERROR: a relay address is required to run a browser listener 1>&2 diff --git a/perf/impl/js-libp2p/v1.0-webrtc-256kb/index.js b/perf/impl/js-libp2p/v1.0-webrtc-256kb/index.js deleted file mode 100644 index 716239add..000000000 --- a/perf/impl/js-libp2p/v1.0-webrtc-256kb/index.js +++ /dev/null @@ -1,108 +0,0 @@ -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { tcp } from '@libp2p/tcp' -import { multiaddr } from '@multiformats/multiaddr' -import { createLibp2p } from 'libp2p' -import { perf } from '@libp2p/perf' -import { parseArgs } from 'node:util' - -const argv = parseArgs({ - options: { - 'run-server': { - type: 'string', - default: 'false' - }, - 'server-address': { - type: 'string' - }, - transport: { - type: 'string', - default: 'tcp' - }, - 'upload-bytes': { - type: 'string', - default: '0' - }, - 'download-bytes': { - type: 'string', - default: '0' - } - } -}) - -/** - * @param {boolean} runServer - * @param {string} serverIpAddress - * @param {string} transport - * @param {number} uploadBytes - * @param {number} downloadBytes - */ -export async function main (runServer, serverIpAddress, transport, uploadBytes, downloadBytes) { - const { host, port } = splitHostPort(serverIpAddress) - - const config = { - transports: [ - tcp() - ], - streamMuxers: [ - yamux() - ], - connectionEncryption: [ - noise() - ], - connectionManager: { - minConnections: 0 - }, - services: { - perf: perf() - } - } - - if (runServer) { - Object.assign(config, { - addresses: { - listen: [ - // #TODO: right now we only support tcp - `/ip4/${host}/tcp/${port}` - ] - } - }) - } - - const node = await createLibp2p(config) - - await node.start() - - if (!runServer) { - for await (const output of node.services.perf.measurePerformance(multiaddr(`/ip4/${host}/tcp/${port}`), uploadBytes, downloadBytes)) { - // eslint-disable-next-line no-console - console.log(JSON.stringify(output)) - } - - await node.stop() - } -} - -/** - * @param {string} address - * @returns { host: string, port?: string } - */ -function splitHostPort (address) { - try { - const parts = address.split(':') - const host = parts[0] - const port = parts[1] - return { - host, - port - } - } catch (error) { - throw Error('Invalid server address') - } -} - -main(argv.values['run-server'] === 'true', argv.values['server-address'], argv.values.transport, Number(argv.values['upload-bytes']), Number(argv.values['download-bytes'])).catch((err) => { - // eslint-disable-next-line no-console - console.error(err) - process.exit(1) -}) diff --git a/perf/impl/js-libp2p/v1.0-webrtc-256kb/perf b/perf/impl/js-libp2p/v1.0-webrtc-256kb/perf index f06e640cd..f519e9a63 100755 --- a/perf/impl/js-libp2p/v1.0-webrtc-256kb/perf +++ b/perf/impl/js-libp2p/v1.0-webrtc-256kb/perf @@ -7,7 +7,7 @@ cleanup() { } trap cleanup EXIT TERM -role="" +role="dialer" platform="" # Parse named parameters manually @@ -21,7 +21,7 @@ for ((i = 1; i <= $#; i++)); do if [ "${!i}" == "--relay-address" ]; then export RELAY_ADDRESS="${@:i+1:1}" fi - if [ "${!i}" == "--listener-address" ]; then + if [ "${!i}" == "--server-address" ]; then export LISTENER_ADDRESS="${@:i+1:1}" fi if [ "${!i}" == "--upload-bytes" ]; then @@ -33,8 +33,8 @@ for ((i = 1; i <= $#; i++)); do if [ "${!i}" == "--transport" ]; then export TRANSPORT="${@:i+1:1}" fi - if [ "${!i}" == "--role" ]; then - role="${@:i+1:1}" + if [ "${!i}" == "--run-server" ]; then + role="listener" fi if [ "${!i}" == "--platform" ]; then platform="${@:i+1:1}" @@ -44,9 +44,7 @@ done cd $(dirname "$0") # start something -if [ "${role}" == "relay" ]; then - node relay.js & -elif [ "${role}" == "listener" ]; then +if [ "${role}" == "listener" ]; then if [ "${platform}" == "chromium" ] || [ "${platform}" == "firefox" ] || [ "${platform}" == "webkit" ]; then if [ $RELAY_ADDRESS == "" ]; then echo ERROR: a relay address is required to run a browser listener 1>&2 diff --git a/perf/impl/js-libp2p/v1.0-webrtc-256kb/relay.js b/perf/impl/js-libp2p/v1.0-webrtc-256kb/relay.js deleted file mode 100644 index 7495c6aad..000000000 --- a/perf/impl/js-libp2p/v1.0-webrtc-256kb/relay.js +++ /dev/null @@ -1,39 +0,0 @@ -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { circuitRelayServer } from '@libp2p/circuit-relay-v2' -import { identify } from '@libp2p/identify' -import { webSockets } from '@libp2p/websockets' -import { createLibp2p } from 'libp2p' - -const node = await createLibp2p({ - addresses: { - listen: [ - `/ip4/0.0.0.0/tcp/${process.env.LISTEN_PORT}/ws` - ], - announce: [ - `/ip4/${process.env.EXTERNAL_IP}/tcp/${process.env.LISTEN_PORT}/ws` - ] - }, - transports: [ - webSockets() - ], - streamMuxers: [ - yamux() - ], - connectionEncryption: [ - noise() - ], - connectionManager: { - minConnections: 0 - }, - services: { - identify: identify(), - relay: circuitRelayServer({ - reservations: { - maxReservations: 1024 * 1024 - } - }) - } -}) - -console.info(node.getMultiaddrs()[0].toString()) diff --git a/perf/relay/Makefile b/perf/relay/Makefile new file mode 100644 index 000000000..3d78da383 --- /dev/null +++ b/perf/relay/Makefile @@ -0,0 +1,9 @@ +all: relay + +relay: + npm ci + +clean: + rm -rf node_modules + +.PHONY: all clean relay diff --git a/perf/impl/js-libp2p/v1.0-webrtc-16kb/relay.js b/perf/relay/index.js similarity index 83% rename from perf/impl/js-libp2p/v1.0-webrtc-16kb/relay.js rename to perf/relay/index.js index 7495c6aad..fcaca94c5 100644 --- a/perf/impl/js-libp2p/v1.0-webrtc-16kb/relay.js +++ b/perf/relay/index.js @@ -5,13 +5,18 @@ import { identify } from '@libp2p/identify' import { webSockets } from '@libp2p/websockets' import { createLibp2p } from 'libp2p' +const { + LISTEN_PORT, + EXTERNAL_IP +} = process.env + const node = await createLibp2p({ addresses: { listen: [ - `/ip4/0.0.0.0/tcp/${process.env.LISTEN_PORT}/ws` + `/ip4/0.0.0.0/tcp/${LISTEN_PORT}/ws` ], announce: [ - `/ip4/${process.env.EXTERNAL_IP}/tcp/${process.env.LISTEN_PORT}/ws` + `/ip4/${EXTERNAL_IP}/tcp/${LISTEN_PORT}/ws` ] }, transports: [ diff --git a/perf/relay/package-lock.json b/perf/relay/package-lock.json new file mode 100644 index 000000000..cf7cfe3cb --- /dev/null +++ b/perf/relay/package-lock.json @@ -0,0 +1,1083 @@ +{ + "name": "@libp2p/perf-js-libp2p-1-0-webrtc-256kb", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@libp2p/perf-js-libp2p-1-0-webrtc-256kb", + "dependencies": { + "@chainsafe/libp2p-noise": "^15.1.2", + "@chainsafe/libp2p-yamux": "^6.0.1", + "@libp2p/circuit-relay-v2": "^1.1.5", + "@libp2p/identify": "^2.1.5", + "@libp2p/websockets": "^8.2.0", + "libp2p": "^1.0.5" + } + }, + "node_modules/@chainsafe/as-chacha20poly1305": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@chainsafe/as-chacha20poly1305/-/as-chacha20poly1305-0.1.0.tgz", + "integrity": "sha512-BpNcL8/lji/GM3+vZ/bgRWqJ1q5kwvTFmGPk7pxm/QQZDbaMI98waOHjEymTjq2JmdD/INdNBFOVSyJofXg7ew==" + }, + "node_modules/@chainsafe/as-sha256": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.4.2.tgz", + "integrity": "sha512-HJ8GZBRjLeWtRsAXf3EbNsNzmTGpzTFjfpSf4yHkLYC+E52DhT6hwz+7qpj6I/EmFzSUm5tYYvT9K8GZokLQCQ==" + }, + "node_modules/@chainsafe/is-ip": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@chainsafe/is-ip/-/is-ip-2.0.2.tgz", + "integrity": "sha512-ndGqEMG1W5WkGagaqOZHpPU172AGdxr+LD15sv3WIUvT5oCFUrG1Y0CW/v2Egwj4JXEvSibaIIIqImsm98y1nA==" + }, + "node_modules/@chainsafe/libp2p-noise": { + "version": "15.1.2", + "resolved": "https://registry.npmjs.org/@chainsafe/libp2p-noise/-/libp2p-noise-15.1.2.tgz", + "integrity": "sha512-o6mqsAbaCBucgdLOOHtkwtGVL1c8RLKhlTnHQY+leazY+thiE1Sm6qPCwsTHKQnWii1q5hDVI2Q0l9QgYi5v4Q==", + "dependencies": { + "@chainsafe/as-chacha20poly1305": "^0.1.0", + "@chainsafe/as-sha256": "^0.4.1", + "@libp2p/crypto": "^4.0.0", + "@libp2p/interface": "^1.5.0", + "@libp2p/peer-id": "^4.0.0", + "@noble/ciphers": "^0.6.0", + "@noble/curves": "^1.1.0", + "@noble/hashes": "^1.3.1", + "it-length-prefixed": "^9.0.1", + "it-length-prefixed-stream": "^1.0.0", + "it-pair": "^2.0.6", + "it-pipe": "^3.0.1", + "it-stream-types": "^2.0.1", + "protons-runtime": "^5.0.0", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^5.0.0", + "wherearewe": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0", + "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", + "integrity": "sha512-I3Z+6SWUoaljh3TBzCnCxjlUyN8tA+NAk5L6m9IxvCf1BENQTePzPMis97CoN/iMW1St3WN+AWCCRp+TTBRiDg==", + "dependencies": { + "@chainsafe/is-ip": "^2.0.1" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==" + }, + "node_modules/@libp2p/circuit-relay-v2": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@libp2p/circuit-relay-v2/-/circuit-relay-v2-1.1.5.tgz", + "integrity": "sha512-WVIHaj61LJd2JB6vvPikd049NhC2R3vrkuu4T00WJSMNWobmhrKPvFyQMN+1miL6KmdL8Yt1AjK0gog2oT4vDw==", + "dependencies": { + "@libp2p/interface": "^1.7.0", + "@libp2p/interface-internal": "^1.3.4", + "@libp2p/peer-collections": "^5.2.9", + "@libp2p/peer-id": "^4.2.4", + "@libp2p/peer-record": "^7.0.25", + "@libp2p/utils": "^5.4.9", + "@multiformats/mafmt": "^12.1.6", + "@multiformats/multiaddr": "^12.2.3", + "any-signal": "^4.1.1", + "it-protobuf-stream": "^1.1.3", + "it-stream-types": "^2.0.1", + "multiformats": "^13.1.0", + "p-defer": "^4.0.1", + "progress-events": "^1.0.0", + "protons-runtime": "^5.4.0", + "race-signal": "^1.0.2", + "uint8arraylist": "^2.4.8", + "uint8arrays": "^5.1.0" + } + }, + "node_modules/@libp2p/crypto": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@libp2p/crypto/-/crypto-4.1.9.tgz", + "integrity": "sha512-8Cf2VKh0uC/rQLvTLSloIOMqUvf4jsSTHXgjWQRf47lDNJlNNI0wSv2S6gakT72GZsRV/jCjYwKPqRlsa5S0iA==", + "dependencies": { + "@libp2p/interface": "^1.7.0", + "@noble/curves": "^1.4.0", + "@noble/hashes": "^1.4.0", + "asn1js": "^3.0.5", + "multiformats": "^13.1.0", + "protons-runtime": "^5.4.0", + "uint8arraylist": "^2.4.8", + "uint8arrays": "^5.1.0" + } + }, + "node_modules/@libp2p/identify": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@libp2p/identify/-/identify-2.1.5.tgz", + "integrity": "sha512-uVghY2KfZ3ffDkPmcivfiRDlq1h5rCcoHAW+Kb7JF2qrDfg6BgHAn6IRN4pe/DnYXOuJXIIm6+jjcReTPGBKBQ==", + "dependencies": { + "@libp2p/interface": "^1.7.0", + "@libp2p/interface-internal": "^1.3.4", + "@libp2p/peer-id": "^4.2.4", + "@libp2p/peer-record": "^7.0.25", + "@multiformats/multiaddr": "^12.2.3", + "@multiformats/multiaddr-matcher": "^1.2.1", + "it-drain": "^3.0.7", + "it-parallel": "^3.0.7", + "it-protobuf-stream": "^1.1.3", + "protons-runtime": "^5.4.0", + "uint8arraylist": "^2.4.8", + "uint8arrays": "^5.1.0", + "wherearewe": "^2.0.1" + } + }, + "node_modules/@libp2p/interface": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-1.7.0.tgz", + "integrity": "sha512-/zFyaIaIGW0aihhsH7/93vQdpWInUzFocxF11RO/029Y6h0SVjs24HHbils+DqaFDTqN+L7oNlBx2rM2MnmTjA==", + "dependencies": { + "@multiformats/multiaddr": "^12.2.3", + "it-pushable": "^3.2.3", + "it-stream-types": "^2.0.1", + "multiformats": "^13.1.0", + "progress-events": "^1.0.0", + "uint8arraylist": "^2.4.8" + } + }, + "node_modules/@libp2p/interface-internal": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@libp2p/interface-internal/-/interface-internal-1.3.4.tgz", + "integrity": "sha512-8x/0sdeH8T16yZ9t/Cfja0ms6Ho9fF3riX56WhQrNxMU6C1sIgAFmzUNzHLxxOR+rkKyL9cyXIyB+RcBf4gzjA==", + "dependencies": { + "@libp2p/interface": "^1.7.0", + "@libp2p/peer-collections": "^5.2.9", + "@multiformats/multiaddr": "^12.2.3", + "progress-events": "^1.0.0", + "uint8arraylist": "^2.4.8" + } + }, + "node_modules/@libp2p/logger": { + "version": "4.0.20", + "resolved": "https://registry.npmjs.org/@libp2p/logger/-/logger-4.0.20.tgz", + "integrity": "sha512-TTh2dhHsOTAlMPxSa9ncFPHa/0jTt+0AQxwHdlxg/OGLAgc9VRhnrhHUbJZp07Crcw4T/MOfS4KhjlxgqYgJRw==", + "dependencies": { + "@libp2p/interface": "^1.7.0", + "@multiformats/multiaddr": "^12.2.3", + "interface-datastore": "^8.2.11", + "multiformats": "^13.1.0", + "weald": "^1.0.2" + } + }, + "node_modules/@libp2p/multistream-select": { + "version": "5.1.17", + "resolved": "https://registry.npmjs.org/@libp2p/multistream-select/-/multistream-select-5.1.17.tgz", + "integrity": "sha512-QOMGjCzKGf/W+qzWw5OxaqLEYhK45XjMCxGJYQ7L5eUkcwAv6rlPZAYw6YslaMLpJTa61/yfh8D4u7EuoMFsUw==", + "dependencies": { + "@libp2p/interface": "^1.7.0", + "it-length-prefixed": "^9.0.4", + "it-length-prefixed-stream": "^1.1.7", + "it-stream-types": "^2.0.1", + "p-defer": "^4.0.1", + "race-signal": "^1.0.2", + "uint8-varint": "^2.0.4", + "uint8arraylist": "^2.4.8", + "uint8arrays": "^5.1.0" + } + }, + "node_modules/@libp2p/peer-collections": { + "version": "5.2.9", + "resolved": "https://registry.npmjs.org/@libp2p/peer-collections/-/peer-collections-5.2.9.tgz", + "integrity": "sha512-8gBmzQlCWjjb+FSQBKK33T25Y5Df/8FWCXFtJDsprVxVUzDOQoibQJ5Tb4Y+mb96HUhNzoaRWVEamB78MMB3DA==", + "dependencies": { + "@libp2p/interface": "^1.7.0", + "@libp2p/peer-id": "^4.2.4", + "@libp2p/utils": "^5.4.9" + } + }, + "node_modules/@libp2p/peer-id": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@libp2p/peer-id/-/peer-id-4.2.4.tgz", + "integrity": "sha512-mvvsVxt4HkF14BrTNKbqr14VObW+KBJBWu1Oe6BFCoDttGMQLaI+PdduE1r6Tquntv5IONBqoITgD7ow5dQ+vQ==", + "dependencies": { + "@libp2p/interface": "^1.7.0", + "multiformats": "^13.1.0", + "uint8arrays": "^5.1.0" + } + }, + "node_modules/@libp2p/peer-id-factory": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@libp2p/peer-id-factory/-/peer-id-factory-4.2.4.tgz", + "integrity": "sha512-NDQ/qIWpcAG/6xQjyut6xCkrYYAoCaI/33Z+7yzo5qFODwLfNonLzSTasnA6jhuvHn33aHnD1qhdpFkmstxtNQ==", + "dependencies": { + "@libp2p/crypto": "^4.1.9", + "@libp2p/interface": "^1.7.0", + "@libp2p/peer-id": "^4.2.4", + "protons-runtime": "^5.4.0", + "uint8arraylist": "^2.4.8", + "uint8arrays": "^5.1.0" + } + }, + "node_modules/@libp2p/peer-record": { + "version": "7.0.25", + "resolved": "https://registry.npmjs.org/@libp2p/peer-record/-/peer-record-7.0.25.tgz", + "integrity": "sha512-b54P3cSeQniW/HPJjBVbeF3KaVUQkWa431gotuIFUS1PYgtz69uzkRrVY6Qt+RBb4R4fcmH4K4jWyZi3xyLGfQ==", + "dependencies": { + "@libp2p/crypto": "^4.1.9", + "@libp2p/interface": "^1.7.0", + "@libp2p/peer-id": "^4.2.4", + "@libp2p/utils": "^5.4.9", + "@multiformats/multiaddr": "^12.2.3", + "protons-runtime": "^5.4.0", + "uint8-varint": "^2.0.4", + "uint8arraylist": "^2.4.8", + "uint8arrays": "^5.1.0" + } + }, + "node_modules/@libp2p/peer-store": { + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/@libp2p/peer-store/-/peer-store-10.1.5.tgz", + "integrity": "sha512-JqQcIcxZS7kicCPabGRyrKD+qZlOdaooL00hdHogVb4MIMqfjiQMmOEpzIvTQLCKHKM2mmfnV3P7kc6hYzPq8g==", + "dependencies": { + "@libp2p/interface": "^1.7.0", + "@libp2p/peer-collections": "^5.2.9", + "@libp2p/peer-id": "^4.2.4", + "@libp2p/peer-record": "^7.0.25", + "@multiformats/multiaddr": "^12.2.3", + "interface-datastore": "^8.2.11", + "it-all": "^3.0.6", + "mortice": "^3.0.4", + "multiformats": "^13.1.0", + "protons-runtime": "^5.4.0", + "uint8arraylist": "^2.4.8", + "uint8arrays": "^5.1.0" + } + }, + "node_modules/@libp2p/utils": { + "version": "5.4.9", + "resolved": "https://registry.npmjs.org/@libp2p/utils/-/utils-5.4.9.tgz", + "integrity": "sha512-0fRdX98WqhTmXU2WEVLegLFxs/kKTtUHanHk5Lzs4oGsIzlPHR7zE6lj/U1WfsFA+Xo1eYQpNLiXEL29hG+Nyw==", + "dependencies": { + "@chainsafe/is-ip": "^2.0.2", + "@libp2p/crypto": "^4.1.9", + "@libp2p/interface": "^1.7.0", + "@libp2p/logger": "^4.0.20", + "@multiformats/multiaddr": "^12.2.3", + "@multiformats/multiaddr-matcher": "^1.2.1", + "@sindresorhus/fnv1a": "^3.1.0", + "@types/murmurhash3js-revisited": "^3.0.3", + "any-signal": "^4.1.1", + "delay": "^6.0.0", + "get-iterator": "^2.0.1", + "is-loopback-addr": "^2.0.2", + "it-pushable": "^3.2.3", + "it-stream-types": "^2.0.1", + "murmurhash3js-revisited": "^3.0.0", + "netmask": "^2.0.2", + "p-defer": "^4.0.1", + "race-event": "^1.3.0", + "race-signal": "^1.0.2", + "uint8arraylist": "^2.4.8", + "uint8arrays": "^5.1.0" + } + }, + "node_modules/@libp2p/websockets": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@libp2p/websockets/-/websockets-8.2.0.tgz", + "integrity": "sha512-UNjqkQ8/emnYswp1ohIIuZCnhI5DlvWF9IaIND2MoTCDavi7yubWfMp8jSWBsAqPnMeLMO8MQ6YlOo4FFC104Q==", + "dependencies": { + "@libp2p/interface": "^1.7.0", + "@libp2p/utils": "^5.4.9", + "@multiformats/mafmt": "^12.1.6", + "@multiformats/multiaddr": "^12.2.3", + "@multiformats/multiaddr-to-uri": "^10.0.1", + "@types/ws": "^8.5.10", + "it-ws": "^6.1.1", + "p-defer": "^4.0.1", + "progress-events": "^1.0.0", + "race-signal": "^1.0.2", + "wherearewe": "^2.0.1", + "ws": "^8.17.0" + } + }, + "node_modules/@multiformats/dns": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@multiformats/dns/-/dns-1.0.6.tgz", + "integrity": "sha512-nt/5UqjMPtyvkG9BQYdJ4GfLK3nMqGpFZOzf4hAmIa0sJh2LlS9YKXZ4FgwBDsaHvzZqR/rUFIywIc7pkHNNuw==", + "dependencies": { + "@types/dns-packet": "^5.6.5", + "buffer": "^6.0.3", + "dns-packet": "^5.6.1", + "hashlru": "^2.3.0", + "p-queue": "^8.0.1", + "progress-events": "^1.0.0", + "uint8arrays": "^5.0.2" + } + }, + "node_modules/@multiformats/mafmt": { + "version": "12.1.6", + "resolved": "https://registry.npmjs.org/@multiformats/mafmt/-/mafmt-12.1.6.tgz", + "integrity": "sha512-tlJRfL21X+AKn9b5i5VnaTD6bNttpSpcqwKVmDmSHLwxoz97fAHaepqFOk/l1fIu94nImIXneNbhsJx/RQNIww==", + "dependencies": { + "@multiformats/multiaddr": "^12.0.0" + } + }, + "node_modules/@multiformats/multiaddr": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/@multiformats/multiaddr/-/multiaddr-12.3.0.tgz", + "integrity": "sha512-JQ8Gc/jgucqqvEaDTFN/AvxlYDHEE7lgEWLMYW7hKZkWggER+GvG/tVxUgUxIP8M0vFpvEHKKHE0lKzyMsgi8Q==", + "dependencies": { + "@chainsafe/is-ip": "^2.0.1", + "@chainsafe/netmask": "^2.0.0", + "@libp2p/interface": "^1.0.0", + "@multiformats/dns": "^1.0.3", + "multiformats": "^13.0.0", + "uint8-varint": "^2.0.1", + "uint8arrays": "^5.0.0" + } + }, + "node_modules/@multiformats/multiaddr-matcher": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@multiformats/multiaddr-matcher/-/multiaddr-matcher-1.2.4.tgz", + "integrity": "sha512-GgpqzQFL4Mj8t7cLNHC5nuYUuSm0kTtSUyYswiyWwTSUY3XwRAMx0UiFWQg+ETk0u+/IvFaHxfnyEoH3tasvwg==", + "dependencies": { + "@chainsafe/is-ip": "^2.0.1", + "@multiformats/multiaddr": "^12.0.0", + "multiformats": "^13.0.0" + } + }, + "node_modules/@multiformats/multiaddr-to-uri": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@multiformats/multiaddr-to-uri/-/multiaddr-to-uri-10.1.0.tgz", + "integrity": "sha512-ZNwSAx3ssBWwd4y0LKrOsq9xG7LBHboQxnUdSduNc2fTh/NS1UjA2slgUy6KHxH5k9S2DSus0iU2CoyJyN0/pg==", + "dependencies": { + "@multiformats/multiaddr": "^12.3.0" + } + }, + "node_modules/@noble/ciphers": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.6.0.tgz", + "integrity": "sha512-mIbq/R9QXk5/cTfESb1OKtyFnk7oc1Om/8onA1158K9/OZUQFDEVy55jVTato+xmp3XX6F6Qh0zz0Nc1AxAlRQ==", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.6.0.tgz", + "integrity": "sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==", + "dependencies": { + "@noble/hashes": "1.5.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", + "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@sindresorhus/fnv1a": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/fnv1a/-/fnv1a-3.1.0.tgz", + "integrity": "sha512-KV321z5m/0nuAg83W1dPLy85HpHDk7Sdi4fJbwvacWsEhAh+rZUW4ZfGcXmUIvjZg4ss2bcwNlRhJ7GBEUG08w==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@types/dns-packet": { + "version": "5.6.5", + "resolved": "https://registry.npmjs.org/@types/dns-packet/-/dns-packet-5.6.5.tgz", + "integrity": "sha512-qXOC7XLOEe43ehtWJCMnQXvgcIpv6rPmQ1jXT98Ad8A3TB1Ue50jsCbSSSyuazScEuZ/Q026vHbrOTVkmwA+7Q==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/murmurhash3js-revisited": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.3.tgz", + "integrity": "sha512-QvlqvYtGBYIDeO8dFdY4djkRubcrc+yTJtBc7n8VZPlJDUS/00A+PssbvERM8f9bYRmcaSEHPZgZojeQj7kzAA==" + }, + "node_modules/@types/node": { + "version": "22.5.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/ws": { + "version": "8.5.12", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", + "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/any-signal": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/any-signal/-/any-signal-4.1.1.tgz", + "integrity": "sha512-iADenERppdC+A2YKbOXXB2WUeABLaM6qnpZ70kZbPZ1cZMMJ7eF+3CaYm+/PhBizgkzlvssC7QuHS30oOiQYWA==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "dependencies": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/datastore-core": { + "version": "9.2.9", + "resolved": "https://registry.npmjs.org/datastore-core/-/datastore-core-9.2.9.tgz", + "integrity": "sha512-wraWTPsbtdE7FFaVo3pwPuTB/zXsgwGGAm8BgBYwYAuzZCTS0MfXmd/HH1vR9s0/NFFjOVmBkGiWCvKxZ+QjVw==", + "dependencies": { + "@libp2p/logger": "^4.0.6", + "err-code": "^3.0.1", + "interface-datastore": "^8.0.0", + "interface-store": "^5.0.0", + "it-drain": "^3.0.5", + "it-filter": "^3.0.4", + "it-map": "^3.0.5", + "it-merge": "^3.0.3", + "it-pipe": "^3.0.1", + "it-pushable": "^3.2.3", + "it-sort": "^3.0.4", + "it-take": "^3.0.4" + } + }, + "node_modules/datastore-core/node_modules/interface-store": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/interface-store/-/interface-store-5.1.8.tgz", + "integrity": "sha512-7na81Uxkl0vqk0CBPO5PvyTkdaJBaezwUJGsMOz7riPOq0rJt+7W31iaopaMICWea/iykUsvNlPx/Tc+MxC3/w==" + }, + "node_modules/delay": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-6.0.0.tgz", + "integrity": "sha512-2NJozoOHQ4NuZuVIr5CWd0iiLVIRSDepakaovIN+9eIDHEhdCAEvSy2cuf1DCrPPQLvHmbqTHODlhHg8UCy4zw==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", + "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==" + }, + "node_modules/event-iterator": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/event-iterator/-/event-iterator-2.0.0.tgz", + "integrity": "sha512-KGft0ldl31BZVV//jj+IAIGCxkvvUkkON+ScH6zfoX+l+omX6001ggyRSpI0Io2Hlro0ThXotswCtfzS8UkIiQ==" + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, + "node_modules/get-iterator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/get-iterator/-/get-iterator-2.0.1.tgz", + "integrity": "sha512-7HuY/hebu4gryTDT7O/XY/fvY9wRByEGdK6QOa4of8npTcv0+NS6frFKABcf6S9EBAsveTuKTsZQQBFMMNILIg==" + }, + "node_modules/hashlru": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/hashlru/-/hashlru-2.3.0.tgz", + "integrity": "sha512-0cMsjjIC8I+D3M44pOQdsy0OHXGLVz6Z0beRuufhKa0KfaD2wGwAev6jILzXsd3/vpnNQJmWyZtIILqM1N+n5A==" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/interface-datastore": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/interface-datastore/-/interface-datastore-8.3.0.tgz", + "integrity": "sha512-RM/rTSmRcnoCwGZIHrPm+nlGYVoT4R0lcFvNnDyhdFT4R6BuHHhfFP47UldVEjs98SfxLuMhaNMsyjI918saHw==", + "dependencies": { + "interface-store": "6.0.0", + "uint8arrays": "^5.0.2" + } + }, + "node_modules/interface-store": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/interface-store/-/interface-store-6.0.0.tgz", + "integrity": "sha512-HkjsDPsjA7SKkCr+TH1elUQApAAM3X3JPwrz3vFzaf614wI+ZD6GVvwKGZCHYcbSRqeZP/uzVPqezzeISeo5kA==" + }, + "node_modules/is-electron": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.2.tgz", + "integrity": "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==" + }, + "node_modules/is-loopback-addr": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-loopback-addr/-/is-loopback-addr-2.0.2.tgz", + "integrity": "sha512-26POf2KRCno/KTNL5Q0b/9TYnL00xEsSaLfiFRmjM7m7Lw7ZMmFybzzuX4CcsLAluZGd+niLUiMRxEooVE3aqg==" + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/it-all": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/it-all/-/it-all-3.0.6.tgz", + "integrity": "sha512-HXZWbxCgQZJfrv5rXvaVeaayXED8nTKx9tj9fpBhmcUJcedVZshMMMqTj0RG2+scGypb9Ut1zd1ifbf3lA8L+Q==" + }, + "node_modules/it-byte-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/it-byte-stream/-/it-byte-stream-1.1.0.tgz", + "integrity": "sha512-WWponBWdKEa6o2U3NX+wGMY8X1EkWXcQvpC+3CUqKb4ZzK30q3EPqiTjFxLf9tNVgdF/MNAtx/XclpVfgaz9KQ==", + "dependencies": { + "it-queueless-pushable": "^1.0.0", + "it-stream-types": "^2.0.1", + "uint8arraylist": "^2.4.8" + } + }, + "node_modules/it-drain": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/it-drain/-/it-drain-3.0.7.tgz", + "integrity": "sha512-vy6S1JKjjHSIFHgBpLpD1zhkCRl3z1zYWUxE14+kAYf+BL9ssWSFImJfhl361IIcwr0ofw8etzg11VqqB+ntUA==" + }, + "node_modules/it-filter": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/it-filter/-/it-filter-3.1.1.tgz", + "integrity": "sha512-TOXmVuaSkxlLp2hXKoMTra0WMZMKVFxE3vSsbIA+PbADNCBAHhjJ/lM31vBOUTddHMO34Ku++vU8T9PLlBxQtg==", + "dependencies": { + "it-peekable": "^3.0.0" + } + }, + "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.1.0", + "resolved": "https://registry.npmjs.org/it-length-prefixed/-/it-length-prefixed-9.1.0.tgz", + "integrity": "sha512-kx2UTJuy7/lsT3QUzf50NjfxU1Z4P4wlvYp6YnR5Nc61P8XKfy+QtiJi1VLojA+Kea7vMbB4002rIij1Ol9hcw==", + "dependencies": { + "it-reader": "^6.0.1", + "it-stream-types": "^2.0.1", + "uint8-varint": "^2.0.1", + "uint8arraylist": "^2.0.0", + "uint8arrays": "^5.0.1" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/it-length-prefixed-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/it-length-prefixed-stream/-/it-length-prefixed-stream-1.2.0.tgz", + "integrity": "sha512-vX7dzSl/2UMYYsAr0FQdPNVR5xYEETaeboZ+eXxNBjgARuvxnWA6OedW8lC5/J3ebMTC98JhA3eH76eTijUOsA==", + "dependencies": { + "it-byte-stream": "^1.0.0", + "it-stream-types": "^2.0.1", + "uint8-varint": "^2.0.4", + "uint8arraylist": "^2.4.8" + } + }, + "node_modules/it-map": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/it-map/-/it-map-3.1.1.tgz", + "integrity": "sha512-9bCSwKD1yN1wCOgJ9UOl+46NQtdatosPWzxxUk2NdTLwRPXLh+L7iwCC9QKsbgM60RQxT/nH8bKMqm3H/o8IHQ==", + "dependencies": { + "it-peekable": "^3.0.0" + } + }, + "node_modules/it-merge": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/it-merge/-/it-merge-3.0.5.tgz", + "integrity": "sha512-2l7+mPf85pyRF5pqi0dKcA54E5Jm/2FyY5GsOaN51Ta0ipC7YZ3szuAsH8wOoB6eKY4XsU4k2X+mzPmFBMayEA==", + "dependencies": { + "it-pushable": "^3.2.3" + } + }, + "node_modules/it-pair": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/it-pair/-/it-pair-2.0.6.tgz", + "integrity": "sha512-5M0t5RAcYEQYNG5BV7d7cqbdwbCAp5yLdzvkxsZmkuZsLbTdZzah6MQySYfaAQjNDCq6PUnDt0hqBZ4NwMfW6g==", + "dependencies": { + "it-stream-types": "^2.0.1", + "p-defer": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/it-parallel": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/it-parallel/-/it-parallel-3.0.8.tgz", + "integrity": "sha512-URLhs6eG4Hdr4OdvgBBPDzOjBeSSmI+Kqex2rv/aAyYClME26RYHirLVhZsZP5M+ZP6M34iRlXk8Wlqtezuqpg==", + "dependencies": { + "p-defer": "^4.0.1" + } + }, + "node_modules/it-peekable": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/it-peekable/-/it-peekable-3.0.5.tgz", + "integrity": "sha512-JWQOGMt6rKiPcY30zUVMR4g6YxkpueTwHVE7CMs/aGqCf4OydM6w+7ZM3PvmO1e0TocjuR4aL8xyZWR46cTqCQ==" + }, + "node_modules/it-pipe": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/it-pipe/-/it-pipe-3.0.1.tgz", + "integrity": "sha512-sIoNrQl1qSRg2seYSBH/3QxWhJFn9PKYvOf/bHdtCBF0bnghey44VyASsWzn5dAx0DCDDABq1hZIuzKmtBZmKA==", + "dependencies": { + "it-merge": "^3.0.0", + "it-pushable": "^3.1.2", + "it-stream-types": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/it-protobuf-stream": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/it-protobuf-stream/-/it-protobuf-stream-1.1.5.tgz", + "integrity": "sha512-H70idW45As3cEbU4uSoZ9IYHUIV3YM69/2mmXYR7gOlPabWjuyNi3/abK11geiiq3la27Sos/mXr68JljjKtEQ==", + "dependencies": { + "it-length-prefixed-stream": "^1.0.0", + "it-stream-types": "^2.0.1", + "uint8arraylist": "^2.4.8" + } + }, + "node_modules/it-pushable": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/it-pushable/-/it-pushable-3.2.3.tgz", + "integrity": "sha512-gzYnXYK8Y5t5b/BnJUr7glfQLO4U5vyb05gPx/TyTw+4Bv1zM9gFk4YsOrnulWefMewlphCjKkakFvj1y99Tcg==", + "dependencies": { + "p-defer": "^4.0.0" + } + }, + "node_modules/it-queueless-pushable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/it-queueless-pushable/-/it-queueless-pushable-1.0.0.tgz", + "integrity": "sha512-HbcAbcuQj7a9EBxiRCZ+77FxWutgs/pY5ZvEyQnylWPGNFojCLAUwhcZjf5OuEQ9+y+vSa7w1GQBe8xJdmIn5A==", + "dependencies": { + "p-defer": "^4.0.1", + "race-signal": "^1.0.2" + } + }, + "node_modules/it-reader": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/it-reader/-/it-reader-6.0.4.tgz", + "integrity": "sha512-XCWifEcNFFjjBHtor4Sfaj8rcpt+FkY0L6WdhD578SCDhV4VUm7fCkF3dv5a+fTcfQqvN9BsxBTvWbYO6iCjTg==", + "dependencies": { + "it-stream-types": "^2.0.1", + "uint8arraylist": "^2.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/it-sort": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/it-sort/-/it-sort-3.0.6.tgz", + "integrity": "sha512-aNrlZAXB8vWBd42tCpaXGL6CJVJNDW3OLczmdt6g0k/s9Z6evkTdgU2LjwW5SNNeX41sF+C8MjV+OcVf93PsPw==", + "dependencies": { + "it-all": "^3.0.0" + } + }, + "node_modules/it-stream-types": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/it-stream-types/-/it-stream-types-2.0.1.tgz", + "integrity": "sha512-6DmOs5r7ERDbvS4q8yLKENcj6Yecr7QQTqWApbZdfAUTEC947d+PEha7PCqhm//9oxaLYL7TWRekwhoXl2s6fg==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/it-take": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/it-take/-/it-take-3.0.6.tgz", + "integrity": "sha512-uqw3MRzf9to1SOLxaureGa73lK8k8ZB/asOApTAkvrzUqCznGtKNgPFH7uYIWlt4UuWq/hU6I+U4Fm5xpjN8Vg==" + }, + "node_modules/it-ws": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/it-ws/-/it-ws-6.1.5.tgz", + "integrity": "sha512-uWjMtpy5HqhSd/LlrlP3fhYrr7rUfJFFMABv0F5d6n13Q+0glhZthwUKpEAVhDrXY95Tb1RB5lLqqef+QbVNaw==", + "dependencies": { + "@types/ws": "^8.2.2", + "event-iterator": "^2.0.0", + "it-stream-types": "^2.0.1", + "uint8arrays": "^5.0.0", + "ws": "^8.4.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/libp2p": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/libp2p/-/libp2p-1.9.4.tgz", + "integrity": "sha512-OCMQqJ0Po8jhgb4CilWhI5EWhppn9ENdhg63PQL8Yi1tk2rOwJJt+NBec85AU18zBc0jv7Q6SgQRkzCefAuyIQ==", + "dependencies": { + "@libp2p/crypto": "^4.1.9", + "@libp2p/interface": "^1.7.0", + "@libp2p/interface-internal": "^1.3.4", + "@libp2p/logger": "^4.0.20", + "@libp2p/multistream-select": "^5.1.17", + "@libp2p/peer-collections": "^5.2.9", + "@libp2p/peer-id": "^4.2.4", + "@libp2p/peer-id-factory": "^4.2.4", + "@libp2p/peer-store": "^10.1.5", + "@libp2p/utils": "^5.4.9", + "@multiformats/dns": "^1.0.6", + "@multiformats/multiaddr": "^12.2.3", + "@multiformats/multiaddr-matcher": "^1.2.1", + "any-signal": "^4.1.1", + "datastore-core": "^9.2.9", + "interface-datastore": "^8.2.11", + "it-byte-stream": "^1.0.12", + "it-merge": "^3.0.5", + "it-parallel": "^3.0.7", + "merge-options": "^3.0.4", + "multiformats": "^13.1.0", + "p-defer": "^4.0.1", + "progress-events": "^1.0.0", + "race-event": "^1.3.0", + "race-signal": "^1.0.2", + "uint8arrays": "^5.1.0" + } + }, + "node_modules/merge-options": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", + "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", + "dependencies": { + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mortice": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/mortice/-/mortice-3.0.4.tgz", + "integrity": "sha512-MUHRCAztSl4v/dAmK8vbYi5u1n9NZtQu4H3FsqS7qgMFQIAFw9lTpHiErd9kJpapqmvEdD1L3dUmiikifAvLsQ==", + "dependencies": { + "observable-webworkers": "^2.0.1", + "p-queue": "^8.0.1", + "p-timeout": "^6.0.0" + } + }, + "node_modules/ms": { + "version": "3.0.0-canary.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-3.0.0-canary.1.tgz", + "integrity": "sha512-kh8ARjh8rMN7Du2igDRO9QJnqCb2xYTJxyQYK7vJJS4TvLLmsbyhiKpSW+t+y26gyOyMd0riphX0GeWKU3ky5g==", + "engines": { + "node": ">=12.13" + } + }, + "node_modules/multiformats": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-13.2.2.tgz", + "integrity": "sha512-RWI+nyf0q64vyOxL8LbKtjJMki0sogRL/8axvklNtiTM0iFCVtHwME9w6+0P1/v4dQvsIg8A45oT3ka1t/M/+A==" + }, + "node_modules/murmurhash3js-revisited": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.0.tgz", + "integrity": "sha512-/sF3ee6zvScXMb1XFJ8gDsSnY+X8PbOyjIuBhtgis10W2Jx4ZjIhikUCIF9c4gpJxVnQIsPAFrSwTCuAjicP6g==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/observable-webworkers": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/observable-webworkers/-/observable-webworkers-2.0.1.tgz", + "integrity": "sha512-JI1vB0u3pZjoQKOK1ROWzp0ygxSi7Yb0iR+7UNsw4/Zn4cQ0P3R7XL38zac/Dy2tEA7Lg88/wIJTjF8vYXZ0uw==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/p-defer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-4.0.1.tgz", + "integrity": "sha512-Mr5KC5efvAK5VUptYEIopP1bakB85k2IWXaRC0rsh1uwn1L6M0LVml8OIQ4Gudg4oyZakf7FmeRLkMMtZW1i5A==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.0.1.tgz", + "integrity": "sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==", + "dependencies": { + "eventemitter3": "^5.0.1", + "p-timeout": "^6.1.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.2.tgz", + "integrity": "sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/progress-events": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/progress-events/-/progress-events-1.0.1.tgz", + "integrity": "sha512-MOzLIwhpt64KIVN64h1MwdKWiyKFNc/S6BoYKPIVUHFg0/eIEyBulhWCgn678v/4c0ri3FdGuzXymNCv02MUIw==" + }, + "node_modules/protons-runtime": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/protons-runtime/-/protons-runtime-5.5.0.tgz", + "integrity": "sha512-EsALjF9QsrEk6gbCx3lmfHxVN0ah7nG3cY7GySD4xf4g8cr7g543zB88Foh897Sr1RQJ9yDCUsoT1i1H/cVUFA==", + "dependencies": { + "uint8-varint": "^2.0.2", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^5.0.1" + } + }, + "node_modules/pvtsutils": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.5.tgz", + "integrity": "sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==", + "dependencies": { + "tslib": "^2.6.1" + } + }, + "node_modules/pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/race-event": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/race-event/-/race-event-1.3.0.tgz", + "integrity": "sha512-kaLm7axfOnahIqD3jQ4l1e471FIFcEGebXEnhxyLscuUzV8C94xVHtWEqDDXxll7+yu/6lW0w1Ff4HbtvHvOHg==" + }, + "node_modules/race-signal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/race-signal/-/race-signal-1.1.0.tgz", + "integrity": "sha512-VqsW1uzCXfKBd2DhA3K3NhQlqQr04+5WQ7+kHpf1HzT01Q+ePSFWZdQHXKZPuLmm2eXTZM1XLO76cq15ZRAaEA==" + }, + "node_modules/supports-color": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/uint8-varint": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/uint8-varint/-/uint8-varint-2.0.4.tgz", + "integrity": "sha512-FwpTa7ZGA/f/EssWAb5/YV6pHgVF1fViKdW8cWaEarjB8t7NyofSWBdOTyFPaGuUG4gx3v1O3PQ8etsiOs3lcw==", + "dependencies": { + "uint8arraylist": "^2.0.0", + "uint8arrays": "^5.0.0" + } + }, + "node_modules/uint8arraylist": { + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/uint8arraylist/-/uint8arraylist-2.4.8.tgz", + "integrity": "sha512-vc1PlGOzglLF0eae1M8mLRTBivsvrGsdmJ5RbK3e+QRvRLOZfZhQROTwH/OfyF3+ZVUg9/8hE8bmKP2CvP9quQ==", + "dependencies": { + "uint8arrays": "^5.0.1" + } + }, + "node_modules/uint8arrays": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-5.1.0.tgz", + "integrity": "sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww==", + "dependencies": { + "multiformats": "^13.0.0" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + }, + "node_modules/weald": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/weald/-/weald-1.0.2.tgz", + "integrity": "sha512-iG5cIuBwsPe1ZcoGGd4X6QYlepU1vLr4l4oWpzQWqeJPSo9B8bxxyE6xlnj3TCmThtha7gyVL+uuZgUFkPyfDg==", + "dependencies": { + "ms": "^3.0.0-canary.1", + "supports-color": "^9.4.0" + } + }, + "node_modules/wherearewe": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wherearewe/-/wherearewe-2.0.1.tgz", + "integrity": "sha512-XUguZbDxCA2wBn2LoFtcEhXL6AXo+hVjGonwhSTTTU9SzbWG8Xu3onNIpzf9j/mYUcJQ0f+m37SzG77G851uFw==", + "dependencies": { + "is-electron": "^2.2.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/perf/relay/package.json b/perf/relay/package.json new file mode 100644 index 000000000..9987cf61d --- /dev/null +++ b/perf/relay/package.json @@ -0,0 +1,17 @@ +{ + "name": "@libp2p/perf-js-libp2p-1-0-webrtc-256kb", + "private": true, + "main": "index.js", + "type": "module", + "scripts": { + "start": "node index.js" + }, + "dependencies": { + "@chainsafe/libp2p-noise": "^15.1.2", + "@chainsafe/libp2p-yamux": "^6.0.1", + "@libp2p/circuit-relay-v2": "^1.1.5", + "@libp2p/identify": "^2.1.5", + "@libp2p/websockets": "^8.2.0", + "libp2p": "^1.0.5" + } +} diff --git a/perf/relay/relay b/perf/relay/relay new file mode 100755 index 000000000..a55d7550d --- /dev/null +++ b/perf/relay/relay @@ -0,0 +1,29 @@ +#!/bin/bash + +# In case this script is `kill`ed, `kill` its child process, namely the `node` +# process below. +cleanup() { + kill $node_pid +} +trap cleanup EXIT TERM + +# Parse named parameters manually +for ((i = 1; i <= $#; i++)); do + if [ "${!i}" == "--external-ip" ]; then + export EXTERNAL_IP="${@:i+1:1}" + fi + if [ "${!i}" == "--listen-port" ]; then + export LISTEN_PORT="${@:i+1:1}" + fi +done + +cd $(dirname "$0") + +# start the relay +node relay.js & + +node_pid=$! + +# Wait for `node_pid` to finish, or for it to be `kill`ed by the above +# `cleanup`. +wait $node_pid diff --git a/perf/runner/src/index.ts b/perf/runner/src/index.ts index f3b59804e..08b47f96b 100644 --- a/perf/runner/src/index.ts +++ b/perf/runner/src/index.ts @@ -9,55 +9,72 @@ async function main(clientPublicIP: string, serverPublicIP: string, relayPublicI const iperf = runIPerf(clientPublicIP, serverPublicIP, relayPublicIP, testing); await Promise.all([ - copyAndBuildPerfImplementations(relayPublicIP), - copyAndBuildPerfImplementations(serverPublicIP), - copyAndBuildPerfImplementations(clientPublicIP) + copyAndBuildDir('relay', relayPublicIP), + copyAndBuildDir('impl', serverPublicIP), + copyAndBuildDir('impl', clientPublicIP) ]) - const benchmarks = [ - await runBenchmarkAcrossVersions({ - name: "throughput/upload", - clientPublicIP, - serverPublicIP, - relayPublicIP, - uploadBytes: Number.MAX_SAFE_INTEGER, - downloadBytes: 0, - unit: "bit/s", - iterations: testing ? 1 : 10, - durationSecondsPerIteration: testing ? 5 : 20, - }), - await runBenchmarkAcrossVersions({ - name: "throughput/download", - clientPublicIP, - serverPublicIP, - relayPublicIP, - uploadBytes: 0, - downloadBytes: Number.MAX_SAFE_INTEGER, - unit: "bit/s", - iterations: testing ? 1 : 10, - durationSecondsPerIteration: testing ? 5 : 20, - }), - await runBenchmarkAcrossVersions({ - name: "Connection establishment + 1 byte round trip latencies", - clientPublicIP, - serverPublicIP, - relayPublicIP, - uploadBytes: 1, - downloadBytes: 1, - unit: "s", - iterations: testing ? 1 : 100, - durationSecondsPerIteration: Number.MAX_SAFE_INTEGER, - }), - ]; - - const benchmarkResults: BenchmarkResults = { - benchmarks, - pings, - iperf, - }; + console.error(`=== Starting relay`); + + const relayKillCMD = `ssh -o StrictHostKeyChecking=no ec2-user@${relayPublicIP} 'kill $(cat pidfile); rm pidfile || true'` + const relayKillSTDOUT = execCommand(relayKillCMD) + console.error(relayKillSTDOUT) - // Save results to benchmark-results.json - fs.writeFileSync('./benchmark-results.json', JSON.stringify(benchmarkResults, null, 2)); + const relayCMD = `ssh -o StrictHostKeyChecking=no ec2-user@${relayPublicIP} 'nohup ./relay/relay --external-ip ${relayPublicIP} --listen-port 8001 & echo \$! > pidfile '` + const { proc, promise } = await waitForMultiaddr('Relay', relayCMD) + const relayProc = proc + const relayAddress = await promise + console.error('Relay listening on', relayAddress) + + try { + const benchmarks = [ + await runBenchmarkAcrossVersions({ + name: "throughput/upload", + clientPublicIP, + serverPublicIP, + relayAddress, + uploadBytes: Number.MAX_SAFE_INTEGER, + downloadBytes: 0, + unit: "bit/s", + iterations: testing ? 1 : 10, + durationSecondsPerIteration: testing ? 5 : 20, + }), + await runBenchmarkAcrossVersions({ + name: "throughput/download", + clientPublicIP, + serverPublicIP, + relayAddress, + uploadBytes: 0, + downloadBytes: Number.MAX_SAFE_INTEGER, + unit: "bit/s", + iterations: testing ? 1 : 10, + durationSecondsPerIteration: testing ? 5 : 20, + }), + await runBenchmarkAcrossVersions({ + name: "Connection establishment + 1 byte round trip latencies", + clientPublicIP, + serverPublicIP, + relayAddress, + uploadBytes: 1, + downloadBytes: 1, + unit: "s", + iterations: testing ? 1 : 100, + durationSecondsPerIteration: Number.MAX_SAFE_INTEGER, + }), + ]; + + const benchmarkResults: BenchmarkResults = { + benchmarks, + pings, + iperf, + }; + + // Save results to benchmark-results.json + fs.writeFileSync('./benchmark-results.json', JSON.stringify(benchmarkResults, null, 2)); + } finally { + console.error('=== Stopping Relay') + relayProc?.kill('SIGKILL') + } console.error("== done"); } @@ -119,7 +136,7 @@ interface ArgsRunBenchmarkAcrossVersions { name: string, clientPublicIP: string; serverPublicIP: string; - relayPublicIP: string; + relayAddress: string; uploadBytes: number, downloadBytes: number, unit: "bit/s" | "s", @@ -131,28 +148,10 @@ async function runBenchmarkAcrossVersions(args: ArgsRunBenchmarkAcrossVersions): console.error(`= Benchmark ${args.name}`) const results: Result[] = []; - let relayAddress: string | undefined - let listenerAddress: string for (const version of versions) { console.error(`== Version ${version.implementation}/${version.id}`) - let relayProc: ChildProcess | undefined - - if (version.relay === true) { - console.error(`=== Starting relay ${version.implementation}/${version.id}`); - - const relayKillCMD = `ssh -o StrictHostKeyChecking=no ec2-user@${args.relayPublicIP} 'kill $(cat pidfile); rm pidfile || true'`; - const relayKillSTDOUT = execCommand(relayKillCMD); - console.error(relayKillSTDOUT); - - const relayCMD = `ssh -o StrictHostKeyChecking=no ec2-user@${args.relayPublicIP} 'nohup ./impl/${version.implementation}/${version.id}/perf --role relay --external-ip ${args.relayPublicIP} --listen-port 8001 & echo \$! > pidfile '`; - const { proc, promise } = await waitForMultiaddr('Relay', relayCMD) - relayProc = proc - relayAddress = await promise - console.error('Relay listening on', relayAddress); - } - for (const transportStack of version.transportStacks) { console.error(`=== Starting ${transportStack} listener ${version.implementation}/${version.id}`); @@ -160,18 +159,26 @@ async function runBenchmarkAcrossVersions(args: ArgsRunBenchmarkAcrossVersions): const killSTDOUT = execCommand(killCMD); console.error(killSTDOUT); - const listenerCMD = `ssh -o StrictHostKeyChecking=no ec2-user@${args.serverPublicIP} 'nohup ./impl/${version.implementation}/${version.id}/perf --role listener --external-ip ${args.serverPublicIP} --listen-port 4001 --transport ${transportStack}${version.server != null ? ` --platform ${version.server}` : ''}${relayAddress ? ` --relay-address ${relayAddress}` : ''} & echo \$! > pidfile '`; - const { proc, promise } = await waitForMultiaddr('Listener', listenerCMD) - const listenerProc = proc - listenerAddress = await promise - - console.error('Listener listening on', listenerAddress); + const serverArgs = [ + '--run-server true', + `--external-ip ${args.serverPublicIP}`, + '--listen-port 4001', + `--transport ${transportStack}`, + `--relay-address ${args.relayAddress}`, + version.server != null ? ` --platform ${version.server}` : '' + ] + const serverCMD = `ssh -o StrictHostKeyChecking=no ec2-user@${args.serverPublicIP} 'nohup ./impl/${version.implementation}/${version.id}/perf ${serverArgs.join(' ')} & echo \$! > pidfile '`; + const { proc, promise } = await waitForMultiaddr('Server', serverCMD, `${args.serverPublicIP}:4001`) + const serverProc = proc + const serverAddress = await promise + + console.error('=== Server listening on', serverAddress); const result = runClient({ ...args, ...version, transportStack, - listenerAddress + serverAddress }); results.push({ @@ -181,13 +188,8 @@ async function runBenchmarkAcrossVersions(args: ArgsRunBenchmarkAcrossVersions): transportStack: transportStack, }); - console.error('Stopping Listener') - listenerProc.kill('SIGKILL') - } - - if (relayProc != null) { - console.error('Stopping Relay') - relayProc?.kill('SIGKILL') + console.error('=== Stopping Server') + serverProc.kill('SIGKILL') } }; @@ -212,13 +214,20 @@ interface ArgsRunBenchmark { iterations: number durationSecondsPerIteration: number client?: PLATFORM - listenerAddress: string + serverAddress: string } function runClient(args: ArgsRunBenchmark): ResultValue[] { - console.error(`=== Starting client ${args.implementation}/${args.id}/${args.transportStack}`); - - const cmd = `./impl/${args.implementation}/${args.id}/perf --role dialer --listener-address ${args.listenerAddress} --transport ${args.transportStack} --upload-bytes ${args.uploadBytes} --download-bytes ${args.downloadBytes} ${args.client != null ? `--platform ${args.client}` : ''}` + console.error(`=== Starting client ${args.implementation}/${args.id}/${args.transportStack}`) + + const clientArgs = [ + `--server-address ${args.serverAddress}`, + `--transport ${args.transportStack}`, + `--upload-bytes ${args.uploadBytes}`, + `--download-bytes ${args.downloadBytes}`, + args.client != null ? ` --platform ${args.client}` : '' + ] + const cmd = `./impl/${args.implementation}/${args.id}/perf ${clientArgs.join(' ')}` // Note 124 is timeout's exit code when timeout is hit which is not a failure here. const withTimeout = `timeout ${args.durationSecondsPerIteration}s ${cmd} || [ $? -eq 124 ]` const withForLoop = `for i in {1..${args.iterations}}; do ${withTimeout}; done` @@ -256,8 +265,8 @@ function execCommand(cmd: string): string { } } -async function copyAndBuildPerfImplementations(ip: string): Promise { - console.error(`= Building implementations on ${ip}`); +async function copyAndBuildDir(dir: string, ip: string): Promise { + console.error(`= Building ${dir} on ${ip}`); const rsyncDeferred = defer() let rsyncStdout = '' @@ -276,7 +285,7 @@ async function copyAndBuildPerfImplementations(ip: string): Promise { const makeDeferred = defer() let makeStdout = '' - const makeProc = exec(`ssh -o StrictHostKeyChecking=no ec2-user@${ip} 'cd impl && make'`); + const makeProc = exec(`ssh -o StrictHostKeyChecking=no ec2-user@${ip} 'cd ${dir} && make'`); makeProc.stdout?.on('data', buf => { makeStdout += buf.toString() }) @@ -341,7 +350,11 @@ function defer (): DeferredPromise { } } -function waitForMultiaddr (name: string, cmd: string): { proc: ChildProcess, promise: Promise } { +/** + * Attempts to parse a multiaddr from the output, otherwise returns the passed + * host:port pair if passed. + */ +function waitForMultiaddr (name: string, cmd: string, defaultAddress?: string): { proc: ChildProcess, promise: Promise } { const deferred = defer() const proc = exec(cmd) proc.stdout?.on('data', (buf) => { @@ -351,6 +364,10 @@ function waitForMultiaddr (name: string, cmd: string): { proc: ChildProcess, pro if (str.includes('/p2p/')) { deferred.resolve(str) } + + if (defaultAddress != null) { + deferred.resolve(defaultAddress) + } }) proc.on('close', () => { deferred.reject(new Error(`${name} exited without listening on an address`)) diff --git a/perf/runner/src/versions.ts b/perf/runner/src/versions.ts index 929bb4aba..ebe53d484 100644 --- a/perf/runner/src/versions.ts +++ b/perf/runner/src/versions.ts @@ -9,12 +9,6 @@ export type Version = { implementation: "go-libp2p" | "js-libp2p" | "nim-libp2p" | "rust-libp2p" | "zig-libp2p" | "https" | "quic-go", transportStacks: TRANSPORT[], - /** - * If specified, an invocation of the perf script with `--role=relay` will - * occur - */ - relay?: boolean - /** * If specified this will be passed to the client as `--platform=$PLATFORM` */ @@ -27,4 +21,3 @@ export type Version = { } export const versions: Array = JSON.parse(fs.readFileSync(path.join(__dirname, '../versionsInput.json'), 'utf8')); -