From 8e5318dc4a79fbd5947429400eb8feeea9157267 Mon Sep 17 00:00:00 2001 From: Franck Royer Date: Tue, 21 Jun 2022 13:23:42 +1000 Subject: [PATCH] Upgrade libp2p-gossipsub --- package-lock.json | 1095 +++++++++++++++++++++---- package.json | 5 +- src/lib/discovery/random_subset.ts | 2 +- src/lib/waku.node.spec.ts | 5 +- src/lib/waku.ts | 23 +- src/lib/waku_relay/get_relay_peers.ts | 48 -- src/lib/waku_relay/index.ts | 431 ++-------- src/lib/waku_relay/relay_heartbeat.ts | 379 --------- 8 files changed, 1033 insertions(+), 955 deletions(-) delete mode 100644 src/lib/waku_relay/get_relay_peers.ts delete mode 100644 src/lib/waku_relay/relay_heartbeat.ts diff --git a/package-lock.json b/package-lock.json index fecb7301e0..d789cc754e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.24.0", "license": "MIT OR Apache-2.0", "dependencies": { + "@chainsafe/libp2p-gossipsub": "^2.0.0", "@chainsafe/libp2p-noise": "^5.0.0", "@ethersproject/rlp": "^5.5.0", "@libp2p/interface-peer-id": "^1.0.2", @@ -17,7 +18,7 @@ "@libp2p/peer-id": "^1.1.10", "@multiformats/multiaddr": "^10.2.0", "@noble/secp256k1": "^1.3.4", - "debug": "^4.3.1", + "debug": "^4.3.4", "dns-query": "^0.11.1", "hi-base32": "^0.5.1", "it-concat": "^2.0.0", @@ -27,7 +28,6 @@ "libp2p": "^0.37.3", "libp2p-bootstrap": "^0.14.0", "libp2p-crypto": "^0.21.2", - "libp2p-gossipsub": "0.13.0", "libp2p-mplex": "^0.10.4", "libp2p-websockets": "^0.16.1", "multiformats": "^9.6.5", @@ -44,6 +44,7 @@ "@size-limit/preset-big-lib": "^7.0.8", "@types/app-root-path": "^1.2.4", "@types/chai": "^4.2.15", + "@types/debug": "^4.1.7", "@types/mocha": "^9.1.0", "@types/node": "^17.0.6", "@types/secp256k1": "^4.0.2", @@ -640,6 +641,151 @@ "node": ">=6.9.0" } }, + "node_modules/@chainsafe/libp2p-gossipsub": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@chainsafe/libp2p-gossipsub/-/libp2p-gossipsub-2.0.0.tgz", + "integrity": "sha512-9tnxXdYbYEA7s4OuC/Ff5XHiKAPsfjSPdbcsdRrIanri0WI7rrwrj7xpOB60IvFIDmGRb2qQjs9qPQcy//670g==", + "dependencies": { + "@libp2p/components": "^1.0.0", + "@libp2p/crypto": "^1.0.0", + "@libp2p/interface-keys": "^1.0.2", + "@libp2p/interface-peer-id": "^1.0.2", + "@libp2p/interface-pubsub": "^1.0.1", + "@libp2p/interface-registrar": "^1.0.0", + "@libp2p/interfaces": "^3.0.2", + "@libp2p/logger": "^2.0.0", + "@libp2p/peer-id": "^1.1.13", + "@libp2p/peer-record": "^2.0.0", + "@libp2p/pubsub": "^2.0.0", + "@libp2p/topology": "^2.0.0", + "denque": "^1.5.0", + "err-code": "^3.0.1", + "iso-random-stream": "^2.0.2", + "it-pipe": "^2.0.3", + "multiformats": "^9.6.4", + "protons-runtime": "^1.0.4", + "uint8arrays": "^3.0.0" + } + }, + "node_modules/@chainsafe/libp2p-gossipsub/node_modules/@libp2p/crypto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/crypto/-/crypto-1.0.0.tgz", + "integrity": "sha512-oV/KaHE8XaJQDH+iDq4Kn4GaVWRsEXJnLXTpN+8hz00tuxxsE3+4g0OYaFCauAYeX1IcGPwMvUhdgujnKzpAbg==", + "dependencies": { + "@libp2p/interface-keys": "^1.0.2", + "@noble/ed25519": "^1.6.0", + "@noble/secp256k1": "^1.5.4", + "err-code": "^3.0.1", + "iso-random-stream": "^2.0.0", + "multiformats": "^9.4.5", + "node-forge": "^1.1.0", + "protons-runtime": "^1.0.4", + "uint8arrays": "^3.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@chainsafe/libp2p-gossipsub/node_modules/@libp2p/logger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/logger/-/logger-2.0.0.tgz", + "integrity": "sha512-aC1Yz4bni8Cui1tKCL5PzQSlS3BE/hhvyVnEHhcUz+GCo+MpbmyrZSPAb/m1e7bHrDDKkT1f9DSr7vgmS/NkuQ==", + "dependencies": { + "@libp2p/interface-peer-id": "^1.0.2", + "debug": "^4.3.3", + "interface-datastore": "^6.1.0", + "multiformats": "^9.6.3" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@chainsafe/libp2p-gossipsub/node_modules/@libp2p/peer-record": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@libp2p/peer-record/-/peer-record-2.0.2.tgz", + "integrity": "sha512-JkH9fBpBpGQYqDMJP3+LNtXLyjNCf0fVcBkdjyfPTSwUXTPJ5NxsluJAH+MZkkrJG9YJG22NgrZO5784GSLAaA==", + "dependencies": { + "@libp2p/crypto": "^1.0.0", + "@libp2p/interface-peer-id": "^1.0.2", + "@libp2p/interface-record": "^1.0.1", + "@libp2p/logger": "^2.0.0", + "@libp2p/peer-id": "^1.1.13", + "@libp2p/utils": "^2.0.0", + "@multiformats/multiaddr": "^10.1.5", + "err-code": "^3.0.1", + "interface-datastore": "^6.1.0", + "it-all": "^1.0.6", + "it-filter": "^1.0.3", + "it-foreach": "^0.1.1", + "it-map": "^1.0.6", + "it-pipe": "^2.0.3", + "multiformats": "^9.6.3", + "protons-runtime": "^1.0.4", + "uint8arrays": "^3.0.0", + "varint": "^6.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@chainsafe/libp2p-gossipsub/node_modules/@libp2p/utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@libp2p/utils/-/utils-2.0.1.tgz", + "integrity": "sha512-R0r9fkskuTmm5jMrlRXWpTdYJeDYcNQ1KdfSEmoVlCs5AlTeWn31+cdaHQihSEbkpEKtVCExfsZkwa3f7C1l8A==", + "dependencies": { + "@achingbrain/ip-address": "^8.1.0", + "@libp2p/interface-connection": "^1.0.1", + "@libp2p/interface-peer-store": "^1.0.0", + "@libp2p/logger": "^2.0.0", + "@multiformats/multiaddr": "^10.1.1", + "abortable-iterator": "^4.0.2", + "err-code": "^3.0.1", + "is-loopback-addr": "^2.0.1", + "it-stream-types": "^1.0.4", + "private-ip": "^2.1.1" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@chainsafe/libp2p-gossipsub/node_modules/abortable-iterator": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/abortable-iterator/-/abortable-iterator-4.0.2.tgz", + "integrity": "sha512-SJGELER5yXr9v3kiL6mT5RZ1qlyJ9hV4nm34+vfsdIM1lp3zENQvpsqKgykpFLgRMUn3lzlizLTpiOASW05/+g==", + "dependencies": { + "get-iterator": "^2.0.0", + "it-stream-types": "^1.0.3" + } + }, + "node_modules/@chainsafe/libp2p-gossipsub/node_modules/get-iterator": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-iterator/-/get-iterator-2.0.0.tgz", + "integrity": "sha512-BDJawD5PU2gZv6Vlp8O28H4GnZcsr3h9gZUvnAP5xXP3WOy/QAoOsyMepSkw21jur+4t5Vppde72ChjhTIzxzg==" + }, + "node_modules/@chainsafe/libp2p-gossipsub/node_modules/is-loopback-addr": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-loopback-addr/-/is-loopback-addr-2.0.1.tgz", + "integrity": "sha512-SEsepLbdWFb13B6U0tt6dYcUM0iK/U7XOC43N70Z4Qb88WpNtp+ospyNI9ddpqncs7Z7brAEsVBTQpaqSNntIw==" + }, + "node_modules/@chainsafe/libp2p-gossipsub/node_modules/it-pipe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/it-pipe/-/it-pipe-2.0.3.tgz", + "integrity": "sha512-1bfNC0v8yFDQu5KwZpHZrVO+nxOIEXfrobYtv55NXcsMfGu2SueMOCyCm63khejA+sCU0gLcRFQIfKWlBNNTGw==", + "dependencies": { + "it-merge": "^1.0.4", + "it-pushable": "^2.0.0", + "it-stream-types": "^1.0.3" + } + }, + "node_modules/@chainsafe/libp2p-gossipsub/node_modules/it-pushable": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/it-pushable/-/it-pushable-2.0.2.tgz", + "integrity": "sha512-f/n6HqXGDbHvuMR/3UN+S6W4y/bS1Pxg6Lb0oVc5dbflxy5f3NKkizKs86B8vzqHnB9hm1YpE0pgcEvI3FKDQw==" + }, "node_modules/@chainsafe/libp2p-noise": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/@chainsafe/libp2p-noise/-/libp2p-noise-5.0.3.tgz", @@ -1240,6 +1386,32 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, + "node_modules/@libp2p/components": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/components/-/components-1.0.0.tgz", + "integrity": "sha512-FksZm+bboEWAqHmw6GBRn+ppQEUwyt7TDTEn4J6nsA8OAXRi4R0bQc9KrdTrzomdaWjBTyAtA4hA1DYxQmmEmg==", + "dependencies": { + "@libp2p/interface-address-manager": "^1.0.1", + "@libp2p/interface-connection": "^1.0.0", + "@libp2p/interface-connection-manager": "^1.0.0", + "@libp2p/interface-content-routing": "^1.0.0", + "@libp2p/interface-dht": "^1.0.0", + "@libp2p/interface-metrics": "^1.0.2", + "@libp2p/interface-peer-id": "^1.0.2", + "@libp2p/interface-peer-routing": "^1.0.0", + "@libp2p/interface-peer-store": "^1.0.0", + "@libp2p/interface-pubsub": "^1.0.0", + "@libp2p/interface-registrar": "^1.0.0", + "@libp2p/interface-transport": "^1.0.0", + "@libp2p/interfaces": "^3.0.2", + "err-code": "^3.0.1", + "interface-datastore": "^6.1.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@libp2p/connection": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@libp2p/connection/-/connection-2.0.4.tgz", @@ -1319,6 +1491,93 @@ "resolved": "https://registry.npmjs.org/it-pushable/-/it-pushable-2.0.2.tgz", "integrity": "sha512-f/n6HqXGDbHvuMR/3UN+S6W4y/bS1Pxg6Lb0oVc5dbflxy5f3NKkizKs86B8vzqHnB9hm1YpE0pgcEvI3FKDQw==" }, + "node_modules/@libp2p/interface-address-manager": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@libp2p/interface-address-manager/-/interface-address-manager-1.0.2.tgz", + "integrity": "sha512-YUZzuY3yySXaeYd/LXkEDV/aKp6eJBsropXypwqeP3ErmEvkN06nbShQQAyNvRnloecYVAeLt2IZW2N9ImlRFg==", + "dependencies": { + "@libp2p/interfaces": "^3.0.0", + "@multiformats/multiaddr": "^10.2.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@libp2p/interface-connection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@libp2p/interface-connection/-/interface-connection-1.0.1.tgz", + "integrity": "sha512-4MP+RvqR5xu6EWgrebLo34HWm/X+hGXtzsCKmNfmLN9bpaYhEobzL4Rm3RYi/0ICrgAZmoU8n+x8widiuwERew==", + "dependencies": { + "@libp2p/interface-peer-id": "^1.0.0", + "@libp2p/interfaces": "^3.0.0", + "@multiformats/multiaddr": "^10.2.0", + "it-stream-types": "^1.0.4" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@libp2p/interface-connection-manager": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@libp2p/interface-connection-manager/-/interface-connection-manager-1.0.2.tgz", + "integrity": "sha512-92gM7sZhVidD+vsQbc+LbI4MMvxgRjFy9kUrrsOosbtCt0nl68rIeRFKRpfX92/4QY40tL41VXT69ijCUskEwg==", + "dependencies": { + "@libp2p/interface-connection": "^2.0.0", + "@libp2p/interface-peer-id": "^1.0.0", + "@libp2p/interfaces": "^3.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@libp2p/interface-connection-manager/node_modules/@libp2p/interface-connection": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@libp2p/interface-connection/-/interface-connection-2.1.1.tgz", + "integrity": "sha512-gjugaMsZvfo3r4tCc/yPifVQsfLogmEmJtW+eXMNiNDna3ZfmwWD9Z+KyEwuVsXKs0C4GESXei2y4SJSCEfkbA==", + "dependencies": { + "@libp2p/interface-peer-id": "^1.0.0", + "@libp2p/interfaces": "^3.0.0", + "@multiformats/multiaddr": "^10.2.0", + "it-stream-types": "^1.0.4" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@libp2p/interface-content-routing": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@libp2p/interface-content-routing/-/interface-content-routing-1.0.2.tgz", + "integrity": "sha512-Ue1X8XrZ4ymTMQk/GWom/EKfPB5Lu7zy33ohjSix26Da/HbBvkXBdnYGDj485vxSOZGZRqeBhh21nCVjD/yLyg==", + "dependencies": { + "@libp2p/interface-peer-info": "^1.0.0", + "@libp2p/interfaces": "^3.0.0", + "multiformats": "^9.6.3" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@libp2p/interface-dht": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@libp2p/interface-dht/-/interface-dht-1.0.1.tgz", + "integrity": "sha512-EToxQznHUnD9frWoHwq8DUaOa7RZ2qoo6beb1aWdQrEJsEdUBi62FHh9qrLkrL+E4W3rkl2+WrhSP6/iHxZZwQ==", + "dependencies": { + "@libp2p/interface-peer-discovery": "^1.0.0", + "@libp2p/interface-peer-id": "^1.0.0", + "@libp2p/interface-peer-info": "^1.0.0", + "@libp2p/interfaces": "^3.0.0", + "multiformats": "^9.6.3" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@libp2p/interface-keys": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@libp2p/interface-keys/-/interface-keys-1.0.3.tgz", @@ -1328,6 +1587,32 @@ "npm": ">=7.0.0" } }, + "node_modules/@libp2p/interface-metrics": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@libp2p/interface-metrics/-/interface-metrics-1.0.3.tgz", + "integrity": "sha512-kPSQY/dJqeJ92YeldismoIAxWn0z13kOz0UJY7M5QE7KcW5tJAYDNzDw6sIKKbbWN7bU6KJydnYBSRzhXpLlDw==", + "dependencies": { + "@libp2p/interface-peer-id": "^1.0.0", + "it-stream-types": "^1.0.4" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@libp2p/interface-peer-discovery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@libp2p/interface-peer-discovery/-/interface-peer-discovery-1.0.1.tgz", + "integrity": "sha512-ZqBhpX7fR3ROYQaGYV47YhyTJJzFDzyyEIsQ7NnDuG3KhcQb2PtocnN0sy1Ozm784M0oYveM/HjfuNxxcOwdYg==", + "dependencies": { + "@libp2p/interface-peer-info": "^1.0.0", + "@libp2p/interfaces": "^3.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@libp2p/interface-peer-id": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@libp2p/interface-peer-id/-/interface-peer-id-1.0.4.tgz", @@ -1353,6 +1638,20 @@ "npm": ">=7.0.0" } }, + "node_modules/@libp2p/interface-peer-routing": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@libp2p/interface-peer-routing/-/interface-peer-routing-1.0.1.tgz", + "integrity": "sha512-MKx2g0mIUI6qNuLv3xApKXR2ZrO9CUTT9ZPL0gvRlhpFCXovEkdWJ1h8KnmkR7tGPxKHt2bsCCJ8gqUaFeNstA==", + "dependencies": { + "@libp2p/interface-peer-id": "^1.0.0", + "@libp2p/interface-peer-info": "^1.0.0", + "@libp2p/interfaces": "^3.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@libp2p/interface-peer-store": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@libp2p/interface-peer-store/-/interface-peer-store-1.2.0.tgz", @@ -1369,6 +1668,41 @@ "npm": ">=7.0.0" } }, + "node_modules/@libp2p/interface-pubsub": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@libp2p/interface-pubsub/-/interface-pubsub-1.0.4.tgz", + "integrity": "sha512-BSkt0h4fbBBHcr3LCF7fTtAoCdQBjKbTGxCa4tIJpI3m5suxC5h6OrLC2rmrexOxR9aZRkr9da4VShRyOfRLag==", + "dependencies": { + "@libp2p/interface-connection": "^2.0.0", + "@libp2p/interface-peer-id": "^1.0.0", + "@libp2p/interfaces": "^3.0.0", + "it-pushable": "^3.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@libp2p/interface-pubsub/node_modules/@libp2p/interface-connection": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@libp2p/interface-connection/-/interface-connection-2.1.1.tgz", + "integrity": "sha512-gjugaMsZvfo3r4tCc/yPifVQsfLogmEmJtW+eXMNiNDna3ZfmwWD9Z+KyEwuVsXKs0C4GESXei2y4SJSCEfkbA==", + "dependencies": { + "@libp2p/interface-peer-id": "^1.0.0", + "@libp2p/interfaces": "^3.0.0", + "@multiformats/multiaddr": "^10.2.0", + "it-stream-types": "^1.0.4" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@libp2p/interface-pubsub/node_modules/it-pushable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/it-pushable/-/it-pushable-3.0.0.tgz", + "integrity": "sha512-Lpo9Q6wghDDoX8RyA2vIkpNckd5E0EY7RzIKwgiTPakrTmwDw7tKMx6DDJ1ZXrunYnHdKHnKSHYJL3Csya5U2w==" + }, "node_modules/@libp2p/interface-record": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@libp2p/interface-record/-/interface-record-1.0.2.tgz", @@ -1381,6 +1715,49 @@ "npm": ">=7.0.0" } }, + "node_modules/@libp2p/interface-registrar": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@libp2p/interface-registrar/-/interface-registrar-1.1.0.tgz", + "integrity": "sha512-1Uoyn3KAecklXhsit7ANrc0FP8+mh8pVXB7c8LwGpVwKHK4IPAAfB+beUZSrHHEabp16T87FokaVYRLrGYUqRQ==", + "dependencies": { + "@libp2p/interface-connection": "^1.0.0", + "@libp2p/interface-peer-id": "^1.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@libp2p/interface-transport": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@libp2p/interface-transport/-/interface-transport-1.0.2.tgz", + "integrity": "sha512-alOdxYfYQp/v2rMGc5V7GSfRUSJc4C38HfqI3CLEfSD9DJ3NFid804MvbOS/v4mP4yWtHyN/tfR5fmH8mmGqPw==", + "dependencies": { + "@libp2p/interface-connection": "^2.0.0", + "@libp2p/interfaces": "^3.0.0", + "@multiformats/multiaddr": "^10.2.0", + "it-stream-types": "^1.0.4" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@libp2p/interface-transport/node_modules/@libp2p/interface-connection": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@libp2p/interface-connection/-/interface-connection-2.1.1.tgz", + "integrity": "sha512-gjugaMsZvfo3r4tCc/yPifVQsfLogmEmJtW+eXMNiNDna3ZfmwWD9Z+KyEwuVsXKs0C4GESXei2y4SJSCEfkbA==", + "dependencies": { + "@libp2p/interface-peer-id": "^1.0.0", + "@libp2p/interfaces": "^3.0.0", + "@multiformats/multiaddr": "^10.2.0", + "it-stream-types": "^1.0.4" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@libp2p/interfaces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@libp2p/interfaces/-/interfaces-3.0.3.tgz", @@ -1756,6 +2133,146 @@ "resolved": "https://registry.npmjs.org/it-pushable/-/it-pushable-2.0.2.tgz", "integrity": "sha512-f/n6HqXGDbHvuMR/3UN+S6W4y/bS1Pxg6Lb0oVc5dbflxy5f3NKkizKs86B8vzqHnB9hm1YpE0pgcEvI3FKDQw==" }, + "node_modules/@libp2p/pubsub": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/pubsub/-/pubsub-2.0.0.tgz", + "integrity": "sha512-J10G3KMqKfnGnig1sLnLntcCVOu3wU9YqkKLFz10DqqsOFTFVXcYvvWFzCh1AAmo8jvrGBc0fBFLmT/B/fYfeA==", + "dependencies": { + "@libp2p/components": "^1.0.0", + "@libp2p/crypto": "^1.0.0", + "@libp2p/interfaces": "^3.0.2", + "@libp2p/logger": "^1.1.0", + "@libp2p/peer-collections": "^1.0.0", + "@libp2p/peer-id": "^1.1.0", + "@libp2p/topology": "^2.0.0", + "@multiformats/multiaddr": "^10.2.0", + "abortable-iterator": "^4.0.2", + "err-code": "^3.0.1", + "iso-random-stream": "^2.0.0", + "it-length-prefixed": "^7.0.1", + "it-pipe": "^2.0.3", + "it-pushable": "^3.0.0", + "multiformats": "^9.6.3", + "p-queue": "^7.2.0", + "uint8arrays": "^3.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@libp2p/pubsub/node_modules/@libp2p/crypto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/crypto/-/crypto-1.0.0.tgz", + "integrity": "sha512-oV/KaHE8XaJQDH+iDq4Kn4GaVWRsEXJnLXTpN+8hz00tuxxsE3+4g0OYaFCauAYeX1IcGPwMvUhdgujnKzpAbg==", + "dependencies": { + "@libp2p/interface-keys": "^1.0.2", + "@noble/ed25519": "^1.6.0", + "@noble/secp256k1": "^1.5.4", + "err-code": "^3.0.1", + "iso-random-stream": "^2.0.0", + "multiformats": "^9.4.5", + "node-forge": "^1.1.0", + "protons-runtime": "^1.0.4", + "uint8arrays": "^3.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@libp2p/pubsub/node_modules/abortable-iterator": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/abortable-iterator/-/abortable-iterator-4.0.2.tgz", + "integrity": "sha512-SJGELER5yXr9v3kiL6mT5RZ1qlyJ9hV4nm34+vfsdIM1lp3zENQvpsqKgykpFLgRMUn3lzlizLTpiOASW05/+g==", + "dependencies": { + "get-iterator": "^2.0.0", + "it-stream-types": "^1.0.3" + } + }, + "node_modules/@libp2p/pubsub/node_modules/get-iterator": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-iterator/-/get-iterator-2.0.0.tgz", + "integrity": "sha512-BDJawD5PU2gZv6Vlp8O28H4GnZcsr3h9gZUvnAP5xXP3WOy/QAoOsyMepSkw21jur+4t5Vppde72ChjhTIzxzg==" + }, + "node_modules/@libp2p/pubsub/node_modules/it-length-prefixed": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/it-length-prefixed/-/it-length-prefixed-7.0.1.tgz", + "integrity": "sha512-UozKoT0zZPUa0LO9OSq5KaLKPn83U7Vsy/BNAN0TUXfTI/pKrOz6RuyTSOok6NDad12FZsShBGnl9DKlfDT95g==", + "dependencies": { + "err-code": "^3.0.1", + "it-stream-types": "^1.0.4", + "uint8arraylist": "^1.2.0", + "varint": "^6.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@libp2p/pubsub/node_modules/it-pipe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/it-pipe/-/it-pipe-2.0.3.tgz", + "integrity": "sha512-1bfNC0v8yFDQu5KwZpHZrVO+nxOIEXfrobYtv55NXcsMfGu2SueMOCyCm63khejA+sCU0gLcRFQIfKWlBNNTGw==", + "dependencies": { + "it-merge": "^1.0.4", + "it-pushable": "^2.0.0", + "it-stream-types": "^1.0.3" + } + }, + "node_modules/@libp2p/pubsub/node_modules/it-pipe/node_modules/it-pushable": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/it-pushable/-/it-pushable-2.0.2.tgz", + "integrity": "sha512-f/n6HqXGDbHvuMR/3UN+S6W4y/bS1Pxg6Lb0oVc5dbflxy5f3NKkizKs86B8vzqHnB9hm1YpE0pgcEvI3FKDQw==" + }, + "node_modules/@libp2p/pubsub/node_modules/it-pushable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/it-pushable/-/it-pushable-3.0.0.tgz", + "integrity": "sha512-Lpo9Q6wghDDoX8RyA2vIkpNckd5E0EY7RzIKwgiTPakrTmwDw7tKMx6DDJ1ZXrunYnHdKHnKSHYJL3Csya5U2w==" + }, + "node_modules/@libp2p/pubsub/node_modules/p-queue": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-7.2.0.tgz", + "integrity": "sha512-Kvv7p13M46lTYLQ/PsZdaj/1Vj6u/8oiIJgyQyx4oVkOfHdd7M2EZvXigDvcsSzRwanCzQirV5bJPQFoSQt5MA==", + "dependencies": { + "eventemitter3": "^4.0.7", + "p-timeout": "^5.0.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@libp2p/pubsub/node_modules/p-timeout": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz", + "integrity": "sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@libp2p/topology": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/topology/-/topology-2.0.0.tgz", + "integrity": "sha512-BV6kIsDdChrjETwJsuvPf64BTScGgQEltJqZJGeEC6h12SnEX7Hh6bVPZqdIPSHzr97HpzXxP/f+fBEaLl/Ivg==", + "dependencies": { + "@libp2p/interface-peer-id": "^1.0.2", + "@libp2p/interface-registrar": "^1.0.0", + "@libp2p/logger": "^1.1.6", + "@multiformats/multiaddr": "^10.2.0", + "err-code": "^3.0.1", + "it-all": "^1.0.6" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@libp2p/tracked-map": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@libp2p/tracked-map/-/tracked-map-1.0.8.tgz", @@ -2439,6 +2956,7 @@ "version": "4.1.7", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "dev": true, "dependencies": { "@types/ms": "*" } @@ -2506,7 +3024,8 @@ "node_modules/@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", + "dev": true }, "node_modules/@types/node": { "version": "17.0.6", @@ -7198,9 +7717,9 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "node_modules/iso-random-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/iso-random-stream/-/iso-random-stream-2.0.0.tgz", - "integrity": "sha512-lGuIu104KfBV9ubYTSaE3GeAr6I69iggXxBHbTBc5u/XKlwlWl0LCytnkIZissaKqvxablwRD9B3ktVnmIUnEg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/iso-random-stream/-/iso-random-stream-2.0.2.tgz", + "integrity": "sha512-yJvs+Nnelic1L2vH2JzWvvPQFA4r7kSTnpST/+LkAQjSz0hos2oqLD+qIVi9Qk38Hoe7mNDt3j0S27R58MVjLQ==", "dependencies": { "events": "^3.3.0", "readable-stream": "^3.4.0" @@ -7962,42 +8481,6 @@ "node": ">=12.0.0" } }, - "node_modules/libp2p-gossipsub": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/libp2p-gossipsub/-/libp2p-gossipsub-0.13.0.tgz", - "integrity": "sha512-xy2jRZGmJpjy++Di6f1admtjve8Fx0z5l8NISTQS282egwbRMmTPE6/UeYktb6hNGAgtSTIwXdHjXmMOiTarFA==", - "dependencies": { - "@types/debug": "^4.1.7", - "debug": "^4.3.1", - "denque": "^1.5.0", - "err-code": "^3.0.1", - "it-pipe": "^1.1.0", - "libp2p-interfaces": "^4.0.4", - "peer-id": "^0.16.0", - "protobufjs": "^6.11.2", - "uint8arrays": "^3.0.0" - } - }, - "node_modules/libp2p-interfaces": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/libp2p-interfaces/-/libp2p-interfaces-4.0.6.tgz", - "integrity": "sha512-3KjzNEIWhi+VoOamLvgKKUE/xqwxSw/JYqsBnfMhAWVRvRtosROtVT03wci2XbuuowCYw+/hEX1xKJIR1w5n0A==", - "dependencies": { - "abortable-iterator": "^3.0.0", - "debug": "^4.3.1", - "err-code": "^3.0.1", - "it-length-prefixed": "^5.0.2", - "it-pipe": "^1.1.0", - "it-pushable": "^1.4.2", - "libp2p-crypto": "^0.21.0", - "multiaddr": "^10.0.0", - "multiformats": "^9.1.2", - "p-queue": "^6.6.2", - "peer-id": "^0.16.0", - "protobufjs": "^6.10.2", - "uint8arrays": "^3.0.0" - } - }, "node_modules/libp2p-mplex": { "version": "0.10.7", "resolved": "https://registry.npmjs.org/libp2p-mplex/-/libp2p-mplex-0.10.7.tgz", @@ -9752,14 +10235,6 @@ "p-defer": "^3.0.0" } }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "engines": { - "node": ">=4" - } - }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -9819,32 +10294,6 @@ "node": ">=8" } }, - "node_modules/p-queue": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", - "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", - "dependencies": { - "eventemitter3": "^4.0.4", - "p-timeout": "^3.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-queue/node_modules/p-timeout": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", - "dependencies": { - "p-finally": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/p-reflect": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-reflect/-/p-reflect-3.0.0.tgz", @@ -13538,6 +13987,137 @@ "to-fast-properties": "^2.0.0" } }, + "@chainsafe/libp2p-gossipsub": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@chainsafe/libp2p-gossipsub/-/libp2p-gossipsub-2.0.0.tgz", + "integrity": "sha512-9tnxXdYbYEA7s4OuC/Ff5XHiKAPsfjSPdbcsdRrIanri0WI7rrwrj7xpOB60IvFIDmGRb2qQjs9qPQcy//670g==", + "requires": { + "@libp2p/components": "^1.0.0", + "@libp2p/crypto": "^1.0.0", + "@libp2p/interface-keys": "^1.0.2", + "@libp2p/interface-peer-id": "^1.0.2", + "@libp2p/interface-pubsub": "^1.0.1", + "@libp2p/interface-registrar": "^1.0.0", + "@libp2p/interfaces": "^3.0.2", + "@libp2p/logger": "^2.0.0", + "@libp2p/peer-id": "^1.1.13", + "@libp2p/peer-record": "^2.0.0", + "@libp2p/pubsub": "^2.0.0", + "@libp2p/topology": "^2.0.0", + "denque": "^1.5.0", + "err-code": "^3.0.1", + "iso-random-stream": "^2.0.2", + "it-pipe": "^2.0.3", + "multiformats": "^9.6.4", + "protons-runtime": "^1.0.4", + "uint8arrays": "^3.0.0" + }, + "dependencies": { + "@libp2p/crypto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/crypto/-/crypto-1.0.0.tgz", + "integrity": "sha512-oV/KaHE8XaJQDH+iDq4Kn4GaVWRsEXJnLXTpN+8hz00tuxxsE3+4g0OYaFCauAYeX1IcGPwMvUhdgujnKzpAbg==", + "requires": { + "@libp2p/interface-keys": "^1.0.2", + "@noble/ed25519": "^1.6.0", + "@noble/secp256k1": "^1.5.4", + "err-code": "^3.0.1", + "iso-random-stream": "^2.0.0", + "multiformats": "^9.4.5", + "node-forge": "^1.1.0", + "protons-runtime": "^1.0.4", + "uint8arrays": "^3.0.0" + } + }, + "@libp2p/logger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/logger/-/logger-2.0.0.tgz", + "integrity": "sha512-aC1Yz4bni8Cui1tKCL5PzQSlS3BE/hhvyVnEHhcUz+GCo+MpbmyrZSPAb/m1e7bHrDDKkT1f9DSr7vgmS/NkuQ==", + "requires": { + "@libp2p/interface-peer-id": "^1.0.2", + "debug": "^4.3.3", + "interface-datastore": "^6.1.0", + "multiformats": "^9.6.3" + } + }, + "@libp2p/peer-record": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@libp2p/peer-record/-/peer-record-2.0.2.tgz", + "integrity": "sha512-JkH9fBpBpGQYqDMJP3+LNtXLyjNCf0fVcBkdjyfPTSwUXTPJ5NxsluJAH+MZkkrJG9YJG22NgrZO5784GSLAaA==", + "requires": { + "@libp2p/crypto": "^1.0.0", + "@libp2p/interface-peer-id": "^1.0.2", + "@libp2p/interface-record": "^1.0.1", + "@libp2p/logger": "^2.0.0", + "@libp2p/peer-id": "^1.1.13", + "@libp2p/utils": "^2.0.0", + "@multiformats/multiaddr": "^10.1.5", + "err-code": "^3.0.1", + "interface-datastore": "^6.1.0", + "it-all": "^1.0.6", + "it-filter": "^1.0.3", + "it-foreach": "^0.1.1", + "it-map": "^1.0.6", + "it-pipe": "^2.0.3", + "multiformats": "^9.6.3", + "protons-runtime": "^1.0.4", + "uint8arrays": "^3.0.0", + "varint": "^6.0.0" + } + }, + "@libp2p/utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@libp2p/utils/-/utils-2.0.1.tgz", + "integrity": "sha512-R0r9fkskuTmm5jMrlRXWpTdYJeDYcNQ1KdfSEmoVlCs5AlTeWn31+cdaHQihSEbkpEKtVCExfsZkwa3f7C1l8A==", + "requires": { + "@achingbrain/ip-address": "^8.1.0", + "@libp2p/interface-connection": "^1.0.1", + "@libp2p/interface-peer-store": "^1.0.0", + "@libp2p/logger": "^2.0.0", + "@multiformats/multiaddr": "^10.1.1", + "abortable-iterator": "^4.0.2", + "err-code": "^3.0.1", + "is-loopback-addr": "^2.0.1", + "it-stream-types": "^1.0.4", + "private-ip": "^2.1.1" + } + }, + "abortable-iterator": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/abortable-iterator/-/abortable-iterator-4.0.2.tgz", + "integrity": "sha512-SJGELER5yXr9v3kiL6mT5RZ1qlyJ9hV4nm34+vfsdIM1lp3zENQvpsqKgykpFLgRMUn3lzlizLTpiOASW05/+g==", + "requires": { + "get-iterator": "^2.0.0", + "it-stream-types": "^1.0.3" + } + }, + "get-iterator": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-iterator/-/get-iterator-2.0.0.tgz", + "integrity": "sha512-BDJawD5PU2gZv6Vlp8O28H4GnZcsr3h9gZUvnAP5xXP3WOy/QAoOsyMepSkw21jur+4t5Vppde72ChjhTIzxzg==" + }, + "is-loopback-addr": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-loopback-addr/-/is-loopback-addr-2.0.1.tgz", + "integrity": "sha512-SEsepLbdWFb13B6U0tt6dYcUM0iK/U7XOC43N70Z4Qb88WpNtp+ospyNI9ddpqncs7Z7brAEsVBTQpaqSNntIw==" + }, + "it-pipe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/it-pipe/-/it-pipe-2.0.3.tgz", + "integrity": "sha512-1bfNC0v8yFDQu5KwZpHZrVO+nxOIEXfrobYtv55NXcsMfGu2SueMOCyCm63khejA+sCU0gLcRFQIfKWlBNNTGw==", + "requires": { + "it-merge": "^1.0.4", + "it-pushable": "^2.0.0", + "it-stream-types": "^1.0.3" + } + }, + "it-pushable": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/it-pushable/-/it-pushable-2.0.2.tgz", + "integrity": "sha512-f/n6HqXGDbHvuMR/3UN+S6W4y/bS1Pxg6Lb0oVc5dbflxy5f3NKkizKs86B8vzqHnB9hm1YpE0pgcEvI3FKDQw==" + } + } + }, "@chainsafe/libp2p-noise": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/@chainsafe/libp2p-noise/-/libp2p-noise-5.0.3.tgz", @@ -14049,6 +14629,28 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, + "@libp2p/components": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/components/-/components-1.0.0.tgz", + "integrity": "sha512-FksZm+bboEWAqHmw6GBRn+ppQEUwyt7TDTEn4J6nsA8OAXRi4R0bQc9KrdTrzomdaWjBTyAtA4hA1DYxQmmEmg==", + "requires": { + "@libp2p/interface-address-manager": "^1.0.1", + "@libp2p/interface-connection": "^1.0.0", + "@libp2p/interface-connection-manager": "^1.0.0", + "@libp2p/interface-content-routing": "^1.0.0", + "@libp2p/interface-dht": "^1.0.0", + "@libp2p/interface-metrics": "^1.0.2", + "@libp2p/interface-peer-id": "^1.0.2", + "@libp2p/interface-peer-routing": "^1.0.0", + "@libp2p/interface-peer-store": "^1.0.0", + "@libp2p/interface-pubsub": "^1.0.0", + "@libp2p/interface-registrar": "^1.0.0", + "@libp2p/interface-transport": "^1.0.0", + "@libp2p/interfaces": "^3.0.2", + "err-code": "^3.0.1", + "interface-datastore": "^6.1.0" + } + }, "@libp2p/connection": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@libp2p/connection/-/connection-2.0.4.tgz", @@ -14116,11 +14718,94 @@ } } }, + "@libp2p/interface-address-manager": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@libp2p/interface-address-manager/-/interface-address-manager-1.0.2.tgz", + "integrity": "sha512-YUZzuY3yySXaeYd/LXkEDV/aKp6eJBsropXypwqeP3ErmEvkN06nbShQQAyNvRnloecYVAeLt2IZW2N9ImlRFg==", + "requires": { + "@libp2p/interfaces": "^3.0.0", + "@multiformats/multiaddr": "^10.2.0" + } + }, + "@libp2p/interface-connection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@libp2p/interface-connection/-/interface-connection-1.0.1.tgz", + "integrity": "sha512-4MP+RvqR5xu6EWgrebLo34HWm/X+hGXtzsCKmNfmLN9bpaYhEobzL4Rm3RYi/0ICrgAZmoU8n+x8widiuwERew==", + "requires": { + "@libp2p/interface-peer-id": "^1.0.0", + "@libp2p/interfaces": "^3.0.0", + "@multiformats/multiaddr": "^10.2.0", + "it-stream-types": "^1.0.4" + } + }, + "@libp2p/interface-connection-manager": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@libp2p/interface-connection-manager/-/interface-connection-manager-1.0.2.tgz", + "integrity": "sha512-92gM7sZhVidD+vsQbc+LbI4MMvxgRjFy9kUrrsOosbtCt0nl68rIeRFKRpfX92/4QY40tL41VXT69ijCUskEwg==", + "requires": { + "@libp2p/interface-connection": "^2.0.0", + "@libp2p/interface-peer-id": "^1.0.0", + "@libp2p/interfaces": "^3.0.0" + }, + "dependencies": { + "@libp2p/interface-connection": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@libp2p/interface-connection/-/interface-connection-2.1.1.tgz", + "integrity": "sha512-gjugaMsZvfo3r4tCc/yPifVQsfLogmEmJtW+eXMNiNDna3ZfmwWD9Z+KyEwuVsXKs0C4GESXei2y4SJSCEfkbA==", + "requires": { + "@libp2p/interface-peer-id": "^1.0.0", + "@libp2p/interfaces": "^3.0.0", + "@multiformats/multiaddr": "^10.2.0", + "it-stream-types": "^1.0.4" + } + } + } + }, + "@libp2p/interface-content-routing": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@libp2p/interface-content-routing/-/interface-content-routing-1.0.2.tgz", + "integrity": "sha512-Ue1X8XrZ4ymTMQk/GWom/EKfPB5Lu7zy33ohjSix26Da/HbBvkXBdnYGDj485vxSOZGZRqeBhh21nCVjD/yLyg==", + "requires": { + "@libp2p/interface-peer-info": "^1.0.0", + "@libp2p/interfaces": "^3.0.0", + "multiformats": "^9.6.3" + } + }, + "@libp2p/interface-dht": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@libp2p/interface-dht/-/interface-dht-1.0.1.tgz", + "integrity": "sha512-EToxQznHUnD9frWoHwq8DUaOa7RZ2qoo6beb1aWdQrEJsEdUBi62FHh9qrLkrL+E4W3rkl2+WrhSP6/iHxZZwQ==", + "requires": { + "@libp2p/interface-peer-discovery": "^1.0.0", + "@libp2p/interface-peer-id": "^1.0.0", + "@libp2p/interface-peer-info": "^1.0.0", + "@libp2p/interfaces": "^3.0.0", + "multiformats": "^9.6.3" + } + }, "@libp2p/interface-keys": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@libp2p/interface-keys/-/interface-keys-1.0.3.tgz", "integrity": "sha512-K8/HlRl/swbVTWuGHNHF28EytszYfUhKgUHfv8CdbMk9ZA/bgO4uU+d9rcrg/Dhw3511U3aRz2bwl2psn6rJfg==" }, + "@libp2p/interface-metrics": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@libp2p/interface-metrics/-/interface-metrics-1.0.3.tgz", + "integrity": "sha512-kPSQY/dJqeJ92YeldismoIAxWn0z13kOz0UJY7M5QE7KcW5tJAYDNzDw6sIKKbbWN7bU6KJydnYBSRzhXpLlDw==", + "requires": { + "@libp2p/interface-peer-id": "^1.0.0", + "it-stream-types": "^1.0.4" + } + }, + "@libp2p/interface-peer-discovery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@libp2p/interface-peer-discovery/-/interface-peer-discovery-1.0.1.tgz", + "integrity": "sha512-ZqBhpX7fR3ROYQaGYV47YhyTJJzFDzyyEIsQ7NnDuG3KhcQb2PtocnN0sy1Ozm784M0oYveM/HjfuNxxcOwdYg==", + "requires": { + "@libp2p/interface-peer-info": "^1.0.0", + "@libp2p/interfaces": "^3.0.0" + } + }, "@libp2p/interface-peer-id": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@libp2p/interface-peer-id/-/interface-peer-id-1.0.4.tgz", @@ -14138,6 +14823,16 @@ "@multiformats/multiaddr": "^10.2.0" } }, + "@libp2p/interface-peer-routing": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@libp2p/interface-peer-routing/-/interface-peer-routing-1.0.1.tgz", + "integrity": "sha512-MKx2g0mIUI6qNuLv3xApKXR2ZrO9CUTT9ZPL0gvRlhpFCXovEkdWJ1h8KnmkR7tGPxKHt2bsCCJ8gqUaFeNstA==", + "requires": { + "@libp2p/interface-peer-id": "^1.0.0", + "@libp2p/interface-peer-info": "^1.0.0", + "@libp2p/interfaces": "^3.0.0" + } + }, "@libp2p/interface-peer-store": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@libp2p/interface-peer-store/-/interface-peer-store-1.2.0.tgz", @@ -14150,6 +14845,35 @@ "@multiformats/multiaddr": "^10.2.0" } }, + "@libp2p/interface-pubsub": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@libp2p/interface-pubsub/-/interface-pubsub-1.0.4.tgz", + "integrity": "sha512-BSkt0h4fbBBHcr3LCF7fTtAoCdQBjKbTGxCa4tIJpI3m5suxC5h6OrLC2rmrexOxR9aZRkr9da4VShRyOfRLag==", + "requires": { + "@libp2p/interface-connection": "^2.0.0", + "@libp2p/interface-peer-id": "^1.0.0", + "@libp2p/interfaces": "^3.0.0", + "it-pushable": "^3.0.0" + }, + "dependencies": { + "@libp2p/interface-connection": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@libp2p/interface-connection/-/interface-connection-2.1.1.tgz", + "integrity": "sha512-gjugaMsZvfo3r4tCc/yPifVQsfLogmEmJtW+eXMNiNDna3ZfmwWD9Z+KyEwuVsXKs0C4GESXei2y4SJSCEfkbA==", + "requires": { + "@libp2p/interface-peer-id": "^1.0.0", + "@libp2p/interfaces": "^3.0.0", + "@multiformats/multiaddr": "^10.2.0", + "it-stream-types": "^1.0.4" + } + }, + "it-pushable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/it-pushable/-/it-pushable-3.0.0.tgz", + "integrity": "sha512-Lpo9Q6wghDDoX8RyA2vIkpNckd5E0EY7RzIKwgiTPakrTmwDw7tKMx6DDJ1ZXrunYnHdKHnKSHYJL3Csya5U2w==" + } + } + }, "@libp2p/interface-record": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@libp2p/interface-record/-/interface-record-1.0.2.tgz", @@ -14158,6 +14882,39 @@ "@libp2p/interface-peer-id": "^1.0.0" } }, + "@libp2p/interface-registrar": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@libp2p/interface-registrar/-/interface-registrar-1.1.0.tgz", + "integrity": "sha512-1Uoyn3KAecklXhsit7ANrc0FP8+mh8pVXB7c8LwGpVwKHK4IPAAfB+beUZSrHHEabp16T87FokaVYRLrGYUqRQ==", + "requires": { + "@libp2p/interface-connection": "^1.0.0", + "@libp2p/interface-peer-id": "^1.0.0" + } + }, + "@libp2p/interface-transport": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@libp2p/interface-transport/-/interface-transport-1.0.2.tgz", + "integrity": "sha512-alOdxYfYQp/v2rMGc5V7GSfRUSJc4C38HfqI3CLEfSD9DJ3NFid804MvbOS/v4mP4yWtHyN/tfR5fmH8mmGqPw==", + "requires": { + "@libp2p/interface-connection": "^2.0.0", + "@libp2p/interfaces": "^3.0.0", + "@multiformats/multiaddr": "^10.2.0", + "it-stream-types": "^1.0.4" + }, + "dependencies": { + "@libp2p/interface-connection": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@libp2p/interface-connection/-/interface-connection-2.1.1.tgz", + "integrity": "sha512-gjugaMsZvfo3r4tCc/yPifVQsfLogmEmJtW+eXMNiNDna3ZfmwWD9Z+KyEwuVsXKs0C4GESXei2y4SJSCEfkbA==", + "requires": { + "@libp2p/interface-peer-id": "^1.0.0", + "@libp2p/interfaces": "^3.0.0", + "@multiformats/multiaddr": "^10.2.0", + "it-stream-types": "^1.0.4" + } + } + } + }, "@libp2p/interfaces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@libp2p/interfaces/-/interfaces-3.0.3.tgz", @@ -14475,6 +15232,122 @@ } } }, + "@libp2p/pubsub": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/pubsub/-/pubsub-2.0.0.tgz", + "integrity": "sha512-J10G3KMqKfnGnig1sLnLntcCVOu3wU9YqkKLFz10DqqsOFTFVXcYvvWFzCh1AAmo8jvrGBc0fBFLmT/B/fYfeA==", + "requires": { + "@libp2p/components": "^1.0.0", + "@libp2p/crypto": "^1.0.0", + "@libp2p/interfaces": "^3.0.2", + "@libp2p/logger": "^1.1.0", + "@libp2p/peer-collections": "^1.0.0", + "@libp2p/peer-id": "^1.1.0", + "@libp2p/topology": "^2.0.0", + "@multiformats/multiaddr": "^10.2.0", + "abortable-iterator": "^4.0.2", + "err-code": "^3.0.1", + "iso-random-stream": "^2.0.0", + "it-length-prefixed": "^7.0.1", + "it-pipe": "^2.0.3", + "it-pushable": "^3.0.0", + "multiformats": "^9.6.3", + "p-queue": "^7.2.0", + "uint8arrays": "^3.0.0" + }, + "dependencies": { + "@libp2p/crypto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/crypto/-/crypto-1.0.0.tgz", + "integrity": "sha512-oV/KaHE8XaJQDH+iDq4Kn4GaVWRsEXJnLXTpN+8hz00tuxxsE3+4g0OYaFCauAYeX1IcGPwMvUhdgujnKzpAbg==", + "requires": { + "@libp2p/interface-keys": "^1.0.2", + "@noble/ed25519": "^1.6.0", + "@noble/secp256k1": "^1.5.4", + "err-code": "^3.0.1", + "iso-random-stream": "^2.0.0", + "multiformats": "^9.4.5", + "node-forge": "^1.1.0", + "protons-runtime": "^1.0.4", + "uint8arrays": "^3.0.0" + } + }, + "abortable-iterator": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/abortable-iterator/-/abortable-iterator-4.0.2.tgz", + "integrity": "sha512-SJGELER5yXr9v3kiL6mT5RZ1qlyJ9hV4nm34+vfsdIM1lp3zENQvpsqKgykpFLgRMUn3lzlizLTpiOASW05/+g==", + "requires": { + "get-iterator": "^2.0.0", + "it-stream-types": "^1.0.3" + } + }, + "get-iterator": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-iterator/-/get-iterator-2.0.0.tgz", + "integrity": "sha512-BDJawD5PU2gZv6Vlp8O28H4GnZcsr3h9gZUvnAP5xXP3WOy/QAoOsyMepSkw21jur+4t5Vppde72ChjhTIzxzg==" + }, + "it-length-prefixed": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/it-length-prefixed/-/it-length-prefixed-7.0.1.tgz", + "integrity": "sha512-UozKoT0zZPUa0LO9OSq5KaLKPn83U7Vsy/BNAN0TUXfTI/pKrOz6RuyTSOok6NDad12FZsShBGnl9DKlfDT95g==", + "requires": { + "err-code": "^3.0.1", + "it-stream-types": "^1.0.4", + "uint8arraylist": "^1.2.0", + "varint": "^6.0.0" + } + }, + "it-pipe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/it-pipe/-/it-pipe-2.0.3.tgz", + "integrity": "sha512-1bfNC0v8yFDQu5KwZpHZrVO+nxOIEXfrobYtv55NXcsMfGu2SueMOCyCm63khejA+sCU0gLcRFQIfKWlBNNTGw==", + "requires": { + "it-merge": "^1.0.4", + "it-pushable": "^2.0.0", + "it-stream-types": "^1.0.3" + }, + "dependencies": { + "it-pushable": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/it-pushable/-/it-pushable-2.0.2.tgz", + "integrity": "sha512-f/n6HqXGDbHvuMR/3UN+S6W4y/bS1Pxg6Lb0oVc5dbflxy5f3NKkizKs86B8vzqHnB9hm1YpE0pgcEvI3FKDQw==" + } + } + }, + "it-pushable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/it-pushable/-/it-pushable-3.0.0.tgz", + "integrity": "sha512-Lpo9Q6wghDDoX8RyA2vIkpNckd5E0EY7RzIKwgiTPakrTmwDw7tKMx6DDJ1ZXrunYnHdKHnKSHYJL3Csya5U2w==" + }, + "p-queue": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-7.2.0.tgz", + "integrity": "sha512-Kvv7p13M46lTYLQ/PsZdaj/1Vj6u/8oiIJgyQyx4oVkOfHdd7M2EZvXigDvcsSzRwanCzQirV5bJPQFoSQt5MA==", + "requires": { + "eventemitter3": "^4.0.7", + "p-timeout": "^5.0.2" + } + }, + "p-timeout": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz", + "integrity": "sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==" + } + } + }, + "@libp2p/topology": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@libp2p/topology/-/topology-2.0.0.tgz", + "integrity": "sha512-BV6kIsDdChrjETwJsuvPf64BTScGgQEltJqZJGeEC6h12SnEX7Hh6bVPZqdIPSHzr97HpzXxP/f+fBEaLl/Ivg==", + "requires": { + "@libp2p/interface-peer-id": "^1.0.2", + "@libp2p/interface-registrar": "^1.0.0", + "@libp2p/logger": "^1.1.6", + "@multiformats/multiaddr": "^10.2.0", + "err-code": "^3.0.1", + "it-all": "^1.0.6" + } + }, "@libp2p/tracked-map": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@libp2p/tracked-map/-/tracked-map-1.0.8.tgz", @@ -15036,6 +15909,7 @@ "version": "4.1.7", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "dev": true, "requires": { "@types/ms": "*" } @@ -15103,7 +15977,8 @@ "@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", + "dev": true }, "@types/node": { "version": "17.0.6", @@ -18579,9 +19454,9 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "iso-random-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/iso-random-stream/-/iso-random-stream-2.0.0.tgz", - "integrity": "sha512-lGuIu104KfBV9ubYTSaE3GeAr6I69iggXxBHbTBc5u/XKlwlWl0LCytnkIZissaKqvxablwRD9B3ktVnmIUnEg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/iso-random-stream/-/iso-random-stream-2.0.2.tgz", + "integrity": "sha512-yJvs+Nnelic1L2vH2JzWvvPQFA4r7kSTnpST/+LkAQjSz0hos2oqLD+qIVi9Qk38Hoe7mNDt3j0S27R58MVjLQ==", "requires": { "events": "^3.3.0", "readable-stream": "^3.4.0" @@ -19317,42 +20192,6 @@ "uint8arrays": "^3.0.0" } }, - "libp2p-gossipsub": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/libp2p-gossipsub/-/libp2p-gossipsub-0.13.0.tgz", - "integrity": "sha512-xy2jRZGmJpjy++Di6f1admtjve8Fx0z5l8NISTQS282egwbRMmTPE6/UeYktb6hNGAgtSTIwXdHjXmMOiTarFA==", - "requires": { - "@types/debug": "^4.1.7", - "debug": "^4.3.1", - "denque": "^1.5.0", - "err-code": "^3.0.1", - "it-pipe": "^1.1.0", - "libp2p-interfaces": "^4.0.4", - "peer-id": "^0.16.0", - "protobufjs": "^6.11.2", - "uint8arrays": "^3.0.0" - } - }, - "libp2p-interfaces": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/libp2p-interfaces/-/libp2p-interfaces-4.0.6.tgz", - "integrity": "sha512-3KjzNEIWhi+VoOamLvgKKUE/xqwxSw/JYqsBnfMhAWVRvRtosROtVT03wci2XbuuowCYw+/hEX1xKJIR1w5n0A==", - "requires": { - "abortable-iterator": "^3.0.0", - "debug": "^4.3.1", - "err-code": "^3.0.1", - "it-length-prefixed": "^5.0.2", - "it-pipe": "^1.1.0", - "it-pushable": "^1.4.2", - "libp2p-crypto": "^0.21.0", - "multiaddr": "^10.0.0", - "multiformats": "^9.1.2", - "p-queue": "^6.6.2", - "peer-id": "^0.16.0", - "protobufjs": "^6.10.2", - "uint8arrays": "^3.0.0" - } - }, "libp2p-mplex": { "version": "0.10.7", "resolved": "https://registry.npmjs.org/libp2p-mplex/-/libp2p-mplex-0.10.7.tgz", @@ -20602,11 +21441,6 @@ "p-defer": "^3.0.0" } }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" - }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -20650,25 +21484,6 @@ "aggregate-error": "^3.0.0" } }, - "p-queue": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", - "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", - "requires": { - "eventemitter3": "^4.0.4", - "p-timeout": "^3.2.0" - }, - "dependencies": { - "p-timeout": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", - "requires": { - "p-finally": "^1.0.0" - } - } - } - }, "p-reflect": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-reflect/-/p-reflect-3.0.0.tgz", diff --git a/package.json b/package.json index d79081621e..fa3e9cb2d4 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "node": ">=16" }, "dependencies": { + "@chainsafe/libp2p-gossipsub": "^2.0.0", "@chainsafe/libp2p-noise": "^5.0.0", "@ethersproject/rlp": "^5.5.0", "@libp2p/interface-peer-id": "^1.0.2", @@ -74,7 +75,7 @@ "@libp2p/peer-id": "^1.1.10", "@multiformats/multiaddr": "^10.2.0", "@noble/secp256k1": "^1.3.4", - "debug": "^4.3.1", + "debug": "^4.3.4", "dns-query": "^0.11.1", "hi-base32": "^0.5.1", "it-concat": "^2.0.0", @@ -84,7 +85,6 @@ "libp2p": "^0.37.3", "libp2p-bootstrap": "^0.14.0", "libp2p-crypto": "^0.21.2", - "libp2p-gossipsub": "0.13.0", "libp2p-mplex": "^0.10.4", "libp2p-websockets": "^0.16.1", "multiformats": "^9.6.5", @@ -101,6 +101,7 @@ "@size-limit/preset-big-lib": "^7.0.8", "@types/app-root-path": "^1.2.4", "@types/chai": "^4.2.15", + "@types/debug": "^4.1.7", "@types/mocha": "^9.1.0", "@types/node": "^17.0.6", "@types/secp256k1": "^4.0.2", diff --git a/src/lib/discovery/random_subset.ts b/src/lib/discovery/random_subset.ts index be038946a4..27899cfd09 100644 --- a/src/lib/discovery/random_subset.ts +++ b/src/lib/discovery/random_subset.ts @@ -1,4 +1,4 @@ -import { shuffle } from "libp2p-gossipsub/src/utils/index"; +import { shuffle } from "@chainsafe/libp2p-gossipsub/utils/shuffle"; export function getPseudoRandomSubset( values: T[], diff --git a/src/lib/waku.node.spec.ts b/src/lib/waku.node.spec.ts index 9d42293ef8..2d38464638 100644 --- a/src/lib/waku.node.spec.ts +++ b/src/lib/waku.node.spec.ts @@ -201,7 +201,7 @@ describe("Wait for remote peer / get peers", function () { const nimPeerId = multiAddrWithId.getPeerId(); expect(nimPeerId).to.not.be.undefined; - expect(peers.has(nimPeerId as string)).to.be.true; + expect(peers).to.includes(nimPeerId); }); it("Relay - dialed after", async function () { @@ -219,11 +219,12 @@ describe("Wait for remote peer / get peers", function () { await waku.dial(multiAddrWithId); await waitPromise; + // TODO: Should getMeshPeers be used instead? const peers = waku.relay.getPeers(); const nimPeerId = multiAddrWithId.getPeerId(); expect(nimPeerId).to.not.be.undefined; - expect(peers.has(nimPeerId as string)).to.be.true; + expect(peers).includes(nimPeerId); }); it("Relay - times out", function (done) { diff --git a/src/lib/waku.ts b/src/lib/waku.ts index f73d66751f..91298f3ecf 100644 --- a/src/lib/waku.ts +++ b/src/lib/waku.ts @@ -128,8 +128,7 @@ export class Waku { options.relayKeepAlive || DefaultRelayKeepAliveValueSecs; libp2p.connectionManager.addEventListener("peer:connect", (evt) => { - const { detail: connection } = evt; - this.startKeepAlive(connection.remotePeer, pingKeepAlive, relayKeepAlive); + this.startKeepAlive(evt.detail.remotePeer, pingKeepAlive, relayKeepAlive); }); /** @@ -144,8 +143,7 @@ export class Waku { * @see https://github.com/libp2p/js-libp2p/blob/bad9e8c0ff58d60a78314077720c82ae331cc55b/doc/API.md?plain=1#L2100 */ libp2p.connectionManager.addEventListener("peer:disconnect", (evt) => { - const { detail: connection } = evt; - this.stopKeepAlive(connection.remotePeer); + this.stopKeepAlive(evt.detail.remotePeer); }); options?.decryptionKeys?.forEach((key) => { @@ -372,10 +370,21 @@ export class Waku { if (protocols.includes(Protocols.Store)) { const storePromise = (async (): Promise => { - for await (const peer of this.store.peers) { - dbg("Store peer found", peer.id.toString()); - break; + const peers = await this.store.peers(); + + if (peers.length) { + dbg("Store peer found: ", peers[0].id.toString()); + return; } + + await new Promise((resolve) => { + this.libp2p.peerStore.addEventListener("change:protocols", (evt) => { + if (evt.detail.protocols.includes(LightPushCodec)) { + dbg("Resolving for", LightPushCodec, evt.detail.protocols); + resolve(); + } + }); + }); })(); promises.push(storePromise); } diff --git a/src/lib/waku_relay/get_relay_peers.ts b/src/lib/waku_relay/get_relay_peers.ts deleted file mode 100644 index df03553dab..0000000000 --- a/src/lib/waku_relay/get_relay_peers.ts +++ /dev/null @@ -1,48 +0,0 @@ -import Gossipsub from "libp2p-gossipsub"; -import { shuffle } from "libp2p-gossipsub/src/utils"; - -import { RelayCodecs } from "./constants"; - -/** - * Given a topic, returns up to count peers subscribed to that topic - * that pass an optional filter function - * - * @param {Gossipsub} router - * @param {String} topic - * @param {Number} count - * @param {Function} [filter] a function to filter acceptable peers - * @returns {Set} - * - */ -export function getRelayPeers( - router: Gossipsub, - topic: string, - count: number, - filter: (id: string) => boolean = (): boolean => true -): Set { - const peersInTopic = router.topics.get(topic); - if (!peersInTopic) { - return new Set(); - } - - // Adds all peers using our protocol - // that also pass the filter function - let peers: string[] = []; - peersInTopic.forEach((id: string) => { - const peerStreams = router.peers.get(id); - if (!peerStreams) { - return; - } - if (RelayCodecs.includes(peerStreams.protocol) && filter(id)) { - peers.push(id); - } - }); - - // Pseudo-randomly shuffles peers - peers = shuffle(peers); - if (count > 0 && peers.length > count) { - peers = peers.slice(0, count); - } - - return new Set(peers); -} diff --git a/src/lib/waku_relay/index.ts b/src/lib/waku_relay/index.ts index 003c46721e..40cb020537 100644 --- a/src/lib/waku_relay/index.ts +++ b/src/lib/waku_relay/index.ts @@ -1,17 +1,10 @@ -import debug from "debug"; -import { Libp2p } from "libp2p"; -import Gossipsub from "libp2p-gossipsub"; -import { AddrInfo, MessageIdFunction } from "libp2p-gossipsub/src/interfaces"; -import { MessageCache } from "libp2p-gossipsub/src/message-cache"; -import { RPC } from "libp2p-gossipsub/src/message/rpc"; import { - PeerScoreParams, - PeerScoreThresholds, -} from "libp2p-gossipsub/src/score"; -import { createGossipRpc, shuffle } from "libp2p-gossipsub/src/utils"; -import { InMessage } from "libp2p-interfaces/src/pubsub"; -import { SignaturePolicy } from "libp2p-interfaces/src/pubsub/signature-policy"; -import PeerId from "peer-id"; + GossipSub, + GossipsubMessage, + GossipsubOpts, +} from "@chainsafe/libp2p-gossipsub"; +import { SignaturePolicy } from "@chainsafe/libp2p-gossipsub/types"; +import debug from "debug"; import { DefaultPubSubTopic } from "../constants"; import { hexToBytes } from "../utils"; @@ -19,35 +12,9 @@ import { CreateOptions } from "../waku"; import { DecryptionMethod, WakuMessage } from "../waku_message"; import * as constants from "./constants"; -import { getRelayPeers } from "./get_relay_peers"; -import { RelayHeartbeat } from "./relay_heartbeat"; const dbg = debug("waku:relay"); -/** - * See constructor libp2p-gossipsub [API](https://github.com/ChainSafe/js-libp2p-gossipsub#api). - */ -export interface GossipOptions { - emitSelf: boolean; - gossipIncoming: boolean; - fallbackToFloodsub: boolean; - floodPublish: boolean; - doPX: boolean; - msgIdFn: MessageIdFunction; - messageCache: MessageCache; - // This option is always overridden - // globalSignaturePolicy: string; - scoreParams: Partial; - scoreThresholds: Partial; - directPeers: AddrInfo[]; - D: number; - Dlo: number; - Dhi: number; - Dscore: number; - Dout: number; - Dlazy: number; -} - /** * Implements the [Waku v2 Relay protocol]{@link https://rfc.vac.dev/spec/11/}. * Must be passed as a `pubsub` module to a {Libp2p} instance. @@ -55,9 +22,9 @@ export interface GossipOptions { * @implements {require('libp2p-interfaces/src/pubsub')} * @noInheritDoc */ -export class WakuRelay extends Gossipsub { - heartbeat: RelayHeartbeat; +export class WakuRelay extends GossipSub { pubSubTopic: string; + public static multicodec: string = constants.RelayCodecs[0]; public decryptionKeys: Map< Uint8Array, @@ -72,26 +39,19 @@ export class WakuRelay extends Gossipsub { [contentTopic: string]: Set<(message: WakuMessage) => void>; }; - constructor( - libp2p: Libp2p, - options?: Partial - ) { + constructor(options?: Partial) { super( - libp2p, - Object.assign(options ?? {}, { + Object.assign(options, { // Ensure that no signature is included nor expected in the messages. globalSignaturePolicy: SignaturePolicy.StrictNoSign, + fallbackToFloodsub: false, }) ); + this.multicodecs = constants.RelayCodecs; - this.heartbeat = new RelayHeartbeat(this); this.observers = {}; this.decryptionKeys = new Map(); - const multicodecs = constants.RelayCodecs; - - Object.assign(this, { multicodecs }); - this.pubSubTopic = options?.pubSubTopic || DefaultPubSubTopic; options?.decryptionKeys?.forEach((key) => { @@ -119,7 +79,7 @@ export class WakuRelay extends Gossipsub { */ public async send(message: WakuMessage): Promise { const msg = message.encode(); - await super.publish(this.pubSubTopic, msg); + await this.publish(this.pubSubTopic, msg); } /** @@ -195,338 +155,57 @@ export class WakuRelay extends Gossipsub { } } - /** - * Return the relay peers we are connected to, and we would publish a message to - */ - getPeers(): Set { - return getRelayPeers(this, this.pubSubTopic, this._options.D, (id) => { - // Filter peers we would not publish to - return ( - this.score.score(id) >= this._options.scoreThresholds.publishThreshold - ); - }); - } - /** * Subscribe to a pubsub topic and start emitting Waku messages to observers. * * @override */ subscribe(pubSubTopic: string): void { - this.on(pubSubTopic, (event) => { - const decryptionKeys = Array.from(this.decryptionKeys).map( - ([key, { method, contentTopics }]) => { - return { - key, - method, - contentTopics, - }; - } - ); - - dbg(`Message received on ${pubSubTopic}`); - WakuMessage.decode(event.data, decryptionKeys) - .then((wakuMsg) => { - if (!wakuMsg) { - dbg("Failed to decode Waku Message"); - return; - } - - if (this.observers[""]) { - this.observers[""].forEach((callbackFn) => { - callbackFn(wakuMsg); - }); - } - if (wakuMsg.contentTopic) { - if (this.observers[wakuMsg.contentTopic]) { - this.observers[wakuMsg.contentTopic].forEach((callbackFn) => { - callbackFn(wakuMsg); - }); + this.addEventListener( + "gossipsub:message", + (event: CustomEvent) => { + if (event.detail.msg.topic === pubSubTopic) { + const decryptionKeys = Array.from(this.decryptionKeys).map( + ([key, { method, contentTopics }]) => { + return { + key, + method, + contentTopics, + }; } - } - }) - .catch((e) => { - dbg("Failed to decode Waku Message", e); - }); - }); + ); + + dbg(`Message received on ${pubSubTopic}`); + WakuMessage.decode(event.detail.msg.data, decryptionKeys) + .then((wakuMsg) => { + if (!wakuMsg) { + dbg("Failed to decode Waku Message"); + return; + } + + if (this.observers[""]) { + this.observers[""].forEach((callbackFn) => { + callbackFn(wakuMsg); + }); + } + if (wakuMsg.contentTopic) { + if (this.observers[wakuMsg.contentTopic]) { + this.observers[wakuMsg.contentTopic].forEach((callbackFn) => { + callbackFn(wakuMsg); + }); + } + } + }) + .catch((e) => { + dbg("Failed to decode Waku Message", e); + }); + } + } + ); super.subscribe(pubSubTopic); } - /** - * Join pubsub topic. - * This is present to override the behavior of Gossipsub and should not - * be used by API Consumers - * - * @internal - * @param {string} topic - * @returns {void} - * @override - */ - join(topic: string): void { - if (!this.started) { - throw new Error("WakuRelayPubSub has not started"); - } - - const fanoutPeers = this.fanout.get(topic); - if (fanoutPeers) { - // these peers have a score above the publish threshold, which may be negative - // so drop the ones with a negative score - fanoutPeers.forEach((id) => { - if (this.score.score(id) < 0) { - fanoutPeers.delete(id); - } - }); - if (fanoutPeers.size < this._options.D) { - // we need more peers; eager, as this would get fixed in the next heartbeat - getRelayPeers( - this, - topic, - this._options.D - fanoutPeers.size, - (id: string): boolean => { - // filter our current peers, direct peers, and peers with negative scores - return ( - !fanoutPeers.has(id) && - !this.direct.has(id) && - this.score.score(id) >= 0 - ); - } - ).forEach((id) => fanoutPeers.add(id)); - } - this.mesh.set(topic, fanoutPeers); - this.fanout.delete(topic); - this.lastpub.delete(topic); - } else { - const peers = getRelayPeers( - this, - topic, - this._options.D, - (id: string): boolean => { - // filter direct peers and peers with negative score - return !this.direct.has(id) && this.score.score(id) >= 0; - } - ); - this.mesh.set(topic, peers); - } - this.mesh.get(topic)?.forEach((id) => { - this.log("JOIN: Add mesh link to %s in %s", id, topic); - this._sendGraft(id, topic); - }); - } - - /** - * Publish messages. - * This is present to override the behavior of Gossipsub and should not - * be used by API Consumers - * - * @ignore - * @override - * @param {InMessage} msg - * @returns {void} - */ - async _publish(msg: InMessage): Promise { - const msgIdStr = await this.getCanonicalMsgIdStr(msg); - if (msg.receivedFrom !== this.peerId.toString()) { - this.score.deliverMessage(msg, msgIdStr); - this.gossipTracer.deliverMessage(msgIdStr); - } - - // put in seen cache - this.seenCache.put(msgIdStr); - - this.messageCache.put(msg, msgIdStr); - - const toSend = new Set(); - msg.topicIDs.forEach((topic) => { - const peersInTopic = this.topics.get(topic); - if (!peersInTopic) { - return; - } - - // direct peers - this.direct.forEach((id) => { - toSend.add(id); - }); - - let meshPeers = this.mesh.get(topic); - if (!meshPeers || !meshPeers.size) { - // We are not in the mesh for topic, use fanout peers - meshPeers = this.fanout.get(topic); - if (!meshPeers) { - // If we are not in the fanout, then pick peers in topic above the publishThreshold - const peers = getRelayPeers(this, topic, this._options.D, (id) => { - return ( - this.score.score(id) >= - this._options.scoreThresholds.publishThreshold - ); - }); - - if (peers.size > 0) { - meshPeers = peers; - this.fanout.set(topic, peers); - } else { - meshPeers = new Set(); - } - } - // Store the latest publishing time - this.lastpub.set(topic, this._now()); - } - - meshPeers?.forEach((peer) => { - toSend.add(peer); - }); - }); - // Publish messages to peers - const rpc = createGossipRpc([Gossipsub.utils.normalizeOutRpcMessage(msg)]); - dbg(`Relay message to ${toSend.size} peers`); - toSend.forEach((id) => { - if (id === msg.from) { - return; - } - dbg("Relay message to", id); - this._sendRpc(id, rpc); - }); - } - - /** - * Emits gossip to peers in a particular topic. - * - * This is present to override the behavior of Gossipsub and should not - * be used by API Consumers - * - * @ignore - * @override - * @param {string} topic - * @param {Set} exclude peers to exclude - * @returns {void} - */ - _emitGossip(topic: string, exclude: Set): void { - const messageIDs = this.messageCache.getGossipIDs(topic); - if (!messageIDs.length) { - return; - } - - // shuffle to emit in random order - shuffle(messageIDs); - - // if we are emitting more than GossipsubMaxIHaveLength ids, truncate the list - if (messageIDs.length > constants.RelayMaxIHaveLength) { - // we do the truncation (with shuffling) per peer below - this.log( - "too many messages for gossip; will truncate IHAVE list (%d messages)", - messageIDs.length - ); - } - - // Send gossip to GossipFactor peers above threshold with a minimum of D_lazy - // First we collect the peers above gossipThreshold that are not in the exclude set - // and then randomly select from that set - // We also exclude direct peers, as there is no reason to emit gossip to them - const peersToGossip: string[] = []; - const topicPeers = this.topics.get(topic); - if (!topicPeers) { - // no topic peers, no gossip - return; - } - topicPeers.forEach((id) => { - const peerStreams = this.peers.get(id); - if (!peerStreams) { - return; - } - if ( - !exclude.has(id) && - !this.direct.has(id) && - constants.RelayCodecs.includes(peerStreams.protocol) && - this.score.score(id) >= this._options.scoreThresholds.gossipThreshold - ) { - peersToGossip.push(id); - } - }); - - let target = this._options.Dlazy; - const factor = constants.RelayGossipFactor * peersToGossip.length; - if (factor > target) { - target = factor; - } - if (target > peersToGossip.length) { - target = peersToGossip.length; - } else { - shuffle(peersToGossip); - } - // Emit the IHAVE gossip to the selected peers up to the target - peersToGossip.slice(0, target).forEach((id) => { - let peerMessageIDs = messageIDs; - if (messageIDs.length > constants.RelayMaxIHaveLength) { - // shuffle and slice message IDs per peer so that we emit a different set for each peer - // we have enough redundancy in the system that this will significantly increase the message - // coverage when we do truncate - peerMessageIDs = shuffle(peerMessageIDs.slice()).slice( - 0, - constants.RelayMaxIHaveLength - ); - } - this._pushGossip(id, { - topicID: topic, - messageIDs: peerMessageIDs, - }); - }); - } - - /** - * Make a PRUNE control message for a peer in a topic. - * This is present to override the behavior of Gossipsub and should not - * be used by API Consumers - * - * @ignore - * @override - * @param {string} id - * @param {string} topic - * @param {boolean} doPX - * @returns {Promise} - */ - async _makePrune( - id: string, - topic: string, - doPX: boolean - ): Promise { - // backoff is measured in seconds - // RelayPruneBackoff is measured in milliseconds - const backoff = constants.RelayPruneBackoff / 1000; - if (!doPX) { - return { - topicID: topic, - peers: [], - backoff: backoff, - }; - } - - // select peers for Peer eXchange - const peers = getRelayPeers( - this, - topic, - constants.RelayPrunePeers, - (xid: string): boolean => { - return xid !== id && this.score.score(xid) >= 0; - } - ); - const px = await Promise.all( - Array.from(peers).map(async (p) => { - // see if we have a signed record to send back; if we don't, just send - // the peer ID and let the pruned peer find them in the DHT -- we can't trust - // unsigned address records through PX anyways - // Finding signed records in the DHT is not supported at the time of writing in js-libp2p - const peerId = PeerId.createFromB58String(p); - return { - peerID: peerId.toBytes(), - signedPeerRecord: - await this._libp2p.peerStore.addressBook.getRawEnvelope(peerId), - }; - }) - ); - return { - topicID: topic, - peers: px, - backoff: backoff, - }; - } + // TODO: Implement method that uses Relay codec + // public async heartbeat(): Promise { } diff --git a/src/lib/waku_relay/relay_heartbeat.ts b/src/lib/waku_relay/relay_heartbeat.ts deleted file mode 100644 index b3340add06..0000000000 --- a/src/lib/waku_relay/relay_heartbeat.ts +++ /dev/null @@ -1,379 +0,0 @@ -/** - * @hidden - * @module - */ - -import Gossipsub from "libp2p-gossipsub"; -import { Heartbeat } from "libp2p-gossipsub/src/heartbeat"; -import { shuffle } from "libp2p-gossipsub/src/utils"; - -import * as constants from "./constants"; -import { getRelayPeers } from "./get_relay_peers"; - -export class RelayHeartbeat extends Heartbeat { - /** - * @param {Object} gossipsub - * @constructor - */ - constructor(gossipsub: Gossipsub) { - super(gossipsub); - } - - start(): void { - if (this._heartbeatTimer) { - return; - } - - const heartbeat = this._heartbeat.bind(this); - - const timeout = setTimeout(() => { - heartbeat(); - this._heartbeatTimer?.runPeriodically( - heartbeat, - constants.RelayHeartbeatInterval - ); - }, constants.RelayHeartbeatInitialDelay); - - this._heartbeatTimer = { - _intervalId: undefined, - runPeriodically: (fn, period): void => { - // this._heartbeatTimer cannot be null, it is being assigned. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this._heartbeatTimer!._intervalId = setInterval(fn, period); - }, - cancel: (): void => { - clearTimeout(timeout); - clearInterval(this._heartbeatTimer?._intervalId as NodeJS.Timeout); - }, - }; - } - - /** - * Unmounts the gossipsub protocol and shuts down every connection - * @override - * @returns {void} - */ - stop(): void { - if (!this._heartbeatTimer) { - return; - } - - this._heartbeatTimer.cancel(); - this._heartbeatTimer = null; - } - - /** - * Maintains the mesh and fanout maps in gossipsub. - * - * @returns {void} - */ - _heartbeat(): void { - const { D, Dlo, Dhi, Dscore, Dout } = this.gossipsub._options; - this.gossipsub.heartbeatTicks++; - - // cache scores through the heartbeat - const scores = new Map(); - const getScore = (id: string): number => { - let s = scores.get(id); - if (s === undefined) { - s = this.gossipsub.score.score(id); - scores.set(id, s); - } - return s; - }; - - // peer id => topic[] - const toGraft = new Map(); - // peer id => topic[] - const toPrune = new Map(); - // peer id => don't px - const noPX = new Map(); - - // clean up expired backoffs - this.gossipsub._clearBackoff(); - - // clean up peerhave/iasked counters - this.gossipsub.peerhave.clear(); - this.gossipsub.iasked.clear(); - - // apply IWANT request penalties - this.gossipsub._applyIwantPenalties(); - - // ensure direct peers are connected - this.gossipsub._directConnect(); - - // maintain the mesh for topics we have joined - this.gossipsub.mesh.forEach((peers, topic) => { - // prune/graft helper functions (defined per topic) - const prunePeer = (id: string): void => { - this.gossipsub.log( - "HEARTBEAT: Remove mesh link to %s in %s", - id, - topic - ); - // update peer score - this.gossipsub.score.prune(id, topic); - // add prune backoff record - this.gossipsub._addBackoff(id, topic); - // remove peer from mesh - peers.delete(id); - // add to toPrune - const topics = toPrune.get(id); - if (!topics) { - toPrune.set(id, [topic]); - } else { - topics.push(topic); - } - }; - const graftPeer = (id: string): void => { - this.gossipsub.log("HEARTBEAT: Add mesh link to %s in %s", id, topic); - // update peer score - this.gossipsub.score.graft(id, topic); - // add peer to mesh - peers.add(id); - // add to toGraft - const topics = toGraft.get(id); - if (!topics) { - toGraft.set(id, [topic]); - } else { - topics.push(topic); - } - }; - - // drop all peers with negative score, without PX - peers.forEach((id) => { - const score = getScore(id); - if (score < 0) { - this.gossipsub.log( - "HEARTBEAT: Prune peer %s with negative score: score=%d, topic=%s", - id, - score, - topic - ); - prunePeer(id); - noPX.set(id, true); - } - }); - - // do we have enough peers? - if (peers.size < Dlo) { - const backoff = this.gossipsub.backoff.get(topic); - const ineed = D - peers.size; - const peersSet = getRelayPeers( - this.gossipsub, - topic, - ineed, - (id: string) => { - // filter out mesh peers, direct peers, peers we are backing off, peers with negative score - return ( - !peers.has(id) && - !this.gossipsub.direct.has(id) && - (!backoff || !backoff.has(id)) && - getScore(id) >= 0 - ); - } - ); - - peersSet.forEach(graftPeer); - } - - // do we have to many peers? - if (peers.size > Dhi) { - let peersArray = Array.from(peers); - // sort by score - peersArray.sort((a, b) => getScore(b) - getScore(a)); - // We keep the first D_score peers by score and the remaining up to D randomly - // under the constraint that we keep D_out peers in the mesh (if we have that many) - peersArray = peersArray - .slice(0, Dscore) - .concat(shuffle(peersArray.slice(Dscore))); - - // count the outbound peers we are keeping - let outbound = 0; - peersArray.slice(0, D).forEach((p) => { - if (this.gossipsub.outbound.get(p)) { - outbound++; - } - }); - - // if it's less than D_out, bubble up some outbound peers from the random selection - if (outbound < Dout) { - const rotate = (i: number): void => { - // rotate the peersArray to the right and put the ith peer in the front - const p = peersArray[i]; - for (let j = i; j > 0; j--) { - peersArray[j] = peersArray[j - 1]; - } - peersArray[0] = p; - }; - - // first bubble up all outbound peers already in the selection to the front - if (outbound > 0) { - let ihave = outbound; - for (let i = 1; i < D && ihave > 0; i++) { - if (this.gossipsub.outbound.get(peersArray[i])) { - rotate(i); - ihave--; - } - } - } - - // now bubble up enough outbound peers outside the selection to the front - let ineed = D - outbound; - for (let i = D; i < peersArray.length && ineed > 0; i++) { - if (this.gossipsub.outbound.get(peersArray[i])) { - rotate(i); - ineed--; - } - } - } - - // prune the excess peers - peersArray.slice(D).forEach(prunePeer); - } - - // do we have enough outbound peers? - if (peers.size >= Dlo) { - // count the outbound peers we have - let outbound = 0; - peers.forEach((p) => { - if (this.gossipsub.outbound.get(p)) { - outbound++; - } - }); - - // if it's less than D_out, select some peers with outbound connections and graft them - if (outbound < Dout) { - const ineed = Dout - outbound; - const backoff = this.gossipsub.backoff.get(topic); - getRelayPeers(this.gossipsub, topic, ineed, (id: string): boolean => { - // filter our current mesh peers, direct peers, peers we are backing off, peers with negative score - return ( - !peers.has(id) && - !this.gossipsub.direct.has(id) && - (!backoff || !backoff.has(id)) && - getScore(id) >= 0 - ); - }).forEach(graftPeer); - } - } - - // should we try to improve the mesh with opportunistic grafting? - if ( - this.gossipsub.heartbeatTicks % - constants.RelayOpportunisticGraftTicks === - 0 && - peers.size > 1 - ) { - // Opportunistic grafting works as follows: we check the median score of peers in the - // mesh; if this score is below the opportunisticGraftThreshold, we select a few peers at - // random with score over the median. - // The intention is to (slowly) improve an under performing mesh by introducing good - // scoring peers that may have been gossiping at us. This allows us to get out of sticky - // situations where we are stuck with poor peers and also recover from churn of good peers. - - // now compute the median peer score in the mesh - const peersList = Array.from(peers).sort( - (a, b) => getScore(a) - getScore(b) - ); - const medianIndex = Math.floor(peers.size / 2); - const medianScore = getScore(peersList[medianIndex]); - - // if the median score is below the threshold, select a better peer (if any) and GRAFT - if ( - medianScore < - this.gossipsub._options.scoreThresholds.opportunisticGraftThreshold - ) { - const backoff = this.gossipsub.backoff.get(topic); - const peersToGraft = getRelayPeers( - this.gossipsub, - topic, - constants.RelayOpportunisticGraftPeers, - (id: string): boolean => { - // filter out current mesh peers, direct peers, peers we are backing off, peers below or at threshold - return ( - peers.has(id) && - !this.gossipsub.direct.has(id) && - (!backoff || !backoff.has(id)) && - getScore(id) > medianScore - ); - } - ); - peersToGraft.forEach((id: string) => { - this.gossipsub.log( - "HEARTBEAT: Opportunistically graft peer %s on topic %s", - id, - topic - ); - graftPeer(id); - }); - } - } - - // 2nd arg are mesh peers excluded from gossip. We have already pushed - // messages to them, so its redundant to gossip IHAVEs. - this.gossipsub._emitGossip(topic, peers); - }); - - // expire fanout for topics we haven't published to in a while - const now = this.gossipsub._now(); - this.gossipsub.lastpub.forEach((lastpub, topic) => { - if (lastpub + constants.RelayFanoutTTL < now) { - this.gossipsub.fanout.delete(topic); - this.gossipsub.lastpub.delete(topic); - } - }); - - // maintain our fanout for topics we are publishing but we have not joined - this.gossipsub.fanout.forEach((fanoutPeers, topic) => { - // checks whether our peers are still in the topic and have a score above the publish threshold - const topicPeers = this.gossipsub.topics.get(topic); - fanoutPeers.forEach((id) => { - if ( - !topicPeers?.has(id) || - getScore(id) < - this.gossipsub._options.scoreThresholds.publishThreshold - ) { - fanoutPeers.delete(id); - } - }); - - // do we need more peers? - if (fanoutPeers.size < D) { - const ineed = D - fanoutPeers.size; - const peersSet = getRelayPeers( - this.gossipsub, - topic, - ineed, - (id: string): boolean => { - // filter out existing fanout peers, direct peers, and peers with score above the publish threshold - return ( - !fanoutPeers.has(id) && - !this.gossipsub.direct.has(id) && - getScore(id) >= - this.gossipsub._options.scoreThresholds.publishThreshold - ); - } - ); - peersSet.forEach((id: string) => { - fanoutPeers.add(id); - }); - } - - // 2nd arg are fanout peers excluded from gossip. - // We have already pushed messages to them, so its redundant to gossip IHAVEs - this.gossipsub._emitGossip(topic, fanoutPeers); - }); - - // send coalesced GRAFT/PRUNE messages (will piggyback gossip) - this.gossipsub._sendGraftPrune(toGraft, toPrune, noPX); - - // flush pending gossip that wasn't piggybacked above - this.gossipsub._flush(); - - // advance the message history window - this.gossipsub.messageCache.shift(); - - this.gossipsub.emit("gossipsub:heartbeat"); - } -}