diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml new file mode 100644 index 0000000000..13e3f0c970 --- /dev/null +++ b/.github/workflows/examples.yml @@ -0,0 +1,53 @@ +name: Examples +on: + push: + branches: + - master + pull_request: + branches: + - '**' + +jobs: + + build: + name: Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + + test-examples: + name: Test example ${{ matrix.example.name }} + runs-on: ubuntu-latest + needs: build + continue-on-error: true + strategy: + matrix: + example: + - name: js-libp2p-example-chat + repo: https://github.com/libp2p/js-libp2p-example-chat.git + deps: + - '@libp2p/peer-id-factory@$PWD/packages/peer-id-factory' + - '@libp2p/tcp@$PWD/packages/transport-tcp' + - '@libp2p/websockets@$PWD/packages/transport-websockets' + - 'libp2p@$PWD/packages/libp2p' + - name: js-libp2p-example-circuit-relay + repo: https://github.com/libp2p/js-libp2p-example-circuit-relay.git + deps: + - '@libp2p/websockets@$PWD/packages/transport-websockets' + - 'libp2p@$PWD/packages/libp2p' + - name: js-libp2p-example-connection-encryption + repo: https://github.com/libp2p/js-libp2p-example-connection-encryption.git + deps: + - '@libp2p/tcp@$PWD/packages/transport-tcp' + - 'libp2p@$PWD/packages/libp2p' + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npx xvfb-maybe aegir test-dependant ${{ matrix.example.repo }} --deps ${{ join(matrix.example.deps, ',') }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a354658173..cb1ec0cf07 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,4 +1,4 @@ -name: ci +name: CI on: push: branches: @@ -17,6 +17,10 @@ jobs: with: node-version: lts/* - uses: ipfs/aegir/actions/cache-node-modules@master + with: + directories: | + ./interop/dist + ./interop/node_modules check: needs: build @@ -48,8 +52,8 @@ jobs: - run: npm run --if-present test:node - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: - directory: ./.nyc_output flags: node + files: .coverage/*,packages/*/.coverage/* test-chrome: needs: build @@ -63,8 +67,8 @@ jobs: - run: npm run --if-present test:chrome - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: - directory: ./.nyc_output flags: chrome + files: .coverage/*,packages/*/.coverage/* test-chrome-webworker: needs: build @@ -78,8 +82,8 @@ jobs: - run: npm run --if-present test:chrome-webworker - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: - directory: ./.nyc_output flags: chrome-webworker + files: .coverage/*,packages/*/.coverage/* test-firefox: needs: build @@ -93,8 +97,8 @@ jobs: - run: npm run --if-present test:firefox - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: - directory: ./.nyc_output flags: firefox + files: .coverage/*,packages/*/.coverage/* test-firefox-webworker: needs: build @@ -108,8 +112,8 @@ jobs: - run: npm run --if-present test:firefox-webworker - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: - directory: ./.nyc_output flags: firefox-webworker + files: .coverage/*,packages/*/.coverage/* test-webkit: needs: build @@ -124,8 +128,8 @@ jobs: - run: npm run --if-present test:webkit - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: - directory: ./.nyc_output flags: webkit + files: .coverage/*,packages/*/.coverage/* test-electron-main: needs: build @@ -139,8 +143,8 @@ jobs: - run: npx xvfb-maybe npm run --if-present test:electron-main - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: - directory: ./.nyc_output flags: electron-main + files: .coverage/*,packages/*/.coverage/* test-electron-renderer: needs: build @@ -154,8 +158,8 @@ jobs: - run: npx xvfb-maybe npm run --if-present test:electron-renderer - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: - directory: ./.nyc_output flags: electron-renderer + files: .coverage/*,packages/*/.coverage/* test-interop: needs: build @@ -168,17 +172,6 @@ jobs: - uses: ipfs/aegir/actions/cache-node-modules@master - run: npm run test:interop -- --bail - test-examples: - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: lts/* - - uses: ipfs/aegir/actions/cache-node-modules@master - - run: npm run --if-present test:example - transport-interop: needs: build runs-on: ${{ fromJSON(github.repository == 'libp2p/js-libp2p' && '["self-hosted", "linux", "x64", "4xlarge"]' || '"ubuntu-latest"') }} @@ -188,6 +181,10 @@ jobs: with: node-version: lts/* - uses: ipfs/aegir/actions/cache-node-modules@master + with: + directories: | + ./interop/dist + ./interop/node_modules - name: Build images run: (cd interop && make -j 4) - name: Save package-lock.json as artifact @@ -218,7 +215,6 @@ jobs: test-electron-main, test-electron-renderer, test-interop, - test-examples, transport-interop ] if: github.event_name == 'push' && github.ref == 'refs/heads/master' diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 71b4d4c4f6..432a0759b8 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1 @@ -{"interop":"1.0.6","packages/crypto":"2.0.5","packages/interface":"0.1.3","packages/interface-compliance-tests":"4.1.1","packages/interface-internal":"0.1.6","packages/kad-dht":"10.0.9","packages/keychain":"3.0.5","packages/libp2p":"0.46.14","packages/logger":"3.0.3","packages/metrics-prometheus":"2.0.8","packages/multistream-select":"4.0.3","packages/peer-collections":"4.0.5","packages/peer-discovery-bootstrap":"9.0.8","packages/peer-discovery-mdns":"9.0.10","packages/peer-id":"3.0.3","packages/peer-id-factory":"3.0.5","packages/peer-record":"6.0.6","packages/peer-store":"9.0.6","packages/protocol-perf":"1.1.11","packages/pubsub":"8.0.7","packages/pubsub-floodsub":"8.0.9","packages/stream-multiplexer-mplex":"9.0.8","packages/transport-tcp":"8.0.9","packages/transport-webrtc":"3.2.3","packages/transport-websockets":"7.0.9","packages/transport-webtransport":"3.1.3","packages/utils":"4.0.4"} \ No newline at end of file +{"interop":"1.0.8","packages/crypto":"2.0.6","packages/interface":"0.1.4","packages/interface-compliance-tests":"4.1.2","packages/interface-internal":"0.1.7","packages/kad-dht":"10.0.11","packages/keychain":"3.0.6","packages/libp2p":"0.46.16","packages/logger":"3.0.4","packages/metrics-prometheus":"2.0.9","packages/multistream-select":"4.0.4","packages/peer-collections":"4.0.6","packages/peer-discovery-bootstrap":"9.0.9","packages/peer-discovery-mdns":"9.0.11","packages/peer-id":"3.0.4","packages/peer-id-factory":"3.0.6","packages/peer-record":"6.0.7","packages/peer-store":"9.0.7","packages/protocol-perf":"1.1.13","packages/pubsub":"8.0.8","packages/pubsub-floodsub":"8.0.10","packages/stream-multiplexer-mplex":"9.0.9","packages/transport-tcp":"8.0.10","packages/transport-webrtc":"3.2.5","packages/transport-websockets":"7.0.10","packages/transport-webtransport":"3.1.5","packages/utils":"4.0.5"} \ No newline at end of file diff --git a/README.md b/README.md index 06b53a0e6b..b09ffc2614 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ This project has been used in production for years in Ethereum, IPFS, and more. The documentation in the master branch may contain changes from a pre-release. If you are looking for the documentation of the latest release, you can view the latest release on [**npm**](https://www.npmjs.com/package/libp2p), or select the tag in github that matches the version you are looking for. -**Want to get started?** Check our [GETTING\_STARTED.md](./doc/GETTING_STARTED.md) guide and [examples folder](/examples). +**Want to get started?** Check our [GETTING\_STARTED.md](./doc/GETTING_STARTED.md) guide and [examples](https://github.com/libp2p/js-libp2p-examples). **Want to update libp2p in your project?** Check our [migrations folder](./doc/migrations). @@ -114,22 +114,11 @@ If you are starting your journey with `js-libp2p`, read the [GETTING\_STARTED.md ### Tutorials and Examples -You can find multiple examples on the [examples folder](./examples) that will guide you through using libp2p for several scenarios. +You can find multiple examples on the [examples repo](https://github.com/libp2p/js-libp2p-examples) that will guide you through using libp2p for several scenarios. ## Structure - [`/doc`](./doc) Docs for libp2p -- [`/examples/auto-relay`](./examples/auto-relay) Shows how to configure relayed connections -- [`/examples/chat`](./examples/chat) An example chat app using libp2p -- [`/examples/connection-encryption`](./examples/connection-encryption) An example of how to configure connection encrypters -- [`/examples/delegated-routing`](./examples/delegated-routing) How to configure libp2p delegated routers -- [`/examples/discovery-mechanisms`](./examples/discovery-mechanisms) How to configure peer discovery mechanisms -- [`/examples/echo`](./examples/echo) An example echo app -- [`/examples/peer-and-content-routing`](./examples/peer-and-content-routing) How to use peer and content routing -- [`/examples/pnet`](./examples/pnet) How to configure a libp2p private network -- [`/examples/protocol-and-stream-muxing`](./examples/protocol-and-stream-muxing) How to use multiplex protocols streams -- [`/examples/pubsub`](./examples/pubsub) An example using libp2p pubsub -- [`/examples/transports`](./examples/transports) An example using different types of libp2p transport - [`/interop`](./interop) Multidimension Interop Test - [`/packages/crypto`](./packages/crypto) Crypto primitives for libp2p - [`/packages/interface`](./packages/interface) The interface implemented by a libp2p node diff --git a/doc/CONFIGURATION.md b/doc/CONFIGURATION.md index dcba663f72..2173ac59be 100644 --- a/doc/CONFIGURATION.md +++ b/doc/CONFIGURATION.md @@ -1017,7 +1017,7 @@ As libp2p is designed to be a modular networking library, its usage will vary ba If you have developed a project using `js-libp2p`, please consider submitting your configuration to this list so that it can be found easily by other users. -The [examples](../examples) are also a good source of help for finding a configuration that suits your needs. +The [examples repo](https://github.com/libp2p/js-libp2p-examples) is also a good source of help for finding a configuration that suits your needs. ## Limits diff --git a/doc/GETTING_STARTED.md b/doc/GETTING_STARTED.md index 49db548f8f..89fb79d784 100644 --- a/doc/GETTING_STARTED.md +++ b/doc/GETTING_STARTED.md @@ -276,7 +276,7 @@ localStorage.setItem('debug', 'libp2p:websockets,libp2p:webtransport,libp2p:kad- ## What is next -There are a lot of other concepts within `libp2p`, that are not covered in this guide. For additional configuration options we recommend checking out the [Configuration Readme](./CONFIGURATION.md) and the [examples folder](../examples). If you have any problems getting started, or if anything isn't clear, please let us know by submitting an issue! +There are a lot of other concepts within `libp2p`, that are not covered in this guide. For additional configuration options we recommend checking out the [Configuration Readme](./CONFIGURATION.md) and the [examples repo](https://github.com/libp2p/js-libp2p-examples). If you have any problems getting started, or if anything isn't clear, please let us know by submitting an issue! [transport]: https://github.com/libp2p/js-interfaces/tree/master/src/transport diff --git a/doc/package.json b/doc/package.json index a1b9c91f2d..c73eb0317b 100644 --- a/doc/package.json +++ b/doc/package.json @@ -30,7 +30,7 @@ "@libp2p/tcp": "^8.0.0", "aegir": "^41.0.2", "libp2p": "^0.46.0", - "prom-client": "^14.2.0" + "prom-client": "^15.0.0" }, "private": true } diff --git a/examples/README.md b/examples/README.md deleted file mode 100644 index 62762e59b4..0000000000 --- a/examples/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# `js-libp2p` Examples and Tutorials - -In this folder, you can find a variety of examples to help you get started in using js-libp2p, in Node.js and in the Browser. Every example has a specific purpose and some incorporate a full tutorial that you can follow through, helping you expand your knowledge about libp2p and p2p networks in general. - -Let us know if you find any issues, or if you want to contribute and add a new tutorial, feel free to submit a PR, thank you! - -## Understanding how libp2p works - -- [Transports](./transports) -- [Protocol and Stream Muxing](./protocol-and-stream-muxing) -- [Connection Encryption](./connection-encryption) -- [Discovery Mechanisms](./discovery-mechanisms) -- [Peer and Content Routing](./peer-and-content-routing) -- [PubSub](./pubsub) -- [NAT Traversal](./nat-traversal) -- Circuit Relay (future) -- Naming (future) - -## Other examples - -- Running libp2p in the Electron (future) -- [The standard echo net example with libp2p](./echo) -- [A simple chat app with libp2p](./chat) - -## libp2p in the Browser -There are a number of ways libp2p can be used in the browser. Here are some examples: - -- [webRTC](./libp2p-in-the-browser/webrtc/README.md) -- [websockets](./libp2p-in-the-browser/websockets/README.md) -- [webtransport](./libp2p-in-the-browser/webtransport/README.md) - -There is also an tutorial of how all of these transports can be [universally connected](https://github.com/libp2p/universal-connectivity/tree/main) \ No newline at end of file diff --git a/examples/auto-relay/LICENSE b/examples/auto-relay/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/auto-relay/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/auto-relay/LICENSE-APACHE b/examples/auto-relay/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/auto-relay/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/auto-relay/LICENSE-MIT b/examples/auto-relay/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/auto-relay/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/auto-relay/README.md b/examples/auto-relay/README.md deleted file mode 100644 index a4479a22dc..0000000000 --- a/examples/auto-relay/README.md +++ /dev/null @@ -1,200 +0,0 @@ -# @libp2p/example-auto-relay - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> Shows how to configure relayed connections - -## Table of contents - -- [0. Setup the example](#0-setup-the-example) -- [1. Set up a relay node](#1-set-up-a-relay-node) -- [2. Set up a listener node with Auto Relay Enabled](#2-set-up-a-listener-node-with-auto-relay-enabled) -- [3. Set up a dialer node for testing connectivity](#3-set-up-a-dialer-node-for-testing-connectivity) -- [4. What is next?](#4-what-is-next) -- [License](#license) -- [Contribution](#contribution) - -## 0. Setup the example - -Before moving into the examples, you should run `npm install` and `npm run build` on the top level `js-libp2p` folder, in order to install all the dependencies needed for this example. Once the install finishes, you should move into the example folder with `cd examples/auto-relay`. - -This example comes with 3 main files. A `relay.js` file to be used in the first step, a `listener.js` file to be used in the second step and a `dialer.js` file to be used on the third step. All of these scripts will run their own libp2p node, which will interact with the previous ones. All nodes must be running in order for you to proceed. - -## 1. Set up a relay node - -In the first step of this example, we need to configure and run a relay node in order for our target node to bind to for accepting inbound connections. - -The relay node will need to have its relay subsystem enabled, as well as its HOP capability. It can be configured as follows: - -```js -import { createLibp2p } from 'libp2p' -import { webSockets } from '@libp2p/websockets' -import { noise } from '@chainsafe/libp2p-noise' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux', - -const node = await createLibp2p({ - transports: [webSockets()], - connectionEncryption: [noise()], - streamMuxers: [yamux(), mplex()], - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0/ws'] - // TODO check "What is next?" section - // announce: ['/dns4/auto-relay.libp2p.io/tcp/443/wss/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3'] - }, - relay: { - enabled: true, - hop: { - enabled: true - }, - advertise: { - enabled: true, - } - } -}) - -console.log(`Node started with id ${node.peerId.toString()}`) -console.log('Listening on:') -node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) -``` - -The Relay HOP advertise functionality is **NOT** required to be enabled. However, if you are interested in advertising on the network that this node is available to be used as a HOP Relay you can enable it. A content router module or Rendezvous needs to be configured to leverage this option. - -You should now run the following to start the relay node: - -```sh -node relay.js -``` - -This should print out something similar to the following: - -```sh -Node started with id QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3 -Listening on: -/ip4/127.0.0.1/tcp/61592/ws/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3 -/ip4/192.168.1.120/tcp/61592/ws/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3 -``` - -## 2. Set up a listener node with Auto Relay Enabled - -One of the typical use cases for Auto Relay is nodes behind a NAT or browser nodes due to their inability to expose a public address. For running a libp2p node that automatically binds itself to connected HOP relays, you can see the following: - -```js -import { createLibp2p } from 'libp2p' -import { webSockets } from '@libp2p/websockets' -import { noise } from '@chainsafe/libp2p-noise' -import { mplex } from '@libp2p/mplex' - -const relayAddr = process.argv[2] -if (!relayAddr) { - throw new Error('the relay address needs to be specified as a parameter') -} - -const node = await createLibp2p({ - transports: [webSockets()], - connectionEncryption: [noise()], - streamMuxers: [yamux(), mplex()], - relay: { - enabled: true, - autoRelay: { - enabled: true, - maxListeners: 2 - } - } -}) - -console.log(`Node started with id ${node.peerId.toString()}`) - -const conn = await node.dial(relayAddr) - -console.log(`Connected to the HOP relay ${conn.remotePeer.toString()}`) - -// Wait for connection and relay to be bind for the example purpose -node.addEventListener('self:peer:update', (evt) => { - // Updated self multiaddrs? - console.log(`Advertising with a relay address of ${node.getMultiaddrs()[0].toString()}`) -}) -``` - -As you can see in the code, we need to provide the relay address, `relayAddr`, as a process argument. This node will dial the provided relay address and automatically bind to it. - -You should now run the following to start the node running Auto Relay: - -```sh -node listener.js /ip4/192.168.1.120/tcp/61592/ws/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3 -``` - -This should print out something similar to the following: - -```sh -Node started with id QmerrWofKF358JE6gv3z74cEAyL7z1KqhuUoVfGEynqjRm -Connected to the HOP relay QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3 -Advertising with a relay address of /ip4/192.168.1.120/tcp/61592/ws/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3/p2p-circuit/p2p/QmerrWofKF358JE6gv3z74cEAyL7z1KqhuUoVfGEynqjRm -``` - -Per the address, it is possible to verify that the auto relay node is listening on the circuit relay node address. - -Instead of dialing this relay manually, you could set up this node with the Bootstrap module and provide it in the bootstrap list. Moreover, you can use other `peer-discovery` modules to discover peers in the network and the node will automatically bind to the relays that support HOP until reaching the maximum number of listeners. - -## 3. Set up a dialer node for testing connectivity - -Now that you have a relay node and a node bound to that relay, you can test connecting to the auto relay node via the relay. - -```js -import { createLibp2p } from 'libp2p' -import { webSockets } from '@libp2p/websockets' -import { noise } from '@chainsafe/libp2p-noise' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux', - -const autoRelayNodeAddr = process.argv[2] -if (!autoRelayNodeAddr) { - throw new Error('the auto relay node address needs to be specified') -} - -const node = await createLibp2p({ - transports: [webSockets()], - connectionEncryption: [noise()], - streamMuxers: [yamux(), mplex()] -}) - -console.log(`Node started with id ${node.peerId.toString()}`) - -const conn = await node.dial(autoRelayNodeAddr) -console.log(`Connected to the auto relay node via ${conn.remoteAddr.toString()}`) -``` - -You should now run the following to start the relay node using the listen address from step 2: - -```sh -node dialer.js /ip4/192.168.1.120/tcp/61592/ws/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3 -``` - -Once you start your test node, it should print out something similar to the following: - -```sh -Node started: Qme7iEzDxFoFhhkrsrkHkMnM11aPYjysaehP4NZeUfVMKG -Connected to the auto relay node via /ip4/192.168.1.120/tcp/61592/ws/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3/p2p-circuit/p2p/QmerrWofKF358JE6gv3z74cEAyL7z1KqhuUoVfGEynqjRm -``` - -As you can see from the output, the remote address of the established connection uses the relayed connection. - -## 4. What is next? - -Before moving into production, there are a few things that you should take into account. - -A relay node should not advertise its private address in a real world scenario, as the node would not be reachable by others. You should provide an array of public addresses in the libp2p `addresses.announce` option. If you are using websockets, bear in mind that due to browser’s security policies you cannot establish unencrypted connection from secure context. The simplest solution is to setup SSL with nginx and proxy to the node and setup a domain name for the certificate. - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/auto-relay/dialer.js b/examples/auto-relay/dialer.js deleted file mode 100644 index b797da4283..0000000000 --- a/examples/auto-relay/dialer.js +++ /dev/null @@ -1,41 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { webSockets } from '@libp2p/websockets' -import { multiaddr } from '@multiformats/multiaddr' -import { createLibp2p } from 'libp2p' -import { circuitRelayTransport } from 'libp2p/circuit-relay' -import { identifyService } from 'libp2p/identify' - -async function main () { - const autoRelayNodeAddr = process.argv[2] - if (!autoRelayNodeAddr) { - throw new Error('the auto relay node address needs to be specified') - } - - const node = await createLibp2p({ - transports: [ - webSockets(), - circuitRelayTransport() - ], - connectionEncryption: [ - noise() - ], - streamMuxers: [ - yamux(), - mplex() - ], - services: { - identify: identifyService() - } - }) - - console.log(`Node started with id ${node.peerId.toString()}`) - - const conn = await node.dial(multiaddr(autoRelayNodeAddr)) - console.log(`Connected to the auto relay node via ${conn.remoteAddr.toString()}`) -} - -main() diff --git a/examples/auto-relay/listener.js b/examples/auto-relay/listener.js deleted file mode 100644 index 5ee0967372..0000000000 --- a/examples/auto-relay/listener.js +++ /dev/null @@ -1,50 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { webSockets } from '@libp2p/websockets' -import { multiaddr } from '@multiformats/multiaddr' -import { createLibp2p } from 'libp2p' -import { circuitRelayTransport } from 'libp2p/circuit-relay' -import { identifyService } from 'libp2p/identify' - -async function main () { - const relayAddr = process.argv[2] - if (!relayAddr) { - throw new Error('the relay address needs to be specified as a parameter') - } - - const node = await createLibp2p({ - transports: [ - webSockets(), - circuitRelayTransport({ - discoverRelays: 2 - }) - ], - connectionEncryption: [ - noise() - ], - streamMuxers: [ - yamux(), - mplex() - ], - services: { - identify: identifyService() - } - }) - - console.log(`Node started with id ${node.peerId.toString()}`) - - const conn = await node.dial(multiaddr(relayAddr)) - - console.log(`Connected to the HOP relay ${conn.remotePeer.toString()}`) - - // Wait for connection and relay to be bind for the example purpose - node.addEventListener('self:peer:update', (evt) => { - // Updated self multiaddrs? - console.log(`Advertising with a relay address of ${node.getMultiaddrs()[0].toString()}`) - }) -} - -main() diff --git a/examples/auto-relay/package.json b/examples/auto-relay/package.json deleted file mode 100644 index fbef4c84c4..0000000000 --- a/examples/auto-relay/package.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "@libp2p/example-auto-relay", - "version": "0.0.0", - "description": "Shows how to configure relayed connections", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/auto-relay#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/websockets": "^7.0.0", - "@multiformats/multiaddr": "^12.1.5", - "libp2p": "^0.46.0" - }, - "devDependencies": { - "aegir": "^41.0.2", - "execa": "^8.0.1", - "p-defer": "^4.0.0", - "uint8arrays": "^4.0.4" - }, - "private": true -} diff --git a/examples/auto-relay/relay.js b/examples/auto-relay/relay.js deleted file mode 100644 index 17c0053e49..0000000000 --- a/examples/auto-relay/relay.js +++ /dev/null @@ -1,38 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { webSockets } from '@libp2p/websockets' -import { createLibp2p } from 'libp2p' -import { circuitRelayServer } from 'libp2p/circuit-relay' -import { identifyService } from 'libp2p/identify' - -async function main () { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0/ws'] - // TODO check "What is next?" section - // announce: ['/dns4/auto-relay.libp2p.io/tcp/443/wss/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3'] - }, - transports: [ - webSockets() - ], - connectionEncryption: [ - noise() - ], - streamMuxers: [ - yamux(), mplex() - ], - services: { - identify: identifyService(), - relay: circuitRelayServer() - } - }) - - console.log(`Node started with id ${node.peerId.toString()}`) - console.log('Listening on:') - node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) -} - -main() diff --git a/examples/auto-relay/test.js b/examples/auto-relay/test.js deleted file mode 100644 index e0372f6f69..0000000000 --- a/examples/auto-relay/test.js +++ /dev/null @@ -1,91 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { execa } from 'execa' -import pDefer from 'p-defer' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -function startProcess (name, args = []) { - return execa('node', [path.join(__dirname, name), ...args], { - cwd: path.resolve(__dirname), - all: true - }) -} - -let output1 = '' -let output2 = '' -let output3 = '' -let relayAddr -let autoRelayAddr - -const proc1Ready = pDefer() -const proc2Ready = pDefer() - -// Step 1 process -process.stdout.write('relay.js\n') - -const proc1 = startProcess('relay.js') -proc1.all.on('data', async (data) => { - process.stdout.write(data) - - output1 += uint8ArrayToString(data) - - if (output1.includes('Listening on:') && output1.includes('/p2p/')) { - relayAddr = output1.trim().split('Listening on:\n')[1].split('\n')[0] - proc1Ready.resolve() - } -}) - -await proc1Ready.promise -process.stdout.write('==================================================================\n') - -// Step 2 process -process.stdout.write('listener.js\n') - -const proc2 = startProcess('listener.js', [relayAddr]) -proc2.all.on('data', async (data) => { - process.stdout.write(data) - - output2 += uint8ArrayToString(data) - - if (output2.includes('Advertising with a relay address of') && output2.includes('/p2p/')) { - autoRelayAddr = output2.trim().split('Advertising with a relay address of ')[1].trim() - proc2Ready.resolve() - } -}) - -await proc2Ready.promise -process.stdout.write('==================================================================\n') - -// Step 3 process -process.stdout.write('dialer.js\n') - -const proc3 = startProcess('dialer.js', [autoRelayAddr]) -proc3.all.on('data', async (data) => { - process.stdout.write(data) - - output3 += uint8ArrayToString(data) - - if (output3.includes('Connected to the auto relay node via')) { - const remoteAddr = output3.trim().split('Connected to the auto relay node via ')[1] - - if (remoteAddr === autoRelayAddr) { - proc3.kill() - proc2.kill() - proc1.kill() - } else { - throw new Error('dialer did not dial through the relay') - } - } -}) - -await Promise.all([ - proc1, - proc2, - proc3 -]).catch((err) => { - if (err.signal !== 'SIGTERM') { - throw err - } -}) diff --git a/examples/chat/LICENSE b/examples/chat/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/chat/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/chat/LICENSE-APACHE b/examples/chat/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/chat/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/chat/LICENSE-MIT b/examples/chat/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/chat/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/chat/README.md b/examples/chat/README.md deleted file mode 100644 index 0115da0620..0000000000 --- a/examples/chat/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# @libp2p/example-chat - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> An example chat app using libp2p - -## Table of contents - -- [Setup](#setup) -- [Running](#running) -- [License](#license) -- [Contribution](#contribution) - -## Setup - -1. Install the modules in the libp2p root directory, `npm install` and `npm run build`. -2. Open 2 terminal windows in the `./examples/chat/src` directory. - -## Running - -1. Run the listener in window 1, `node listener.js` -2. Run the dialer in window 2, `node dialer.js` -3. Type a message in either window and hit *enter* -4. Tell yourself secrets to your hearts content! - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/chat/package.json b/examples/chat/package.json deleted file mode 100644 index 4c9ca59231..0000000000 --- a/examples/chat/package.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "@libp2p/example-chat", - "version": "0.0.0", - "description": "An example chat app using libp2p", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/chat#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/peer-id-factory": "^3.0.0", - "@libp2p/tcp": "^8.0.0", - "@libp2p/websockets": "^7.0.0", - "@multiformats/multiaddr": "^12.1.5", - "@nodeutils/defaults-deep": "^1.1.0", - "it-length-prefixed": "^9.0.1", - "it-map": "^3.0.3", - "it-pipe": "^3.0.1", - "libp2p": "^0.46.0", - "uint8arrays": "^4.0.6" - }, - "devDependencies": { - "aegir": "^41.0.2", - "execa": "^8.0.1", - "p-defer": "^4.0.0" - }, - "private": true -} diff --git a/examples/chat/src/dialer.js b/examples/chat/src/dialer.js deleted file mode 100644 index 956492dbe4..0000000000 --- a/examples/chat/src/dialer.js +++ /dev/null @@ -1,43 +0,0 @@ -/* eslint-disable no-console */ - -import { createFromJSON } from '@libp2p/peer-id-factory' -import { multiaddr } from '@multiformats/multiaddr' -import { createLibp2p } from './libp2p.js' -import peerIdDialerJson from './peer-id-dialer.js' -import peerIdListenerJson from './peer-id-listener.js' -import { stdinToStream, streamToConsole } from './stream.js' - -async function run () { - const [idDialer, idListener] = await Promise.all([ - createFromJSON(peerIdDialerJson), - createFromJSON(peerIdListenerJson) - ]) - - // Create a new libp2p node on localhost with a randomly chosen port - const nodeDialer = await createLibp2p({ - peerId: idDialer, - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - } - }) - - // Output this node's address - console.log('Dialer ready, listening on:') - nodeDialer.getMultiaddrs().forEach((ma) => { - console.log(ma.toString()) - }) - - // Dial to the remote peer (the "listener") - const listenerMa = multiaddr(`/ip4/127.0.0.1/tcp/10333/p2p/${idListener.toString()}`) - const stream = await nodeDialer.dialProtocol(listenerMa, '/chat/1.0.0') - - console.log('Dialer dialed to listener on protocol: /chat/1.0.0') - console.log('Type a message and see what happens') - - // Send stdin to the stream - stdinToStream(stream) - // Read the stream and output to console - streamToConsole(stream) -} - -run() diff --git a/examples/chat/src/libp2p.js b/examples/chat/src/libp2p.js deleted file mode 100644 index 5a244b59b5..0000000000 --- a/examples/chat/src/libp2p.js +++ /dev/null @@ -1,24 +0,0 @@ -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { webSockets } from '@libp2p/websockets' -import defaultsDeep from '@nodeutils/defaults-deep' -import { createLibp2p as create } from 'libp2p' - -export async function createLibp2p (_options) { - const defaults = { - transports: [ - tcp(), - webSockets() - ], - streamMuxers: [ - yamux(), mplex() - ], - connectionEncryption: [ - noise() - ] - } - - return create(defaultsDeep(_options, defaults)) -} diff --git a/examples/chat/src/listener.js b/examples/chat/src/listener.js deleted file mode 100644 index 7397695424..0000000000 --- a/examples/chat/src/listener.js +++ /dev/null @@ -1,39 +0,0 @@ -/* eslint-disable no-console */ - -import { createFromJSON } from '@libp2p/peer-id-factory' -import { createLibp2p } from './libp2p.js' -import peerIdListenerJson from './peer-id-listener.js' -import { stdinToStream, streamToConsole } from './stream.js' - -async function run () { - // Create a new libp2p node with the given multi-address - const idListener = await createFromJSON(peerIdListenerJson) - const nodeListener = await createLibp2p({ - peerId: idListener, - addresses: { - listen: ['/ip4/0.0.0.0/tcp/10333'] - } - }) - - // Log a message when a remote peer connects to us - nodeListener.addEventListener('peer:connect', (evt) => { - const remotePeer = evt.detail - console.log('connected to: ', remotePeer.toString()) - }) - - // Handle messages for the protocol - await nodeListener.handle('/chat/1.0.0', async ({ stream }) => { - // Send stdin to the stream - stdinToStream(stream) - // Read the stream and output to console - streamToConsole(stream) - }) - - // Output listen addresses to the console - console.log('Listener ready, listening on:') - nodeListener.getMultiaddrs().forEach((ma) => { - console.log(ma.toString()) - }) -} - -run() diff --git a/examples/chat/src/peer-id-dialer.js b/examples/chat/src/peer-id-dialer.js deleted file mode 100644 index 79d31007f2..0000000000 --- a/examples/chat/src/peer-id-dialer.js +++ /dev/null @@ -1,5 +0,0 @@ -export default { - id: 'Qma3GsJmB47xYuyahPZPSadh1avvxfyYQwk8R3UnFrQ6aP', - privKey: 'CAASpwkwggSjAgEAAoIBAQCaNSDOjPz6T8HZsf7LDpxiQRiN2OjeyIHUS05p8QWOr3EFUCFsC31R4moihE5HN+FxNalUyyFZU//yjf1pdnlMJqrVByJSMa+y2y4x2FucpoCAO97Tx+iWzwlZ2UXEUXM1Y81mhPbeWXy+wP2xElTgIER0Tsn/thoA0SD2u9wJuVvM7dB7cBcHYmqV6JH+KWCedRTum6O1BssqP/4Lbm2+rkrbZ4+oVRoU2DRLoFhKqwqLtylrbuj4XOI3XykMXV5+uQXz1JzubNOB9lsc6K+eRC+w8hhhDuFMgzkZ4qomCnx3uhO67KaICd8yqqBa6PJ/+fBM5Xk4hjyR40bwcf41AgMBAAECggEAZnrCJ6IYiLyyRdr9SbKXCNDb4YByGYPEi/HT1aHgIJfFE1PSMjxcdytxfyjP4JJpVtPjiT9JFVU2ddoYu5qJN6tGwjVwgJEWg1UXmPaAw1T/drjS94kVsAs82qICtFmwp52Apg3dBZ0Qwq/8qE1XbG7lLyohIbfCBiL0tiPYMfkcsN9gnFT/kFCX0LVs2pa9fHCRMY9rqCc4/rWJa1w8sMuQ23y4lDaxKF9OZVvOHFQkbBDrkquWHE4r55fchCz/rJklkPJUNENuncBRu0/2X+p4IKFD1DnttXNwb8j4LPiSlLro1T0hiUr5gO2QmdYwXFF63Q3mjQy0+5I4eNbjjQKBgQDZvZy3gUKS/nQNkYfq9za80uLbIj/cWbO+ZZjXCsj0fNIcQFJcKMBoA7DjJvu2S/lf86/41YHkPdmrLAEQAkJ+5BBNOycjYK9minTEjIMMmZDTXXugZ62wnU6F46uLkgEChTqEP57Y6xwwV+JaEDFEsW5N1eE9lEVX9nGIr4phMwKBgQC1TazLuEt1WBx/iUT83ita7obXqoKNzwsS/MWfY2innzYZKDOqeSYZzLtt9uTtp4X4uLyPbYs0qFYhXLsUYMoGHNN8+NdjoyxCjQRJRBkMtaNR0lc5lVDWl3bTuJovjFCgAr9uqJrmI5OHcCIk/cDpdWb3nWaMihVlePmiTcTy9wKBgQCU0u7c1jKkudqks4XM6a+2HAYGdUBk4cLjLhnrUWnNAcuyl5wzdX8dGPi8KZb+IKuQE8WBNJ2VXVj7kBYh1QmSJVunDflQSvNYCOaKuOeRoxzD+y9Wkca74qkbBmPn/6FFEb7PSZTO+tPHjyodGNgz9XpJJRjQuBk1aDJtlF3m1QKBgE5SAr5ym65SZOU3UGUIOKRsfDW4Q/OsqDUImvpywCgBICaX9lHDShFFHwau7FA52ScL7vDquoMB4UtCOtLfyQYA9995w9oYCCurrVlVIJkb8jSLcADBHw3EmqF1kq3NqJqm9TmBfoDCh52vdCCUufxgKh33kfBOSlXuf7B8dgMbAoGAZ3r0/mBQX6S+s5+xCETMTSNv7TQzxgtURIpVs+ZVr2cMhWhiv+n0Omab9X9Z50se8cWl5lkvx8vn3D/XHHIPrMF6qk7RAXtvReb+PeitNvm0odqjFv0J2qki6fDs0HKwq4kojAXI1Md8Th0eobNjsy21fEEJT7uKMJdovI/SErI=', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaNSDOjPz6T8HZsf7LDpxiQRiN2OjeyIHUS05p8QWOr3EFUCFsC31R4moihE5HN+FxNalUyyFZU//yjf1pdnlMJqrVByJSMa+y2y4x2FucpoCAO97Tx+iWzwlZ2UXEUXM1Y81mhPbeWXy+wP2xElTgIER0Tsn/thoA0SD2u9wJuVvM7dB7cBcHYmqV6JH+KWCedRTum6O1BssqP/4Lbm2+rkrbZ4+oVRoU2DRLoFhKqwqLtylrbuj4XOI3XykMXV5+uQXz1JzubNOB9lsc6K+eRC+w8hhhDuFMgzkZ4qomCnx3uhO67KaICd8yqqBa6PJ/+fBM5Xk4hjyR40bwcf41AgMBAAE=' -} diff --git a/examples/chat/src/peer-id-listener.js b/examples/chat/src/peer-id-listener.js deleted file mode 100644 index 8e5acb76c0..0000000000 --- a/examples/chat/src/peer-id-listener.js +++ /dev/null @@ -1,5 +0,0 @@ -export default { - id: 'QmcrQZ6RJdpYuGvZqD5QEHAv6qX4BrQLJLQPQUrTrzdcgm', - privKey: 'CAASqAkwggSkAgEAAoIBAQDLZZcGcbe4urMBVlcHgN0fpBymY+xcr14ewvamG70QZODJ1h9sljlExZ7byLiqRB3SjGbfpZ1FweznwNxWtWpjHkQjTVXeoM4EEgDSNO/Cg7KNlU0EJvgPJXeEPycAZX9qASbVJ6EECQ40VR/7+SuSqsdL1hrmG1phpIju+D64gLyWpw9WEALfzMpH5I/KvdYDW3N4g6zOD2mZNp5y1gHeXINHWzMF596O72/6cxwyiXV1eJ000k1NVnUyrPjXtqWdVLRk5IU1LFpoQoXZU5X1hKj1a2qt/lZfH5eOrF/ramHcwhrYYw1txf8JHXWO/bbNnyemTHAvutZpTNrsWATfAgMBAAECggEAQj0obPnVyjxLFZFnsFLgMHDCv9Fk5V5bOYtmxfvcm50us6ye+T8HEYWGUa9RrGmYiLweuJD34gLgwyzE1RwptHPj3tdNsr4NubefOtXwixlWqdNIjKSgPlaGULQ8YF2tm/kaC2rnfifwz0w1qVqhPReO5fypL+0ShyANVD3WN0Fo2ugzrniCXHUpR2sHXSg6K+2+qWdveyjNWog34b7CgpV73Ln96BWae6ElU8PR5AWdMnRaA9ucA+/HWWJIWB3Fb4+6uwlxhu2L50Ckq1gwYZCtGw63q5L4CglmXMfIKnQAuEzazq9T4YxEkp+XDnVZAOgnQGUBYpetlgMmkkh9qQKBgQDvsEs0ThzFLgnhtC2Jy//ZOrOvIAKAZZf/mS08AqWH3L0/Rjm8ZYbLsRcoWU78sl8UFFwAQhMRDBP9G+RPojWVahBL/B7emdKKnFR1NfwKjFdDVaoX5uNvZEKSl9UubbC4WZJ65u/cd5jEnj+w3ir9G8n+P1gp/0yBz02nZXFgSwKBgQDZPQr4HBxZL7Kx7D49ormIlB7CCn2i7mT11Cppn5ifUTrp7DbFJ2t9e8UNk6tgvbENgCKXvXWsmflSo9gmMxeEOD40AgAkO8Pn2R4OYhrwd89dECiKM34HrVNBzGoB5+YsAno6zGvOzLKbNwMG++2iuNXqXTk4uV9GcI8OnU5ZPQKBgCZUGrKSiyc85XeiSGXwqUkjifhHNh8yH8xPwlwGUFIZimnD4RevZI7OEtXw8iCWpX2gg9XGuyXOuKORAkF5vvfVriV4e7c9Ad4Igbj8mQFWz92EpV6NHXGCpuKqRPzXrZrNOA9PPqwSs+s9IxI1dMpk1zhBCOguWx2m+NP79NVhAoGBAI6WSoTfrpu7ewbdkVzTWgQTdLzYNe6jmxDf2ZbKclrf7lNr/+cYIK2Ud5qZunsdBwFdgVcnu/02czeS42TvVBgs8mcgiQc/Uy7yi4/VROlhOnJTEMjlU2umkGc3zLzDgYiRd7jwRDLQmMrYKNyEr02HFKFn3w8kXSzW5I8rISnhAoGBANhchHVtJd3VMYvxNcQb909FiwTnT9kl9pkjhwivx+f8/K8pDfYCjYSBYCfPTM5Pskv5dXzOdnNuCj6Y2H/9m2SsObukBwF0z5Qijgu1DsxvADVIKZ4rzrGb4uSEmM6200qjJ/9U98fVM7rvOraakrhcf9gRwuspguJQnSO9cLj6', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLZZcGcbe4urMBVlcHgN0fpBymY+xcr14ewvamG70QZODJ1h9sljlExZ7byLiqRB3SjGbfpZ1FweznwNxWtWpjHkQjTVXeoM4EEgDSNO/Cg7KNlU0EJvgPJXeEPycAZX9qASbVJ6EECQ40VR/7+SuSqsdL1hrmG1phpIju+D64gLyWpw9WEALfzMpH5I/KvdYDW3N4g6zOD2mZNp5y1gHeXINHWzMF596O72/6cxwyiXV1eJ000k1NVnUyrPjXtqWdVLRk5IU1LFpoQoXZU5X1hKj1a2qt/lZfH5eOrF/ramHcwhrYYw1txf8JHXWO/bbNnyemTHAvutZpTNrsWATfAgMBAAE=' -} diff --git a/examples/chat/src/stream.js b/examples/chat/src/stream.js deleted file mode 100644 index 194a9c1da0..0000000000 --- a/examples/chat/src/stream.js +++ /dev/null @@ -1,41 +0,0 @@ -/* eslint-disable no-console */ - -import * as lp from 'it-length-prefixed' -import map from 'it-map' -import { pipe } from 'it-pipe' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -export function stdinToStream (stream) { - // Read utf-8 from stdin - process.stdin.setEncoding('utf8') - pipe( - // Read from stdin (the source) - process.stdin, - // Turn strings into buffers - (source) => map(source, (string) => uint8ArrayFromString(string)), - // Encode with length prefix (so receiving side knows how much data is coming) - (source) => lp.encode(source), - // Write to the stream (the sink) - stream.sink - ) -} - -export function streamToConsole (stream) { - pipe( - // Read from the stream (the source) - stream.source, - // Decode length-prefixed data - (source) => lp.decode(source), - // Turn buffers into strings - (source) => map(source, (buf) => uint8ArrayToString(buf.subarray())), - // Sink function - async function (source) { - // For each chunk of data - for await (const msg of source) { - // Output the data as a utf8 string - console.log('> ' + msg.toString().replace('\n', '')) - } - } - ) -} diff --git a/examples/chat/test.js b/examples/chat/test.js deleted file mode 100644 index 28ca41dc1e..0000000000 --- a/examples/chat/test.js +++ /dev/null @@ -1,74 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { execa } from 'execa' -import pDefer from 'p-defer' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -function startProcess (name) { - return execa('node', [path.join(__dirname, name)], { - cwd: path.resolve(__dirname), - all: true - }) -} - -const message = 'test message' -let listenerOutput = '' -let dialerOutput = '' - -let isListening = false -let messageSent = false -const listenerReady = pDefer() -const dialerReady = pDefer() -const messageReceived = pDefer() - -// Step 1 process -process.stdout.write('node listener.js\n') -const listenerProc = startProcess('./src/listener.js') -listenerProc.all.on('data', async (data) => { - process.stdout.write(data) - - listenerOutput += uint8ArrayToString(data) - - if (!isListening && listenerOutput.includes('Listener ready, listening on')) { - listenerReady.resolve() - isListening = true - } else if (isListening && listenerOutput.includes(message)) { - messageReceived.resolve() - } -}) - -await listenerReady.promise -process.stdout.write('==================================================================\n') - -// Step 2 process -process.stdout.write('node dialer.js\n') -const dialerProc = startProcess('./src/dialer.js') -dialerProc.all.on('data', async (data) => { - process.stdout.write(data) - dialerOutput += uint8ArrayToString(data) - - if (!messageSent && dialerOutput.includes('Type a message and see what happens')) { - dialerReady.resolve() - dialerProc.stdin.write(message) - dialerProc.stdin.write('\n') - messageSent = true - } -}) - -await dialerReady.promise -process.stdout.write('==================================================================\n') -await messageReceived.promise -process.stdout.write('chat message received\n') - -listenerProc.kill() -dialerProc.kill() -await Promise.all([ - listenerProc, - dialerProc -]).catch((err) => { - if (err.signal !== 'SIGTERM') { - throw err - } -}) diff --git a/examples/connection-encryption/1.js b/examples/connection-encryption/1.js deleted file mode 100644 index 44e1982b2a..0000000000 --- a/examples/connection-encryption/1.js +++ /dev/null @@ -1,52 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { pipe } from 'it-pipe' -import { createLibp2p } from 'libp2p' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()] - }) - - return node -} - -;(async () => { - const [node1, node2] = await Promise.all([ - createNode(), - createNode() - ]) - - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - - node2.handle('/a-protocol', ({ stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) - }) - - const stream = await node1.dialProtocol(node2.peerId, '/a-protocol') - - await pipe( - [uint8ArrayFromString('This information is sent out encrypted to the other peer')], - stream - ) -})() diff --git a/examples/connection-encryption/LICENSE b/examples/connection-encryption/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/connection-encryption/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/connection-encryption/LICENSE-APACHE b/examples/connection-encryption/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/connection-encryption/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/connection-encryption/LICENSE-MIT b/examples/connection-encryption/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/connection-encryption/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/connection-encryption/README.md b/examples/connection-encryption/README.md deleted file mode 100644 index 786c95b203..0000000000 --- a/examples/connection-encryption/README.md +++ /dev/null @@ -1,54 +0,0 @@ -# @libp2p/example-connection-encryption - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> An example of how to configure connection encrypters - -## Table of contents - -- [Set up encrypted communications](#set-up-encrypted-communications) -- [License](#license) -- [Contribution](#contribution) - -We call this usage a *connection upgrade* where given a connection between peer A to peer B, a protocol handshake can be performed that gives that connection new properties. - -A byproduct of having these encrypted communications modules is that we can authenticate the peers we are dialing to. You might have noticed that every time we dial to a peer in libp2p space, we always use its PeerId at the end (e.g /ip4/127.0.0.1/tcp/89765/p2p/QmWCbVw1XZ8hiYBwwshPce2yaTDYTqTaP7GCHGpry3ykWb), this PeerId is generated by hashing the Public Key of the peer. With this, we can create a crypto challenge when dialing to another peer and prove that peer is the owner of a PrivateKey that matches the Public Key we know. - -## Set up encrypted communications - -We will build this example on top of example for [Protocol and Stream Multiplexing](../protocol-and-stream-multiplexing). You will need the `@chainsafe/libp2p-noise` module to complete it, go ahead and `npm install @chainsafe/libp2p-noise`. - -To add them to your libp2p configuration, all you have to do is: - -```JavaScript -import { createLibp2p } from 'libp2p' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux', -import { noise } from '@chainsafe/libp2p-noise' - -const createNode = async () => { - return await createLibp2p({ - transports: [ tcp() ], - streamMuxers: [ mplex(), yamux() ], - // Attach noise as the crypto channel to use - conectionEncrypters: [ noise() ] - }) -} -``` - -And that's it, from now on, all your libp2p communications are encrypted. Try running the example [1.js](./1.js) to see it working. - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/connection-encryption/package.json b/examples/connection-encryption/package.json deleted file mode 100644 index d4c652bc1b..0000000000 --- a/examples/connection-encryption/package.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "name": "@libp2p/example-connection-encryption", - "version": "0.0.0", - "description": "An example of how to configure connection encrypters", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/connection-encryption#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/tcp": "^8.0.0", - "it-pipe": "^3.0.1", - "libp2p": "^0.46.0", - "uint8arrays": "^4.0.6" - }, - "devDependencies": { - "aegir": "^41.0.2", - "test-ipfs-example": "^1.0.0" - }, - "private": true -} diff --git a/examples/connection-encryption/test.js b/examples/connection-encryption/test.js deleted file mode 100644 index 1bba4c3bf2..0000000000 --- a/examples/connection-encryption/test.js +++ /dev/null @@ -1,11 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -process.stdout.write('1.js\n') - -await waitForOutput('This information is sent out encrypted to the other peer', 'node', [path.join(__dirname, '1.js')], { - cwd: __dirname -}) diff --git a/examples/delegated-routing/LICENSE b/examples/delegated-routing/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/delegated-routing/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/delegated-routing/LICENSE-APACHE b/examples/delegated-routing/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/delegated-routing/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/delegated-routing/LICENSE-MIT b/examples/delegated-routing/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/delegated-routing/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/delegated-routing/README.md b/examples/delegated-routing/README.md deleted file mode 100644 index bebbe9dcf1..0000000000 --- a/examples/delegated-routing/README.md +++ /dev/null @@ -1,75 +0,0 @@ -# @libp2p/example-delegated-routing-example - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> How to configure libp2p delegated routers - -## Table of contents - -- [Prerequisite](#prerequisite) -- [Running this example](#running-this-example) - - [Finding Content via the Delegate](#finding-content-via-the-delegate) - - [Finding Peers via the Delegate](#finding-peers-via-the-delegate) -- [License](#license) -- [Contribution](#contribution) - -The starting [Libp2p Bundle](./src/libp2p-bundle.js) in this example starts by disabling the DHT and adding the Delegated Peer and Content Routers. -Once you've completed the example, you should try enabled the DHT and see what kind of results you get! You can also enable the various Peer Discovery modules and see the impact it has on your Peer count. - -## Prerequisite - -This example uses a publicly known delegated routing node. This aims to ease experimentation, but you should not rely on this in production. - -## Running this example - -1. Install IPFS locally if you dont already have it. [Install Guide](https://docs.ipfs.tech/install/) -2. Run the IPFS daemon: `ipfs daemon` -3. In another window output the addresses of the node: `ipfs id`. Make note of the websocket address, it will contain `/ws/` in the address. - -- If there is no websocket address, you will need to add it in the ipfs config file (`~/.ipfs/config`) -- Add to Swarm Addresses something like: `"/ip4/127.0.0.1/tcp/4010/ws"` - -4. In `./src/App.js` replace `BootstrapNode` with your nodes Websocket address from the step above. -5. Start this example - -```sh -npm install -npm start -``` - -This should open your browser to . If it does not, go ahead and do that now. - -6. Your browser should show you connected to at least 1 peer. - -### Finding Content via the Delegate - -1. Add a file to your IPFS node. From this example root you can do `ipfs add ./README.md` to add the example readme. -2. Copy the hash from line 5, it will look something like *Qmf33vz4HJFkqgH7XPP1uA6atYKTX1BWQEQthzpKcAdeyZ*. -3. In the browser, paste the hash into the *Hash* field and hit `Find`. The readme contents should display. - -This will do a few things: - -- The delegate nodes api will be queried to find providers of the content -- The content will be fetched from the providers -- Since we now have the content, we tell the delegate node to fetch the content from us and become a provider - -### Finding Peers via the Delegate - -1. Get a list of your delegate nodes peer by querying the IPFS daemon: `ipfs swarm peers` -2. Copy one of the CIDs from the list of peer addresses, this will be the last portion of the address and will look something like `QmdoG8DpzYUZMVP5dGmgmigZwR1RE8Cf6SxMPg1SBXJAQ8`. -3. In your browser, paste the CID into the *Peer* field and hit `Find`. -4. You should see information about the peer including its addresses. - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/delegated-routing/package.json b/examples/delegated-routing/package.json deleted file mode 100644 index 1dc0953e35..0000000000 --- a/examples/delegated-routing/package.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "@libp2p/example-delegated-routing-example", - "version": "0.0.0", - "description": "How to configure libp2p delegated routers", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/delegated-routing#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "sourceType": "module", - "parserOptions": { - "sourceType": "module" - } - } - }, - "scripts": { - "lint": "aegir lint", - "start": "react-scripts start" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@libp2p/bootstrap": "^9.0.0", - "@libp2p/delegated-content-routing": "^4.0.0", - "@libp2p/delegated-peer-routing": "^4.0.0", - "@libp2p/kad-dht": "^10.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/websockets": "^7.0.0", - "kubo-rpc-client": "^3.0.1", - "libp2p": "^0.46.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-scripts": "^5.0.1" - }, - "devDependencies": { - "aegir": "^41.0.2" - }, - "browserslist": [ - ">0.2%", - "not dead", - "not ie <= 11", - "not op_mini all" - ], - "private": true -} diff --git a/examples/delegated-routing/public/favicon.ico b/examples/delegated-routing/public/favicon.ico deleted file mode 100644 index a11777cc47..0000000000 Binary files a/examples/delegated-routing/public/favicon.ico and /dev/null differ diff --git a/examples/delegated-routing/public/index.html b/examples/delegated-routing/public/index.html deleted file mode 100644 index 9082175b4e..0000000000 --- a/examples/delegated-routing/public/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - Delegated Routing - - - - -
- - diff --git a/examples/delegated-routing/public/main.css b/examples/delegated-routing/public/main.css deleted file mode 100644 index 5cd8188187..0000000000 --- a/examples/delegated-routing/public/main.css +++ /dev/null @@ -1,67 +0,0 @@ -body { - margin: 0; - padding: 0; - font-family: sans-serif; -} - -section * { - margin: 10px; -} - -header { - background-color: #222; - height: 150px; - padding: 20px; - color: white; -} - -.center { - text-align: center; -} - -pre { - background-color: bisque; - min-height: 100px; - margin: 0px; - padding: 10px; -} - -.loader { - text-align: center; - height: 64px; - margin-bottom: -64px; -} - -.loading .lds-ripple { - display: inline-block; - position: relative; - width: 64px; - height: 64px; -} -.loading .lds-ripple div { - position: absolute; - border: 4px solid #000; - opacity: 1; - border-radius: 50%; - animation: lds-ripple 1s cubic-bezier(0, 0.2, 0.8, 1) infinite; - margin: auto; -} -.loading .lds-ripple div:nth-child(2) { - animation-delay: -0.5s; -} -@keyframes lds-ripple { - 0% { - top: 28px; - left: 28px; - width: 0; - height: 0; - opacity: 1; - } - 100% { - top: -1px; - left: -1px; - width: 58px; - height: 58px; - opacity: 0; - } -} \ No newline at end of file diff --git a/examples/delegated-routing/src/App.js b/examples/delegated-routing/src/App.js deleted file mode 100644 index c092081d55..0000000000 --- a/examples/delegated-routing/src/App.js +++ /dev/null @@ -1,154 +0,0 @@ -// eslint-disable-next-line -'use strict' - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { bootstrap } from '@libp2p/bootstrap' -import { delegatedContentRouting } from '@libp2p/delegated-content-routing' -import { delegatedPeerRouting } from '@libp2p/delegated-peer-routing' -import { mplex } from '@libp2p/mplex' -import { webSockets } from '@libp2p/websockets' -import { create as createKuboRpcClient } from 'kubo-rpc-client' -import { createLibp2p } from 'libp2p' -import { circuitRelayTransport } from 'libp2p/circuit-relay' -import { CID } from 'multiformats/cid' -import React from 'react' - -const Component = React.Component - -const BootstrapNode = '/ip4/127.0.0.1/tcp/8081/ws/p2p/QmdoG8DpzYUZMVP5dGmgmigZwR1RE8Cf6SxMPg1SBXJAQ8' - -class App extends Component { - constructor (props) { - super(props) - this.state = { - peers: 0, - // This hash is the IPFS readme - hash: 'QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB', - // This peer is one of the Bootstrap nodes for IPFS - peer: 'QmV6kA2fB8kTr6jc3pL5zbNsjKbmPUHAPKKHRBYe1kDEyc', - isLoading: 0 - } - this.peerInterval = null - - this.handleHashChange = this.handleHashChange.bind(this) - this.handleHashSubmit = this.handleHashSubmit.bind(this) - this.handlePeerChange = this.handlePeerChange.bind(this) - this.handlePeerSubmit = this.handlePeerSubmit.bind(this) - } - - handleHashChange (event) { - this.setState({ - hash: event.target.value - }) - } - - handlePeerChange (event) { - this.setState({ - peer: event.target.value - }) - } - - async handleHashSubmit (event) { - event.preventDefault() - this.setState({ - isLoading: this.state.isLoading + 1 - }) - - const providers = [] - - for await (const provider of this.libp2p.contentRouting.findProviders(CID.parse(this.state.hash))) { - providers.push(provider) - - this.setState({ - response: providers.toString(), - isLoading: this.state.isLoading - 1 - }) - } - } - - async handlePeerSubmit (event) { - event.preventDefault() - this.setState({ - isLoading: this.state.isLoading + 1 - }) - - const peerInfo = await this.libp2p.peerRouting.findPeer(this.state.peer) - - this.setState({ - response: JSON.stringify(peerInfo, null, 2), - isLoading: this.state.isLoading - 1 - }) - } - - async componentDidMount () { - const client = createKuboRpcClient({ - host: '0.0.0.0', - protocol: 'http', - port: '8080' - }) - - window.libp2p = this.libp2p = await createLibp2p({ - contentRouting: [ - delegatedPeerRouting(client) - ], - peerRouting: [ - delegatedContentRouting(client) - ], - peerDiscovery: [ - bootstrap({ - list: { - BootstrapNode - } - }) - ], - transports: [ - webSockets(), - circuitRelayTransport() - ], - streamMuxers: [ - yamux(), mplex() - ], - connectionEncryption: [ - noise() - ] - }) - } - - render () { - return ( -
-
-

Delegated Routing

-

There are currently {this.state.peers} peers.

-
-
-
- -
-
- -
-
-
0 ? 'loading' : '', 'loader'].join(' ')}> -
-
-
-
-            {this.state.response}
-          
-
-
- ) - } -} - -export default App diff --git a/examples/delegated-routing/src/index.js b/examples/delegated-routing/src/index.js deleted file mode 100644 index 03b5425104..0000000000 --- a/examples/delegated-routing/src/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// eslint-disable-next-line -'use strict' - -import React from 'react' // eslint-disable-line no-unused-vars -import ReactDOM from 'react-dom' -import App from './App.js' // eslint-disable-line no-unused-vars - -ReactDOM.render(, document.getElementById('root')) diff --git a/examples/discovery-mechanisms/1.js b/examples/discovery-mechanisms/1.js deleted file mode 100644 index a653285945..0000000000 --- a/examples/discovery-mechanisms/1.js +++ /dev/null @@ -1,36 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { bootstrap } from '@libp2p/bootstrap' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { createLibp2p } from 'libp2p' -import bootstrappers from './bootstrappers.js' - -(async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - peerDiscovery: [ - bootstrap({ - list: bootstrappers - }) - ] - }) - - node.addEventListener('peer:connect', (evt) => { - const peerId = evt.detail - console.log('Connection established to:', peerId.toString()) // Emitted when a peer has been found - }) - - node.addEventListener('peer:discovery', (evt) => { - const peerInfo = evt.detail - - console.log('Discovered:', peerInfo.id.toString()) - }) -})() diff --git a/examples/discovery-mechanisms/2.js b/examples/discovery-mechanisms/2.js deleted file mode 100644 index 3a80cd5aeb..0000000000 --- a/examples/discovery-mechanisms/2.js +++ /dev/null @@ -1,42 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mdns } from '@libp2p/mdns' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { createLibp2p } from 'libp2p' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [ - tcp() - ], - streamMuxers: [ - yamux(), mplex() - ], - connectionEncryption: [ - noise() - ], - peerDiscovery: [ - mdns({ - interval: 20e3 - }) - ] - }) - - return node -} - -;(async () => { - const [node1, node2] = await Promise.all([ - createNode(), - createNode() - ]) - - node1.addEventListener('peer:discovery', (evt) => console.log('Discovered:', evt.detail.id.toString())) - node2.addEventListener('peer:discovery', (evt) => console.log('Discovered:', evt.detail.id.toString())) -})() diff --git a/examples/discovery-mechanisms/3.js b/examples/discovery-mechanisms/3.js deleted file mode 100644 index 93078517d2..0000000000 --- a/examples/discovery-mechanisms/3.js +++ /dev/null @@ -1,77 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { bootstrap } from '@libp2p/bootstrap' -import { floodsub } from '@libp2p/floodsub' -import { mplex } from '@libp2p/mplex' -import { pubsubPeerDiscovery } from '@libp2p/pubsub-peer-discovery' -import { tcp } from '@libp2p/tcp' -import { createLibp2p } from 'libp2p' -import { circuitRelayTransport, circuitRelayServer } from 'libp2p/circuit-relay' -import { identifyService } from 'libp2p/identify' - -const createNode = async (bootstrappers) => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - peerDiscovery: [ - bootstrap({ - list: bootstrappers - }), - pubsubPeerDiscovery({ - interval: 1000 - }) - ], - services: { - pubsub: floodsub(), - identify: identifyService() - } - }) - - return node -} - -;(async () => { - const relay = await createLibp2p({ - addresses: { - listen: [ - '/ip4/0.0.0.0/tcp/0' - ] - }, - transports: [tcp(), circuitRelayTransport()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - peerDiscovery: [ - pubsubPeerDiscovery({ - interval: 1000 - }) - ], - services: { - relay: circuitRelayServer(), - identify: identifyService(), - pubsub: floodsub() - } - }) - console.log(`libp2p relay started with id: ${relay.peerId.toString()}`) - - const relayMultiaddrs = relay.getMultiaddrs().map((m) => m.toString()) - - const [node1, node2] = await Promise.all([ - createNode(relayMultiaddrs), - createNode(relayMultiaddrs) - ]) - - node1.addEventListener('peer:discovery', (evt) => { - const peer = evt.detail - console.log(`Peer ${node1.peerId.toString()} discovered: ${peer.id.toString()}`) - }) - node2.addEventListener('peer:discovery', (evt) => { - const peer = evt.detail - console.log(`Peer ${node2.peerId.toString()} discovered: ${peer.id.toString()}`) - }) -})() diff --git a/examples/discovery-mechanisms/LICENSE b/examples/discovery-mechanisms/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/discovery-mechanisms/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/discovery-mechanisms/LICENSE-APACHE b/examples/discovery-mechanisms/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/discovery-mechanisms/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/discovery-mechanisms/LICENSE-MIT b/examples/discovery-mechanisms/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/discovery-mechanisms/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/discovery-mechanisms/README.md b/examples/discovery-mechanisms/README.md deleted file mode 100644 index 9402e1540f..0000000000 --- a/examples/discovery-mechanisms/README.md +++ /dev/null @@ -1,315 +0,0 @@ -# @libp2p/example-discovery-mechanisms - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> How to configure peer discovery mechanisms - -## Table of contents - -- [1. Bootstrap list of Peers when booting a node](#1-bootstrap-list-of-peers-when-booting-a-node) -- [2. MulticastDNS to find other peers in the network](#2-multicastdns-to-find-other-peers-in-the-network) -- [3. Pubsub based Peer Discovery](#3-pubsub-based-peer-discovery) -- [4. Where to find other Peer Discovery Mechanisms](#4-where-to-find-other-peer-discovery-mechanisms) -- [License](#license) -- [Contribution](#contribution) - -With this system, a libp2p node can both have a set of nodes to always connect on boot (bootstraper nodes), discover nodes through locality (e.g connected in the same LAN) or through serendipity (random walks on a DHT). - -These mechanisms save configuration and enable a node to operate without any explicit dials, it will just work. Once new peers are discovered, their known data is stored in the peer's PeerStore. - -## 1. Bootstrap list of Peers when booting a node - -For this demo, we will connect to IPFS default bootstrapper nodes and so, we will need to support the same set of features those nodes have, that are: TCP, mplex, and NOISE. You can see the complete example at [1.js](./1.js). - -First, we create our libp2p node. - -```JavaScript -import { createLibp2p } from 'libp2p' -import { bootstrap } from '@libp2p/bootstrap' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' -import { noise } from '@chainsafe/libp2p-noise' - -const node = await createLibp2p({ - transports: [ - tcp() - ], - streamMuxers: [ - yamux(), - mplex() - ], - connectionEncryption: [ - noise() - ], - peerDiscovery: [ - bootstrap({ - interval: 60e3, - list: bootstrapers - }) - ] -}) -``` - -In this configuration, we use a `bootstrappers` array listing peers to connect *on boot*. Here is the list used by js-ipfs and go-ipfs. - -```JavaScript -const bootstrapers = [ - '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt' -] -``` - -Now, once we create and start the node, we can listen for events such as `peer:discovery` and `peer:connect`, these events tell us when we found a peer, independently of the discovery mechanism used and when we actually dialed to that peer. - -```JavaScript -const node = await createLibp2p({ - start: false, - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [ - tcp() - ], - streamMuxers: [ - yamux(), - mplex() - ], - connectionEncryption: [ - noise() - ], - peerDiscovery: [ - bootstrap({ - interval: 60e3, - list: bootstrapers - }) - ] -}) - -node.addEventListener('peer:connect', (evt) => { - console.log('Connection established to:', evt.detail.remotePeer.toString()) // Emitted when a new connection has been created -}) - -node.addEventListener('peer:discovery', (evt) => { - // No need to dial, autoDial is on - console.log('Discovered:', evt.detail.id.toString()) -}) - -await node.start() -``` - -From running [1.js](./1.js), you should see the following: - -```bash -> node 1.js -Discovered: QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ -Discovered: QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN -Discovered: QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb -Discovered: QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp -Discovered: QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa -Discovered: QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt -Connection established to: QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ -Connection established to: QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN -Connection established to: QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp -Connection established to: QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa -Connection established to: QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt -Connection established to: QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb -``` - -## 2. MulticastDNS to find other peers in the network - -For this example, we need `@libp2p/mdns`, go ahead and `npm install` it. You can find the complete solution at [2.js](./2.js). - -Update your libp2p configuration to include MulticastDNS. - -```JavaScript -import { createLibp2p } from 'libp2p' -import { mdns } from '@libp2p/mdns' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' -import { noise } from '@chainsafe/libp2p-noise' - -const createNode = () => { - return createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [ - tcp() - ], - streamMuxers: [ - yamux(),mplex() - ], - connectionEncryption: [ - noise() - ], - peerDiscovery: [ - mdns({ - interval: 20e3 - }) - ] - }) -} -``` - -To observe it working, spawn two nodes. - -```JavaScript -const [node1, node2] = await Promise.all([ - createNode(), - createNode() -]) - -node1.addEventListener('peer:discovery', (evt) => console.log('Discovered:', evt.detail.id.toString())) -node2.addEventListener('peer:discovery', (evt) => console.log('Discovered:', evt.detail.id.toString())) -``` - -If you run this example, you will see the other peers being discovered. - -```bash -> node 2.js -Discovered: QmSSbQpuKrxkoXHm1v4Pi35hPN5hUHMZoBoawEs2Nhvi8m -Discovered: QmRcXXhtG8vTqwVBRonKWtV4ovDoC1Fe56WYtcrw694eiJ -``` - -## 3. Pubsub based Peer Discovery - -For this example, we need [`@libp2p/pubsub-peer-discovery`](https://github.com/libp2p/js-libp2p-pubsub-peer-discovery/), go ahead and `npm install` it. You also need to spin up a set of [`libp2p-relay-servers`](https://github.com/libp2p/js-libp2p-relay-server). These servers act as relay servers and a peer discovery source. - -In the context of this example, we will create and run the `libp2p-relay-server` in the same code snippet. You can find the complete solution at [3.js](./3.js). - -You can create your libp2p nodes as follows: - -```js -import { createLibp2p } from 'libp2p' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { noise } from '@chainsafe/libp2p-noise' -import { GossipSub } from '@chainsafe/libp2p-gossipsub' -import { bootstrap } from '@libp2p/bootstrap' -import { PubSubPeerDiscovery } from '@libp2p/pubsub-peer-discovery' - -const createNode = async (bootstrapers) => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [ - tcp() - ], - streamMuxers: [ - yamux(),mplex() - ], - connectionEncryption: [ - noise() - ], - pubsub: gossipsub({ allowPublishToZeroPeers: true }), - peerDiscovery: [ - bootstrap({ - interval: 60e3, - list: bootstrapers - }), - new PubSubPeerDiscovery({ - interval: 1000 - }) - ] - }) - - return node -} -``` - -We will use the `libp2p-relay-server` as bootstrap nodes for the libp2p nodes, so that they establish a connection with the relay after starting. As a result, after they establish a connection with the relay, the pubsub discovery will kick in and the relay will advertise them. - -```js -const relay = await createLibp2p({ - addresses: { - listen: [ - '/ip4/0.0.0.0/tcp/0' - ] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - pubsub: gossipsub({ allowPublishToZeroPeers: true }), - peerDiscovery: [ - new PubSubPeerDiscovery({ - interval: 1000 - }) - ], - relay: { - enabled: true, // Allows you to dial and accept relayed connections. Does not make you a relay. - hop: { - enabled: true // Allows you to be a relay for other peers - } - } -}) - -console.log(`libp2p relay starting with id: ${relay.peerId.toString()}`) - -await relay.start() - -const relayMultiaddrs = relay.getMultiaddrs() - -const [node1, node2] = await Promise.all([ - createNode(relayMultiaddrs), - createNode(relayMultiaddrs) -]) - -node1.addEventListener('peer:discovery', (evt) => { - console.log(`Peer ${node1.peerId.toString()} discovered: ${evt.detail.id.toString()}`) -}) -node2.addEventListener('peer:discovery', (evt) => { - console.log(`Peer ${node2.peerId.toString()} discovered: ${evt.detail.id.toString()}`) -}) - -;[node1, node2].forEach((node, index) => console.log(`Node ${index} starting with id: ${node.peerId.toString()}`)) - -await Promise.all([ - node1.start(), - node2.start() -]) -``` - -If you run this example, you will see the other peers being discovered. - -```bash -> node 3.js -libp2p relay starting with id: QmW6FqVV6RsyoGC5zaeFGW9gSWA3LcBRVZrjkKMruh38Bo -Node 0 starting with id: QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N -Node 1 starting with id: QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv -Peer QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N discovered: QmW6FqVV6RsyoGC5zaeFGW9gSWA3LcBRVZrjkKMruh38Bo -Peer QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv discovered: QmW6FqVV6RsyoGC5zaeFGW9gSWA3LcBRVZrjkKMruh38Bo -Peer QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv discovered: QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N -Peer QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N discovered: QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv -``` - -Taking into account the output, after the relay and both libp2p nodes start, both libp2p nodes will discover the bootstrap node (relay) and connect with it. After establishing a connection with the relay, they will discover each other. - -This is really useful when running libp2p in constrained environments like a browser. You can run a set of `libp2p-relay-server` nodes that will be responsible for both relaying websocket connections between browser nodes and for discovering other browser peers. - -## 4. Where to find other Peer Discovery Mechanisms - -There are plenty more Peer Discovery Mechanisms out there, you can: - -- Any DHT will offer you a discovery capability. You can simple _random-walk_ the routing tables to find other peers to connect to. For example [@libp2p/kad-dht](https://github.com/libp2p/js-libp2p/tree/master/packages/kad-dht) can be used for peer discovery. An example of how to configure it to enable random walks can be found [here](https://github.com/libp2p/js-libp2p/blob/v0.28.4/doc/CONFIGURATION.md#customizing-dht). -- You can create your own Discovery service, a registry, a list, a radio beacon, you name it! - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/discovery-mechanisms/bootstrappers.js b/examples/discovery-mechanisms/bootstrappers.js deleted file mode 100644 index 85c5e73151..0000000000 --- a/examples/discovery-mechanisms/bootstrappers.js +++ /dev/null @@ -1,9 +0,0 @@ -// Find this list at: https://github.com/ipfs/js-ipfs/blob/master/packages/ipfs-core-config/src/config.js -export default [ - '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt' -] diff --git a/examples/discovery-mechanisms/package.json b/examples/discovery-mechanisms/package.json deleted file mode 100644 index 934710d4a3..0000000000 --- a/examples/discovery-mechanisms/package.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "@libp2p/example-discovery-mechanisms", - "version": "0.0.0", - "description": "How to configure peer discovery mechanisms", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/discovery-mechanisms#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "start": "react-scripts start", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/bootstrap": "^9.0.0", - "@libp2p/floodsub": "^8.0.0", - "@libp2p/mdns": "^9.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/pubsub-peer-discovery": "^9.0.0", - "@libp2p/tcp": "^8.0.0", - "libp2p": "^0.46.0" - }, - "devDependencies": { - "aegir": "^41.0.2", - "execa": "^8.0.1", - "p-wait-for": "^5.0.2", - "uint8arrays": "^4.0.4" - }, - "private": true -} diff --git a/examples/discovery-mechanisms/test-1.js b/examples/discovery-mechanisms/test-1.js deleted file mode 100644 index e8570adb48..0000000000 --- a/examples/discovery-mechanisms/test-1.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('1.js\n') - - await waitForOutput('Connection established to:', 'node', [path.join(__dirname, '1.js')], { - cwd: __dirname - }) -} diff --git a/examples/discovery-mechanisms/test-2.js b/examples/discovery-mechanisms/test-2.js deleted file mode 100644 index 24f3a0b476..0000000000 --- a/examples/discovery-mechanisms/test-2.js +++ /dev/null @@ -1,33 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { execa } from 'execa' -import pWaitFor from 'p-wait-for' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - let discoveredNodes = 0 - - process.stdout.write('2.js\n') - - const proc = execa('node', [path.join(__dirname, '2.js')], { - cwd: path.resolve(__dirname), - all: true - }) - - proc.all.on('data', async (data) => { - process.stdout.write(data) - const str = uint8ArrayToString(data) - - str.split('\n').forEach(line => { - if (line.includes('Discovered:')) { - discoveredNodes++ - } - }) - }) - - await pWaitFor(() => discoveredNodes > 1, 600000) - - proc.kill() -} diff --git a/examples/discovery-mechanisms/test-3.js b/examples/discovery-mechanisms/test-3.js deleted file mode 100644 index cd7e58a5d6..0000000000 --- a/examples/discovery-mechanisms/test-3.js +++ /dev/null @@ -1,38 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { execa } from 'execa' -import pWaitFor from 'p-wait-for' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - const discoveredPeers = [] - - process.stdout.write('3.js\n') - - const proc = execa('node', [path.join(__dirname, '3.js')], { - cwd: path.resolve(__dirname), - all: true - }) - - proc.all.on('data', async (data) => { - process.stdout.write(data) - const str = uint8ArrayToString(data) - const discoveredPeersRegex = /Peer\s+(?[^\s]+)\s+discovered:\s+(?[^\s]+)/ - str.split('\n').forEach(line => { - const peers = line.match(discoveredPeersRegex) - if (peers != null) { - // sort so we don't count reversed pair twice - const match = [peers.groups.Peer1, peers.groups.Peer2].sort().join(',') - if (!discoveredPeers.includes(match)) { - discoveredPeers.push(match) - } - } - }) - }) - - await pWaitFor(() => discoveredPeers.length > 2, 600000) - - proc.kill() -} diff --git a/examples/discovery-mechanisms/test.js b/examples/discovery-mechanisms/test.js deleted file mode 100644 index fd441b83ed..0000000000 --- a/examples/discovery-mechanisms/test.js +++ /dev/null @@ -1,7 +0,0 @@ -import { test as test1 } from './test-1.js' -import { test as test2 } from './test-2.js' -import { test as test3 } from './test-3.js' - -await test1() -await test2() -await test3() diff --git a/examples/echo/LICENSE b/examples/echo/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/echo/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/echo/LICENSE-APACHE b/examples/echo/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/echo/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/echo/LICENSE-MIT b/examples/echo/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/echo/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/echo/README.md b/examples/echo/README.md deleted file mode 100644 index 098e613025..0000000000 --- a/examples/echo/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# @libp2p/example-echo - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> An example echo app - -## Table of contents - -- [Setup](#setup) -- [Running](#running) -- [License](#license) -- [Contribution](#contribution) - -## Setup - -1. Install the modules from libp2p root, `npm install` and `npm run build`. -2. Open 2 terminal windows in the `./src` directory. - -## Running - -1. Run the listener in window 1, `node listener.js` -2. Run the dialer in window 2, `node dialer.js` -3. You should see console logs showing the dial, and the received echo of *hey* -4. If you look at the listener window, you will see it receiving the dial - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/echo/package.json b/examples/echo/package.json deleted file mode 100644 index fe6e07a54b..0000000000 --- a/examples/echo/package.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "@libp2p/example-echo", - "version": "0.0.0", - "description": "An example echo app", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/echo#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/peer-id-factory": "^3.0.0", - "@libp2p/tcp": "^8.0.0", - "@libp2p/websockets": "^7.0.0", - "@multiformats/multiaddr": "^12.1.5", - "@nodeutils/defaults-deep": "^1.1.0", - "it-pipe": "^3.0.1", - "libp2p": "^0.46.0", - "uint8arrays": "^4.0.6" - }, - "devDependencies": { - "aegir": "^41.0.2", - "execa": "^8.0.1", - "p-defer": "^4.0.0" - }, - "private": true -} diff --git a/examples/echo/src/dialer.js b/examples/echo/src/dialer.js deleted file mode 100644 index 07eb3d1584..0000000000 --- a/examples/echo/src/dialer.js +++ /dev/null @@ -1,58 +0,0 @@ -/* eslint-disable no-console */ - -/* - * Dialer Node - */ - -import { createFromJSON } from '@libp2p/peer-id-factory' -import { multiaddr } from '@multiformats/multiaddr' -import { pipe } from 'it-pipe' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import idd from './id-d.js' -import idl from './id-l.js' -import { createLibp2p } from './libp2p.js' - -async function run () { - const [dialerId, listenerId] = await Promise.all([ - createFromJSON(idd), - createFromJSON(idl) - ]) - - // Dialer - const dialerNode = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - peerId: dialerId - }) - - // Add peer to Dial (the listener) into the PeerStore - const listenerMultiaddr = multiaddr('/ip4/127.0.0.1/tcp/10333/p2p/' + listenerId.toString()) - - console.log('Dialer ready, listening on:') - dialerNode.getMultiaddrs().forEach((ma) => console.log(ma.toString())) - - // Dial the listener node - console.log('Dialing to peer:', listenerMultiaddr) - const stream = await dialerNode.dialProtocol(listenerMultiaddr, '/echo/1.0.0') - - console.log('nodeA dialed to nodeB on protocol: /echo/1.0.0') - - pipe( - // Source data - [uint8ArrayFromString('hey')], - // Write to the stream, and pass its output to the next function - stream, - // Sink function - async function (source) { - // For each chunk of data - for await (const data of source) { - // Output the data - console.log('received echo:', uint8ArrayToString(data.subarray())) - } - } - ) -} - -run() diff --git a/examples/echo/src/id-d.js b/examples/echo/src/id-d.js deleted file mode 100644 index 79d31007f2..0000000000 --- a/examples/echo/src/id-d.js +++ /dev/null @@ -1,5 +0,0 @@ -export default { - id: 'Qma3GsJmB47xYuyahPZPSadh1avvxfyYQwk8R3UnFrQ6aP', - privKey: 'CAASpwkwggSjAgEAAoIBAQCaNSDOjPz6T8HZsf7LDpxiQRiN2OjeyIHUS05p8QWOr3EFUCFsC31R4moihE5HN+FxNalUyyFZU//yjf1pdnlMJqrVByJSMa+y2y4x2FucpoCAO97Tx+iWzwlZ2UXEUXM1Y81mhPbeWXy+wP2xElTgIER0Tsn/thoA0SD2u9wJuVvM7dB7cBcHYmqV6JH+KWCedRTum6O1BssqP/4Lbm2+rkrbZ4+oVRoU2DRLoFhKqwqLtylrbuj4XOI3XykMXV5+uQXz1JzubNOB9lsc6K+eRC+w8hhhDuFMgzkZ4qomCnx3uhO67KaICd8yqqBa6PJ/+fBM5Xk4hjyR40bwcf41AgMBAAECggEAZnrCJ6IYiLyyRdr9SbKXCNDb4YByGYPEi/HT1aHgIJfFE1PSMjxcdytxfyjP4JJpVtPjiT9JFVU2ddoYu5qJN6tGwjVwgJEWg1UXmPaAw1T/drjS94kVsAs82qICtFmwp52Apg3dBZ0Qwq/8qE1XbG7lLyohIbfCBiL0tiPYMfkcsN9gnFT/kFCX0LVs2pa9fHCRMY9rqCc4/rWJa1w8sMuQ23y4lDaxKF9OZVvOHFQkbBDrkquWHE4r55fchCz/rJklkPJUNENuncBRu0/2X+p4IKFD1DnttXNwb8j4LPiSlLro1T0hiUr5gO2QmdYwXFF63Q3mjQy0+5I4eNbjjQKBgQDZvZy3gUKS/nQNkYfq9za80uLbIj/cWbO+ZZjXCsj0fNIcQFJcKMBoA7DjJvu2S/lf86/41YHkPdmrLAEQAkJ+5BBNOycjYK9minTEjIMMmZDTXXugZ62wnU6F46uLkgEChTqEP57Y6xwwV+JaEDFEsW5N1eE9lEVX9nGIr4phMwKBgQC1TazLuEt1WBx/iUT83ita7obXqoKNzwsS/MWfY2innzYZKDOqeSYZzLtt9uTtp4X4uLyPbYs0qFYhXLsUYMoGHNN8+NdjoyxCjQRJRBkMtaNR0lc5lVDWl3bTuJovjFCgAr9uqJrmI5OHcCIk/cDpdWb3nWaMihVlePmiTcTy9wKBgQCU0u7c1jKkudqks4XM6a+2HAYGdUBk4cLjLhnrUWnNAcuyl5wzdX8dGPi8KZb+IKuQE8WBNJ2VXVj7kBYh1QmSJVunDflQSvNYCOaKuOeRoxzD+y9Wkca74qkbBmPn/6FFEb7PSZTO+tPHjyodGNgz9XpJJRjQuBk1aDJtlF3m1QKBgE5SAr5ym65SZOU3UGUIOKRsfDW4Q/OsqDUImvpywCgBICaX9lHDShFFHwau7FA52ScL7vDquoMB4UtCOtLfyQYA9995w9oYCCurrVlVIJkb8jSLcADBHw3EmqF1kq3NqJqm9TmBfoDCh52vdCCUufxgKh33kfBOSlXuf7B8dgMbAoGAZ3r0/mBQX6S+s5+xCETMTSNv7TQzxgtURIpVs+ZVr2cMhWhiv+n0Omab9X9Z50se8cWl5lkvx8vn3D/XHHIPrMF6qk7RAXtvReb+PeitNvm0odqjFv0J2qki6fDs0HKwq4kojAXI1Md8Th0eobNjsy21fEEJT7uKMJdovI/SErI=', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaNSDOjPz6T8HZsf7LDpxiQRiN2OjeyIHUS05p8QWOr3EFUCFsC31R4moihE5HN+FxNalUyyFZU//yjf1pdnlMJqrVByJSMa+y2y4x2FucpoCAO97Tx+iWzwlZ2UXEUXM1Y81mhPbeWXy+wP2xElTgIER0Tsn/thoA0SD2u9wJuVvM7dB7cBcHYmqV6JH+KWCedRTum6O1BssqP/4Lbm2+rkrbZ4+oVRoU2DRLoFhKqwqLtylrbuj4XOI3XykMXV5+uQXz1JzubNOB9lsc6K+eRC+w8hhhDuFMgzkZ4qomCnx3uhO67KaICd8yqqBa6PJ/+fBM5Xk4hjyR40bwcf41AgMBAAE=' -} diff --git a/examples/echo/src/id-l.js b/examples/echo/src/id-l.js deleted file mode 100644 index 8e5acb76c0..0000000000 --- a/examples/echo/src/id-l.js +++ /dev/null @@ -1,5 +0,0 @@ -export default { - id: 'QmcrQZ6RJdpYuGvZqD5QEHAv6qX4BrQLJLQPQUrTrzdcgm', - privKey: 'CAASqAkwggSkAgEAAoIBAQDLZZcGcbe4urMBVlcHgN0fpBymY+xcr14ewvamG70QZODJ1h9sljlExZ7byLiqRB3SjGbfpZ1FweznwNxWtWpjHkQjTVXeoM4EEgDSNO/Cg7KNlU0EJvgPJXeEPycAZX9qASbVJ6EECQ40VR/7+SuSqsdL1hrmG1phpIju+D64gLyWpw9WEALfzMpH5I/KvdYDW3N4g6zOD2mZNp5y1gHeXINHWzMF596O72/6cxwyiXV1eJ000k1NVnUyrPjXtqWdVLRk5IU1LFpoQoXZU5X1hKj1a2qt/lZfH5eOrF/ramHcwhrYYw1txf8JHXWO/bbNnyemTHAvutZpTNrsWATfAgMBAAECggEAQj0obPnVyjxLFZFnsFLgMHDCv9Fk5V5bOYtmxfvcm50us6ye+T8HEYWGUa9RrGmYiLweuJD34gLgwyzE1RwptHPj3tdNsr4NubefOtXwixlWqdNIjKSgPlaGULQ8YF2tm/kaC2rnfifwz0w1qVqhPReO5fypL+0ShyANVD3WN0Fo2ugzrniCXHUpR2sHXSg6K+2+qWdveyjNWog34b7CgpV73Ln96BWae6ElU8PR5AWdMnRaA9ucA+/HWWJIWB3Fb4+6uwlxhu2L50Ckq1gwYZCtGw63q5L4CglmXMfIKnQAuEzazq9T4YxEkp+XDnVZAOgnQGUBYpetlgMmkkh9qQKBgQDvsEs0ThzFLgnhtC2Jy//ZOrOvIAKAZZf/mS08AqWH3L0/Rjm8ZYbLsRcoWU78sl8UFFwAQhMRDBP9G+RPojWVahBL/B7emdKKnFR1NfwKjFdDVaoX5uNvZEKSl9UubbC4WZJ65u/cd5jEnj+w3ir9G8n+P1gp/0yBz02nZXFgSwKBgQDZPQr4HBxZL7Kx7D49ormIlB7CCn2i7mT11Cppn5ifUTrp7DbFJ2t9e8UNk6tgvbENgCKXvXWsmflSo9gmMxeEOD40AgAkO8Pn2R4OYhrwd89dECiKM34HrVNBzGoB5+YsAno6zGvOzLKbNwMG++2iuNXqXTk4uV9GcI8OnU5ZPQKBgCZUGrKSiyc85XeiSGXwqUkjifhHNh8yH8xPwlwGUFIZimnD4RevZI7OEtXw8iCWpX2gg9XGuyXOuKORAkF5vvfVriV4e7c9Ad4Igbj8mQFWz92EpV6NHXGCpuKqRPzXrZrNOA9PPqwSs+s9IxI1dMpk1zhBCOguWx2m+NP79NVhAoGBAI6WSoTfrpu7ewbdkVzTWgQTdLzYNe6jmxDf2ZbKclrf7lNr/+cYIK2Ud5qZunsdBwFdgVcnu/02czeS42TvVBgs8mcgiQc/Uy7yi4/VROlhOnJTEMjlU2umkGc3zLzDgYiRd7jwRDLQmMrYKNyEr02HFKFn3w8kXSzW5I8rISnhAoGBANhchHVtJd3VMYvxNcQb909FiwTnT9kl9pkjhwivx+f8/K8pDfYCjYSBYCfPTM5Pskv5dXzOdnNuCj6Y2H/9m2SsObukBwF0z5Qijgu1DsxvADVIKZ4rzrGb4uSEmM6200qjJ/9U98fVM7rvOraakrhcf9gRwuspguJQnSO9cLj6', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLZZcGcbe4urMBVlcHgN0fpBymY+xcr14ewvamG70QZODJ1h9sljlExZ7byLiqRB3SjGbfpZ1FweznwNxWtWpjHkQjTVXeoM4EEgDSNO/Cg7KNlU0EJvgPJXeEPycAZX9qASbVJ6EECQ40VR/7+SuSqsdL1hrmG1phpIju+D64gLyWpw9WEALfzMpH5I/KvdYDW3N4g6zOD2mZNp5y1gHeXINHWzMF596O72/6cxwyiXV1eJ000k1NVnUyrPjXtqWdVLRk5IU1LFpoQoXZU5X1hKj1a2qt/lZfH5eOrF/ramHcwhrYYw1txf8JHXWO/bbNnyemTHAvutZpTNrsWATfAgMBAAE=' -} diff --git a/examples/echo/src/libp2p.js b/examples/echo/src/libp2p.js deleted file mode 100644 index 85b569490a..0000000000 --- a/examples/echo/src/libp2p.js +++ /dev/null @@ -1,24 +0,0 @@ -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { webSockets } from '@libp2p/websockets' -import defaultsDeep from '@nodeutils/defaults-deep' -import { createLibp2p as createNode } from 'libp2p' - -export async function createLibp2p (_options) { - const defaults = { - transports: [ - tcp(), - webSockets() - ], - streamMuxers: [ - yamux(), mplex() - ], - connectionEncryption: [ - noise() - ] - } - - return createNode(defaultsDeep(_options, defaults)) -} diff --git a/examples/echo/src/listener.js b/examples/echo/src/listener.js deleted file mode 100644 index 1ff193cf33..0000000000 --- a/examples/echo/src/listener.js +++ /dev/null @@ -1,39 +0,0 @@ -/* eslint-disable no-console */ - -/* - * Listener Node - */ - -import { createFromJSON } from '@libp2p/peer-id-factory' -import { pipe } from 'it-pipe' -import idl from './id-l.js' -import { createLibp2p } from './libp2p.js' - -async function run () { - const listenerId = await createFromJSON(idl) - - // Listener libp2p node - const listenerNode = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/10333'] - }, - peerId: listenerId - }) - - // Log a message when we receive a connection - listenerNode.addEventListener('peer:connect', (evt) => { - const remotePeer = evt.detail - console.log('received dial to me from:', remotePeer.toString()) - }) - - // Handle incoming connections for the protocol by piping from the stream - // back to itself (an echo) - await listenerNode.handle('/echo/1.0.0', ({ stream }) => pipe(stream.source, stream.sink)) - - console.log('Listener ready, listening on:') - listenerNode.getMultiaddrs().forEach((ma) => { - console.log(ma.toString()) - }) -} - -run() diff --git a/examples/echo/test.js b/examples/echo/test.js deleted file mode 100644 index 5bdb55c3a6..0000000000 --- a/examples/echo/test.js +++ /dev/null @@ -1,58 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { execa } from 'execa' -import pDefer from 'p-defer' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -function startProcess (name) { - return execa('node', [path.join(__dirname, name)], { - cwd: path.resolve(__dirname), - all: true - }) -} - -const listenerReady = pDefer() -const messageReceived = pDefer() - -// Step 1 process -process.stdout.write('node src/listener.js\n') -const listenerProc = startProcess('src/listener.js') -listenerProc.all.on('data', async (data) => { - process.stdout.write(data) - const s = uint8ArrayToString(data) - - if (s.includes('Listener ready, listening on:')) { - listenerReady.resolve() - } -}) - -await listenerReady.promise -process.stdout.write('==================================================================\n') - -// Step 2 process -process.stdout.write('node src/dialer.js\n') -const dialerProc = startProcess('src/dialer.js') -dialerProc.all.on('data', async (data) => { - process.stdout.write(data) - const s = uint8ArrayToString(data) - - if (s.includes('received echo:')) { - messageReceived.resolve() - } -}) - -await messageReceived.promise -process.stdout.write('echo message received\n') - -listenerProc.kill() -dialerProc.kill() -await Promise.all([ - listenerProc, - dialerProc -]).catch((err) => { - if (err.signal !== 'SIGTERM') { - throw err - } -}) diff --git a/examples/libp2p-in-the-browser/webrtc/README.md b/examples/libp2p-in-the-browser/webrtc/README.md deleted file mode 100644 index 8b78f83bbe..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Examples - -* [Browser to Server Echo](browser-to-server/README.md): connect to a go-libp2p-webrtc server with a browser - diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/README.md b/examples/libp2p-in-the-browser/webrtc/browser-to-browser/README.md deleted file mode 100644 index e7449a0a1e..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# js-libp2p-webrtc Browser to Browser - -This example leverages the [vite bundler](https://vitejs.dev/) to compile and serve the libp2p code in the browser. You can use other bundlers such as Webpack, but we will not be covering them here. - -## Build the `@libp2p/webrtc` package - -Build the `@libp2p/webrtc` package by calling `npm i && npm run build` in the repository root. - -## Running the Relay Server - -For browsers to communicate, we first need to run the LibP2P relay server: - -```shell -npm run relay -``` - -Copy one of the multiaddresses in the output. - -## Running the Example - -In a separate console tab, install dependencies and start the Vite server: - -```shell -npm i && npm run start -``` - -The browser window will automatically open. Let's call this `Browser A`. -Using the copied multiaddress from the Go or NodeJS relay server, paste it into the `Remote MultiAddress` input and click the `Connect` button. -`Browser A` is now connected to the relay server. -Copy the multiaddress located after the `Listening on` message. - -Now open a second browser with the url `http://localhost:5173/`. Let's call this `Browser B`. -Using the copied multiaddress from `Listening on` section in `Browser A`, paste it into the `Remote MultiAddress` input and click the `Connect` button. -`Browser B` is now connected to `Browser A`. -Copy the multiaddress located after the `Listening on` message. - -Using the copied multiaddress from `Listening on` section in `Browser B`, paste it into the `Remote MultiAddress` input in `Browser A` and click the `Connect` button. -`Browser A` is now connected to `Browser B`. - -The peers are now connected to each other. Enter a message and click the `Send` button in either/both browsers and see the echo'd messages. - -The output should look like: - -`Browser A` -```text -Dialing '/ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk' -Listening on /ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk/p2p-circuit/p2p/12D3KooW9wFiWFELqGJTbzEwtByXsPiHJdHB8n7Kin71VMYyERmC/p2p-circuit/webrtc/p2p/12D3KooW9wFiWFELqGJTbzEwtByXsPiHJdHB8n7Kin71VMYyERmC -Dialing '/ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk/p2p-circuit/p2p/12D3KooWBZyVLJfQkofqLK4op9TPkHuUumCZt1ybQrPvNm7TVQV9/p2p-circuit/webrtc/p2p/12D3KooWBZyVLJfQkofqLK4op9TPkHuUumCZt1ybQrPvNm7TVQV9' -Sending message 'helloa' -Received message 'helloa' -Received message 'hellob' -``` - -`Browser B` -```text -Dialing '/ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk/p2p-circuit/p2p/12D3KooW9wFiWFELqGJTbzEwtByXsPiHJdHB8n7Kin71VMYyERmC/p2p-circuit/webrtc/p2p/12D3KooW9wFiWFELqGJTbzEwtByXsPiHJdHB8n7Kin71VMYyERmC' -Listening on /ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk/p2p-circuit/p2p/12D3KooWBZyVLJfQkofqLK4op9TPkHuUumCZt1ybQrPvNm7TVQV9/p2p-circuit/webrtc/p2p/12D3KooWBZyVLJfQkofqLK4op9TPkHuUumCZt1ybQrPvNm7TVQV9 -Received message 'helloa' -Sending message 'hellob' -Received message 'hellob' -``` diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/index.html b/examples/libp2p-in-the-browser/webrtc/browser-to-browser/index.html deleted file mode 100644 index 8da321d9d0..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/index.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - js-libp2p WebRTC - - - -
-
- - - -
-
- - - -
-
-

Active Connections:

-
    -
    -
    -

    Listening addresses:

    -
      -
      -
      -
      - - - diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/index.js b/examples/libp2p-in-the-browser/webrtc/browser-to-browser/index.js deleted file mode 100644 index 36edf09efd..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/index.js +++ /dev/null @@ -1,133 +0,0 @@ -import { multiaddr, protocols } from "@multiformats/multiaddr" -import { pipe } from "it-pipe" -import { fromString, toString } from "uint8arrays" -import { webRTC } from "@libp2p/webrtc" -import { webSockets } from "@libp2p/websockets" -import * as filters from "@libp2p/websockets/filters" -import { pushable } from "it-pushable" -import { mplex } from "@libp2p/mplex" -import { createLibp2p } from "libp2p" -import { circuitRelayTransport } from 'libp2p/circuit-relay' -import { noise } from "@chainsafe/libp2p-noise" -import { identifyService } from 'libp2p/identify' - -const WEBRTC_CODE = protocols('webrtc').code - -const output = document.getElementById("output") -const sendSection = document.getElementById("send-section") -const appendOutput = (line) => { - const div = document.createElement("div") - div.appendChild(document.createTextNode(line)) - output.append(div) -} -const clean = (line) => line.replaceAll("\n", "") -const sender = pushable() - -const node = await createLibp2p({ - addresses: { - listen: [ - '/webrtc' - ] - }, - transports: [ - webSockets({ - filter: filters.all, - }), - webRTC(), - circuitRelayTransport({ - discoverRelays: 1, - }), - ], - connectionEncryption: [noise()], - streamMuxers: [mplex()], - connectionGater: { - denyDialMultiaddr: () => { - // by default we refuse to dial local addresses from the browser since they - // are usually sent by remote peers broadcasting undialable multiaddrs but - // here we are explicitly connecting to a local node so do not deny dialing - // any discovered address - return false - } - }, - services: { - identify: identifyService() - } -}) - -await node.start() - -// handle the echo protocol -await node.handle("/echo/1.0.0", ({ stream }) => { - pipe( - stream, - async function* (source) { - for await (const buf of source) { - const incoming = toString(buf.subarray()) - appendOutput(`Received message '${clean(incoming)}'`) - yield buf - } - }, - stream - ) -}) - -function updateConnList() { - // Update connections list - const connListEls = node.getConnections() - .map((connection) => { - if (connection.remoteAddr.protoCodes().includes(WEBRTC_CODE)) { - sendSection.style.display = "block" - } - - const el = document.createElement("li") - el.textContent = connection.remoteAddr.toString() - return el - }) - document.getElementById("connections").replaceChildren(...connListEls) -} - -node.addEventListener("connection:open", (event) => { - updateConnList() -}) -node.addEventListener("connection:close", (event) => { - updateConnList() -}) - -node.addEventListener("self:peer:update", (event) => { - // Update multiaddrs list - const multiaddrs = node.getMultiaddrs() - .map((ma) => { - const el = document.createElement("li") - el.textContent = ma.toString() - return el - }) - document.getElementById("multiaddrs").replaceChildren(...multiaddrs) -}) - -const isWebrtc = (ma) => { - return ma.protoCodes().includes(WEBRTC_CODE) -} - -window.connect.onclick = async () => { - const ma = multiaddr(window.peer.value) - appendOutput(`Dialing '${ma}'`) - const connection = await node.dial(ma) - - if (isWebrtc(ma)) { - const outgoing_stream = await connection.newStream(["/echo/1.0.0"]) - pipe(sender, outgoing_stream, async (src) => { - for await (const buf of src) { - const response = toString(buf.subarray()) - appendOutput(`Received message '${clean(response)}'`) - } - }) - } - - appendOutput(`Connected to '${ma}'`) -} - -window.send.onclick = async () => { - const message = `${window.message.value}\n` - appendOutput(`Sending message '${clean(message)}'`) - sender.push(fromString(message)) -} diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/package.json b/examples/libp2p-in-the-browser/webrtc/browser-to-browser/package.json deleted file mode 100644 index 050ca2ce6a..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "js-libp2p-webrtc-private-to-private", - "version": "1.0.0", - "description": "Connect a browser to another browser", - "type": "module", - "scripts": { - "start": "vite", - "build": "vite build", - "relay": "node relay.js", - "test:firefox": "npm run build && playwright test --browser=firefox tests", - "test:chrome": "npm run build && playwright test tests", - "test": "npm run build && test-browser-example tests" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@libp2p/websockets": "^6.0.1", - "@libp2p/mplex": "^8.0.1", - "@libp2p/webrtc": "file:../../", - "@multiformats/multiaddr": "^12.0.0", - "it-pushable": "^3.2.0", - "libp2p": "^0.46.0", - "vite": "^4.2.1" - }, - "devDependencies": { - "test-ipfs-example": "^1.0.0" - } -} diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/relay.js b/examples/libp2p-in-the-browser/webrtc/browser-to-browser/relay.js deleted file mode 100644 index 15754c2bc9..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/relay.js +++ /dev/null @@ -1,26 +0,0 @@ -import { mplex } from "@libp2p/mplex" -import { createLibp2p } from "libp2p" -import { noise } from "@chainsafe/libp2p-noise" -import { circuitRelayServer } from 'libp2p/circuit-relay' -import { webSockets } from '@libp2p/websockets' -import * as filters from '@libp2p/websockets/filters' -import { identifyService } from 'libp2p/identify' - -const server = await createLibp2p({ - addresses: { - listen: ['/ip4/127.0.0.1/tcp/0/ws'] - }, - transports: [ - webSockets({ - filter: filters.all - }), - ], - connectionEncryption: [noise()], - streamMuxers: [mplex()], - services: { - identify: identifyService(), - relay: circuitRelayServer() - } -}) - -console.log("p2p addr: ", server.getMultiaddrs().map((ma) => ma.toString())) diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/tests/test.spec.js b/examples/libp2p-in-the-browser/webrtc/browser-to-browser/tests/test.spec.js deleted file mode 100644 index 703ae688cc..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/tests/test.spec.js +++ /dev/null @@ -1,129 +0,0 @@ -/* eslint-disable no-console */ -import { setup, expect } from 'test-ipfs-example/browser' -import { createLibp2p } from 'libp2p' -import { circuitRelayServer } from 'libp2p/circuit-relay' -import { webSockets } from '@libp2p/websockets' -import * as filters from '@libp2p/websockets/filters' -import { mplex } from '@libp2p/mplex' -import { noise } from '@chainsafe/libp2p-noise' -import { identifyService } from 'libp2p/identify' - -// Setup -const test = setup() - -// DOM -const connectBtn = '#connect' -const connectAddr = '#peer' -const messageInput = '#message' -const sendBtn = '#send' -const output = '#output' -const listeningAddresses = '#multiaddrs' - -let url - -// we spawn a js libp2p relay -async function spawnRelay() { - const relayNode = await createLibp2p({ - addresses: { - listen: ['/ip4/127.0.0.1/tcp/0/ws'] - }, - transports: [ - webSockets({ - filter: filters.all - }), - ], - connectionEncryption: [noise()], - streamMuxers: [mplex()], - services: { - identify: identifyService(), - relay: circuitRelayServer() - } - }) - - const relayNodeAddr = relayNode.getMultiaddrs()[0].toString() - - return { relayNode, relayNodeAddr } -} - -test.describe('browser to browser example:', () => { - let relayNode - let relayNodeAddr - - // eslint-disable-next-line no-empty-pattern - test.beforeAll(async ({ servers }, testInfo) => { - testInfo.setTimeout(5 * 60_000) - const r = await spawnRelay() - relayNode = r.relayNode - relayNodeAddr = r.relayNodeAddr - console.log('Server addr:', relayNodeAddr) - url = servers[0].url - }, {}) - - test.afterAll(() => { - relayNode.stop() - }) - - test.beforeEach(async ({ page }) => { - await page.goto(url) - }) - - test('should connect to a relay node', async ({ page: pageA, context }) => { - // load second page - const pageB = await context.newPage() - await pageB.goto(url) - - // connect both pages to the relay - const relayedAddressA = await dialRelay(pageA, relayNodeAddr) - const relayedAddressB = await dialRelay(pageB, relayNodeAddr) - - // dial first page from second page over relay - await dialPeerOverRelay(pageA, relayedAddressB) - await dialPeerOverRelay(pageB, relayedAddressA) - - // stop the relay - await relayNode.stop() - - await echoMessagePeer(pageB, 'hello B') - - await echoMessagePeer(pageA, 'hello A') - }) -}) - -async function echoMessagePeer (page, message) { - // send the message to the peer over webRTC - await page.fill(messageInput, message) - await page.click(sendBtn) - - // check the message was echoed back - const outputLocator = page.locator(output) - await expect(outputLocator).toContainText(`Sending message '${message}'`) - await expect(outputLocator).toContainText(`Received message '${message}'`) -} - -async function dialRelay (page, address) { - // add the go libp2p multiaddress to the input field and submit - await page.fill(connectAddr, address) - await page.click(connectBtn) - - const outputLocator = page.locator(output) - await expect(outputLocator).toContainText(`Dialing '${address}'`) - await expect(outputLocator).toContainText(`Connected to '${address}'`) - - const multiaddrsLocator = page.locator(listeningAddresses) - await expect(multiaddrsLocator).toHaveText(/webrtc/) - - const multiaddrs = await page.textContent(listeningAddresses) - const addr = multiaddrs.split(address).filter(str => str.includes('webrtc')).pop() - - return address + addr -} - -async function dialPeerOverRelay (page, address) { - // add the go libp2p multiaddr to the input field and submit - await page.fill(connectAddr, address) - await page.click(connectBtn) - - const outputLocator = page.locator(output) - await expect(outputLocator).toContainText(`Dialing '${address}'`) - await expect(outputLocator).toContainText(`Connected to '${address}'`) -} diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/vite.config.js b/examples/libp2p-in-the-browser/webrtc/browser-to-browser/vite.config.js deleted file mode 100644 index 353f32b6ef..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/vite.config.js +++ /dev/null @@ -1,11 +0,0 @@ -export default { - build: { - target: 'es2022' - }, - optimizeDeps: { - esbuildOptions: { target: 'es2022', supported: { bigint: true } } - }, - server: { - open: true - } -} \ No newline at end of file diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-server/README.md b/examples/libp2p-in-the-browser/webrtc/browser-to-server/README.md deleted file mode 100644 index fb3d997503..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-server/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# js-libp2p-webrtc Browser to Server - -This example leverages the [vite bundler](https://vitejs.dev/) to compile and serve the libp2p code in the browser. You can use other bundlers such as Webpack, but we will not be covering them here. - -## Running the Go Server - -To run the Go LibP2P WebRTC server: - -```shell -npm run go-libp2p-server -``` - -Copy the multiaddress in the output. - -## Running the Example - -In a separate console tab, install dependencies and start the Vite server: - -```shell -npm i && npm run start -``` - -The browser window will automatically open. -Using the copied multiaddress from the Go server, paste it into the `Server MultiAddress` input and click the `Connect` button. -Once the peer is connected, click the message section will appear. Enter a message and click the `Send` button. - -The output should look like: - -```text -Dialing /ip4/10.0.1.5/udp/54375/webrtc/certhash/uEiADy8JubdWrAzseyzfXFyCpdRN02eWZg86tjCrTCA5dbQ/p2p/12D3KooWEG7N4bnZfFBNZE7WG6xm2P4Sr6sonMwyD4HCAqApEthb -Peer connected '/ip4/10.0.1.5/udp/54375/webrtc/certhash/uEiADy8JubdWrAzseyzfXFyCpdRN02eWZg86tjCrTCA5dbQ/p2p/12D3KooWEG7N4bnZfFBNZE7WG6xm2P4Sr6sonMwyD4HCAqApEthb' -Sending message 'hello' -Received message 'hello' -``` \ No newline at end of file diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-server/index.html b/examples/libp2p-in-the-browser/webrtc/browser-to-server/index.html deleted file mode 100644 index 24ff11f5bd..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-server/index.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - js-libp2p WebRTC - - - -
      -
      - - - -
      -
      - - - -
      -
      -
      - - - diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-server/index.js b/examples/libp2p-in-the-browser/webrtc/browser-to-server/index.js deleted file mode 100644 index 5b9c14d03c..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-server/index.js +++ /dev/null @@ -1,62 +0,0 @@ -import { createLibp2p } from 'libp2p' -import { noise } from '@chainsafe/libp2p-noise' -import { multiaddr } from '@multiformats/multiaddr' -import { pipe } from "it-pipe"; -import { fromString, toString } from "uint8arrays"; -import { webRTCDirect } from '@libp2p/webrtc' -import { pushable } from 'it-pushable'; - -let stream; -const output = document.getElementById('output') -const sendSection = document.getElementById('send-section') -const appendOutput = (line) => { - const div = document.createElement("div") - div.appendChild(document.createTextNode(line)) - output.append(div) -} -const clean = (line) => line.replaceAll('\n', '') -const sender = pushable() - -const node = await createLibp2p({ - transports: [webRTCDirect()], - connectionEncryption: [noise()], - connectionGater: { - denyDialMultiaddr: () => { - // by default we refuse to dial local addresses from the browser since they - // are usually sent by remote peers broadcasting undialable multiaddrs but - // here we are explicitly connecting to a local node so do not deny dialing - // any discovered address - return false - } - } -}); - -await node.start() - -node.addEventListener('peer:connect', (connection) => { - appendOutput(`Peer connected '${node.getConnections().map(c => c.remoteAddr.toString())}'`) - sendSection.style.display = 'block' -}) - -window.connect.onclick = async () => { - // TODO!!(ckousik): hack until webrtc is renamed in Go. Remove once - // complete - let candidateMa = window.peer.value - candidateMa = candidateMa.replace(/\/webrtc\/certhash/, "/webrtc-direct/certhash") - const ma = multiaddr(candidateMa) - - appendOutput(`Dialing '${ma}'`) - stream = await node.dialProtocol(ma, ['/echo/1.0.0']) - pipe(sender, stream, async (src) => { - for await(const buf of src) { - const response = toString(buf.subarray()) - appendOutput(`Received message '${clean(response)}'`) - } - }) -} - -window.send.onclick = async () => { - const message = `${window.message.value}\n` - appendOutput(`Sending message '${clean(message)}'`) - sender.push(fromString(message)) -} diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-server/package.json b/examples/libp2p-in-the-browser/webrtc/browser-to-server/package.json deleted file mode 100644 index 7abaa793c5..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-server/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "js-libp2p-webrtc-browser-to-server", - "version": "1.0.0", - "description": "Connect a browser to a server", - "type": "module", - "scripts": { - "start": "vite", - "build": "vite build", - "go-libp2p-server": "cd ../go-libp2p-server && go run ./main.go", - "test:chrome": "npm run build && playwright test tests", - "test:firefox": "npm run build && playwright test --browser firefox tests", - "test": "npm run build && test-browser-example tests" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@libp2p/webrtc": "file:../../", - "@multiformats/multiaddr": "^12.0.0", - "it-pushable": "^3.2.0", - "libp2p": "^0.46.0", - "vite": "^4.2.1" - }, - "devDependencies": { - "test-ipfs-example": "^1.0.0" - } -} diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-server/tests/test.spec.js b/examples/libp2p-in-the-browser/webrtc/browser-to-server/tests/test.spec.js deleted file mode 100644 index dcdd25d348..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-server/tests/test.spec.js +++ /dev/null @@ -1,94 +0,0 @@ -/* eslint-disable no-console */ -import { setup, expect } from 'test-ipfs-example/browser' -import { spawn, exec } from 'child_process' -import { existsSync } from 'fs' - -// Setup -const test = setup() - -async function spawnGoLibp2p() { - if (!existsSync('../../examples/go-libp2p-server/go-libp2p-server')) { - await new Promise((resolve, reject) => { - exec('go build', - { cwd: '../../examples/go-libp2p-server' }, - (error, stdout, stderr) => { - if (error) { - throw (`exec error: ${error}`) - } - resolve() - }) - }) - } - - const server = spawn('./go-libp2p-server', [], { cwd: '../../examples/go-libp2p-server', killSignal: 'SIGINT' }) - server.stderr.on('data', (data) => { - console.log(`stderr: ${data}`, typeof data) - }) - const serverAddr = await (new Promise(resolve => { - server.stdout.on('data', (data) => { - console.log(`stdout: ${data}`, typeof data) - const addr = String(data).match(/p2p addr: ([^\s]*)/) - if (addr !== null && addr.length > 0) { - resolve(addr[1]) - } - }) - })) - return { server, serverAddr } -} - -test.describe('bundle ipfs with parceljs:', () => { - // DOM - const connectBtn = '#connect' - const connectAddr = '#peer' - const messageInput = '#message' - const sendBtn = '#send' - const output = '#output' - - let server - let serverAddr - - // eslint-disable-next-line no-empty-pattern - test.beforeAll(async ({ }, testInfo) => { - testInfo.setTimeout(5 * 60_000) - const s = await spawnGoLibp2p() - server = s.server - serverAddr = s.serverAddr - console.log('Server addr:', serverAddr) - }, {}) - - test.afterAll(() => { - server.kill('SIGINT') - }) - - test.beforeEach(async ({ servers, page }) => { - await page.goto(servers[0].url) - }) - - test('should connect to a go-libp2p node over webrtc', async ({ page }) => { - const message = 'hello' - - // add the go libp2p multiaddress to the input field and submit - await page.fill(connectAddr, serverAddr) - await page.click(connectBtn) - - // send the relay message to the go libp2p server - await page.fill(messageInput, message) - await page.click(sendBtn) - - await page.waitForSelector('#output:has(div)') - - // Expected output: - // - // Dialing '${serverAddr}' - // Peer connected '${serverAddr}' - // Sending message '${message}' - // Received message '${message}' - const connections = await page.textContent(output) - - expect(connections).toContain(`Dialing '${serverAddr}'`) - expect(connections).toContain(`Peer connected '${serverAddr}'`) - - expect(connections).toContain(`Sending message '${message}'`) - expect(connections).toContain(`Received message '${message}'`) - }) -}) diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-server/vite.config.js b/examples/libp2p-in-the-browser/webrtc/browser-to-server/vite.config.js deleted file mode 100644 index 9b2e2a7b1f..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-server/vite.config.js +++ /dev/null @@ -1,8 +0,0 @@ -export default { - build: { - target: 'es2022' - }, - optimizeDeps: { - esbuildOptions: { target: 'es2022', supported: { bigint: true } } - }, -} \ No newline at end of file diff --git a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/.gitignore b/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/.gitignore deleted file mode 100644 index baadac2c80..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/.gitignore +++ /dev/null @@ -1 +0,0 @@ -go-libp2p-server \ No newline at end of file diff --git a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.mod b/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.mod deleted file mode 100644 index 1a1a228601..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.mod +++ /dev/null @@ -1,117 +0,0 @@ -module github.com/libp2p/js-libp2p-webrtc/examples/go-libp2p-server - -go 1.18 - -// TODO: Remove this once webrtc is merged into Go libp2p -replace github.com/libp2p/go-libp2p => github.com/libp2p/go-libp2p v0.26.1-0.20230404184453-257fbfba50c3 - -require github.com/libp2p/go-libp2p v0.26.3 - -require ( - github.com/benbjohnson/clock v1.3.0 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/containerd/cgroups v1.1.0 // indirect - github.com/coreos/go-systemd/v22 v22.5.0 // indirect - github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/elastic/gosigar v0.14.2 // indirect - github.com/flynn/noise v1.0.0 // indirect - github.com/francoispqt/gojay v1.2.13 // indirect - github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect - github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/mock v1.6.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/google/gopacket v1.1.19 // indirect - github.com/google/pprof v0.0.0-20230309165930-d61513b1440d // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/huin/goupnp v1.1.0 // indirect - github.com/ipfs/go-cid v0.4.1 // indirect - github.com/ipfs/go-log/v2 v2.5.1 // indirect - github.com/jackpal/go-nat-pmp v1.0.2 // indirect - github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect - github.com/klauspost/compress v1.16.3 // indirect - github.com/klauspost/cpuid/v2 v2.2.4 // indirect - github.com/koron/go-ssdp v0.0.4 // indirect - github.com/libp2p/go-buffer-pool v0.1.0 // indirect - github.com/libp2p/go-cidranger v1.1.0 // indirect - github.com/libp2p/go-flow-metrics v0.1.0 // indirect - github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect - github.com/libp2p/go-msgio v0.3.0 // indirect - github.com/libp2p/go-nat v0.1.0 // indirect - github.com/libp2p/go-netroute v0.2.1 // indirect - github.com/libp2p/go-reuseport v0.2.0 // indirect - github.com/libp2p/go-yamux/v4 v4.0.0 // indirect - github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect - github.com/mattn/go-isatty v0.0.17 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/miekg/dns v1.1.52 // indirect - github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect - github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect - github.com/minio/sha256-simd v1.0.0 // indirect - github.com/mr-tron/base58 v1.2.0 // indirect - github.com/multiformats/go-base32 v0.1.0 // indirect - github.com/multiformats/go-base36 v0.2.0 // indirect - github.com/multiformats/go-multiaddr v0.9.0 // indirect - github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect - github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect - github.com/multiformats/go-multibase v0.2.0 // indirect - github.com/multiformats/go-multicodec v0.8.1 // indirect - github.com/multiformats/go-multihash v0.2.1 // indirect - github.com/multiformats/go-multistream v0.4.1 // indirect - github.com/multiformats/go-varint v0.0.7 // indirect - github.com/onsi/ginkgo/v2 v2.9.1 // indirect - github.com/opencontainers/runtime-spec v1.0.2 // indirect - github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect - github.com/pion/datachannel v1.5.5 // indirect - github.com/pion/dtls/v2 v2.2.4 // indirect - github.com/pion/ice/v2 v2.2.13 // indirect - github.com/pion/interceptor v0.1.12 // indirect - github.com/pion/logging v0.2.2 // indirect - github.com/pion/mdns v0.0.5 // indirect - github.com/pion/randutil v0.1.0 // indirect - github.com/pion/rtcp v1.2.10 // indirect - github.com/pion/rtp v1.7.13 // indirect - github.com/pion/sctp v1.8.6 // indirect - github.com/pion/sdp/v3 v3.0.6 // indirect - github.com/pion/srtp/v2 v2.0.11 // indirect - github.com/pion/stun v0.4.0 // indirect - github.com/pion/transport v0.14.1 // indirect - github.com/pion/transport/v2 v2.0.0 // indirect - github.com/pion/turn/v2 v2.0.9 // indirect - github.com/pion/udp v0.1.4 // indirect - github.com/pion/webrtc/v3 v3.1.51 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.14.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.42.0 // indirect - github.com/prometheus/procfs v0.9.0 // indirect - github.com/quic-go/qpack v0.4.0 // indirect - github.com/quic-go/qtls-go1-19 v0.2.1 // indirect - github.com/quic-go/qtls-go1-20 v0.1.1 // indirect - github.com/quic-go/quic-go v0.33.0 // indirect - github.com/quic-go/webtransport-go v0.5.2 // indirect - github.com/raulk/go-watchdog v1.3.0 // indirect - github.com/rogpeppe/go-internal v1.9.0 // indirect - github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/stretchr/testify v1.8.2 // indirect - go.uber.org/atomic v1.10.0 // indirect - go.uber.org/dig v1.16.1 // indirect - go.uber.org/fx v1.19.2 // indirect - go.uber.org/multierr v1.10.0 // indirect - go.uber.org/zap v1.24.0 // indirect - golang.org/x/crypto v0.7.0 // indirect - golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect - golang.org/x/mod v0.9.0 // indirect - golang.org/x/net v0.8.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.7.0 // indirect - golang.org/x/text v0.8.0 // indirect - golang.org/x/tools v0.7.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect - lukechampine.com/blake3 v1.1.7 // indirect - nhooyr.io/websocket v1.8.7 // indirect -) diff --git a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.sum b/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.sum deleted file mode 100644 index 9a3080ca00..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.sum +++ /dev/null @@ -1,637 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= -dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= -dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= -dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= -dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= -git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= -github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= -github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= -github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= -github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= -github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4= -github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= -github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= -github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= -github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= -github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= -github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= -github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= -github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= -github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= -github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= -github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= -github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20230309165930-d61513b1440d h1:um9/pc7tKMINFfP1eE7Wv6PRGXlcCSJkVajF7KJw3uQ= -github.com/google/pprof v0.0.0-20230309165930-d61513b1440d/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= -github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= -github.com/huin/goupnp v1.1.0 h1:gEe0Dp/lZmPZiDFzJJaOfUpOvv2MKUkoBX8lDrn9vKU= -github.com/huin/goupnp v1.1.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= -github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= -github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= -github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= -github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= -github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY= -github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= -github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= -github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= -github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= -github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= -github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= -github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= -github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= -github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= -github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= -github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= -github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= -github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= -github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= -github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro= -github.com/libp2p/go-libp2p v0.26.1-0.20230404184453-257fbfba50c3 h1:PbtmtrIDY1Us9qeGJdHO1nfp0Jik1KZIP64/KYK43YI= -github.com/libp2p/go-libp2p v0.26.1-0.20230404184453-257fbfba50c3/go.mod h1:PwdLfPiWNhYkb96Wqc2uDFd/+0SGE07/IvjAoFiYG70= -github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s= -github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w= -github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= -github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= -github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= -github.com/libp2p/go-nat v0.1.0 h1:MfVsH6DLcpa04Xr+p8hmVRG4juse0s3J8HyNWYHffXg= -github.com/libp2p/go-nat v0.1.0/go.mod h1:X7teVkwRHNInVNWQiO/tAiAVRwSr5zoRz4YSTC3uRBM= -github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= -github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU= -github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ= -github.com/libp2p/go-reuseport v0.2.0 h1:18PRvIMlpY6ZK85nIAicSBuXXvrYoSw3dsBAR7zc560= -github.com/libp2p/go-reuseport v0.2.0/go.mod h1:bvVho6eLMm6Bz5hmU0LYN3ixd3nPPvtIlaURZZgOY4k= -github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= -github.com/libp2p/go-yamux/v4 v4.0.0 h1:+Y80dV2Yx/kv7Y7JKu0LECyVdMXm1VUoko+VQ9rBfZQ= -github.com/libp2p/go-yamux/v4 v4.0.0/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4= -github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= -github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= -github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.52 h1:Bmlc/qsNNULOe6bpXcUTsuOajd0DzRHwup6D9k1An0c= -github.com/miekg/dns v1.1.52/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= -github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= -github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= -github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= -github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= -github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= -github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= -github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= -github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= -github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= -github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= -github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= -github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= -github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= -github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= -github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= -github.com/multiformats/go-multiaddr v0.9.0 h1:3h4V1LHIk5w4hJHekMKWALPXErDfz/sggzwC/NcqbDQ= -github.com/multiformats/go-multiaddr v0.9.0/go.mod h1:mI67Lb1EeTOYb8GQfL/7wpIZwc46ElrvzhYnoJOmTT0= -github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= -github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= -github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= -github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= -github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= -github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= -github.com/multiformats/go-multicodec v0.8.1 h1:ycepHwavHafh3grIbR1jIXnKCsFm0fqsfEOsJ8NtKE8= -github.com/multiformats/go-multicodec v0.8.1/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k= -github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= -github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108= -github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= -github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo= -github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q= -github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= -github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= -github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.9.1 h1:zie5Ly042PD3bsCvsSOPvRnFwyo3rKe64TJlD6nu0mk= -github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.27.3 h1:5VwIwnBY3vbBDOJrNtA4rVdiTZCsq9B5F12pvy1Drmk= -github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= -github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= -github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= -github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= -github.com/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew8= -github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V118yimL0= -github.com/pion/dtls/v2 v2.1.5/go.mod h1:BqCE7xPZbPSubGasRoDFJeTsyJtdD1FanJYL0JGheqY= -github.com/pion/dtls/v2 v2.2.4 h1:YSfYwDQgrxMYXLBc/m7PFY5BVtWlNm/DN4qoU2CbcWg= -github.com/pion/dtls/v2 v2.2.4/go.mod h1:WGKfxqhrddne4Kg3p11FUMJrynkOY4lb25zHNO49wuw= -github.com/pion/ice/v2 v2.2.13 h1:NvLtzwcyob6wXgFqLmVQbGB3s9zzWmOegNMKYig5l9M= -github.com/pion/ice/v2 v2.2.13/go.mod h1:eFO4/1zCI+a3OFVt7l7kP+5jWCuZo8FwU2UwEa3+164= -github.com/pion/interceptor v0.1.11/go.mod h1:tbtKjZY14awXd7Bq0mmWvgtHB5MDaRN7HV3OZ/uy7s8= -github.com/pion/interceptor v0.1.12 h1:CslaNriCFUItiXS5o+hh5lpL0t0ytQkFnUcbbCs2Zq8= -github.com/pion/interceptor v0.1.12/go.mod h1:bDtgAD9dRkBZpWHGKaoKb42FhDHTG2rX8Ii9LRALLVA= -github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= -github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= -github.com/pion/mdns v0.0.5 h1:Q2oj/JB3NqfzY9xGZ1fPzZzK7sDSD8rZPOvcIQ10BCw= -github.com/pion/mdns v0.0.5/go.mod h1:UgssrvdD3mxpi8tMxAXbsppL3vJ4Jipw1mTCW+al01g= -github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= -github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= -github.com/pion/rtcp v1.2.9/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo= -github.com/pion/rtcp v1.2.10 h1:nkr3uj+8Sp97zyItdN60tE/S6vk4al5CPRR6Gejsdjc= -github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL1I= -github.com/pion/rtp v1.7.13 h1:qcHwlmtiI50t1XivvoawdCGTP4Uiypzfrsap+bijcoA= -github.com/pion/rtp v1.7.13/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= -github.com/pion/sctp v1.8.5/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0= -github.com/pion/sctp v1.8.6 h1:CUex11Vkt9YS++VhLf8b55O3VqKrWL6W3SDwX4jAqsI= -github.com/pion/sctp v1.8.6/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0= -github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw= -github.com/pion/sdp/v3 v3.0.6/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw= -github.com/pion/srtp/v2 v2.0.11 h1:6cEEgT1oCLWgE+BynbfaSMAxtsqU0M096x9dNH6olY0= -github.com/pion/srtp/v2 v2.0.11/go.mod h1:vzHprzbuVoYJ9NfaRMycnFrkHcLSaLVuBZDOtFQNZjY= -github.com/pion/stun v0.3.5/go.mod h1:gDMim+47EeEtfWogA37n6qXZS88L5V6LqFcf+DZA2UA= -github.com/pion/stun v0.4.0 h1:vgRrbBE2htWHy7l3Zsxckk7rkjnjOsSM7PHZnBwo8rk= -github.com/pion/stun v0.4.0/go.mod h1:QPsh1/SbXASntw3zkkrIk3ZJVKz4saBY2G7S10P3wCw= -github.com/pion/transport v0.12.2/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q= -github.com/pion/transport v0.13.0/go.mod h1:yxm9uXpK9bpBBWkITk13cLo1y5/ur5VQpG22ny6EP7g= -github.com/pion/transport v0.13.1/go.mod h1:EBxbqzyv+ZrmDb82XswEE0BjfQFtuw1Nu6sjnjWCsGg= -github.com/pion/transport v0.14.1 h1:XSM6olwW+o8J4SCmOBb/BpwZypkHeyM0PGFCxNQBr40= -github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99Jn2fNnI= -github.com/pion/transport/v2 v2.0.0 h1:bsMYyqHCbkvHwj+eNCFBuxtlKndKfyGI2vaQmM3fIE4= -github.com/pion/transport/v2 v2.0.0/go.mod h1:HS2MEBJTwD+1ZI2eSXSvHJx/HnzQqRy2/LXxt6eVMHc= -github.com/pion/turn/v2 v2.0.9 h1:jcDPw0Vfd5I4iTc7s0Upfc2aMnyu2lgJ9vV0SUrNC1o= -github.com/pion/turn/v2 v2.0.9/go.mod h1:DQlwUwx7hL8Xya6TTAabbd9DdKXTNR96Xf5g5Qqso/M= -github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M= -github.com/pion/udp v0.1.4 h1:OowsTmu1Od3sD6i3fQUJxJn2fEvJO6L1TidgadtbTI8= -github.com/pion/udp v0.1.4/go.mod h1:G8LDo56HsFwC24LIcnT4YIDU5qcB6NepqqjP0keL2us= -github.com/pion/webrtc/v3 v3.1.51 h1:uU9vHdY63O3uRFJiDskH0qFJ+219bAH28qOt5csSWcM= -github.com/pion/webrtc/v3 v3.1.51/go.mod h1:sbRNshM9l0zRDQgZRP9K5RTzlsdBmqmyO8KbxngG8jQ= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= -github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= -github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= -github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= -github.com/quic-go/qtls-go1-19 v0.2.1 h1:aJcKNMkH5ASEJB9FXNeZCyTEIHU1J7MmHyz1Q1TSG1A= -github.com/quic-go/qtls-go1-19 v0.2.1/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= -github.com/quic-go/qtls-go1-20 v0.1.1 h1:KbChDlg82d3IHqaj2bn6GfKRj84Per2VGf5XV3wSwQk= -github.com/quic-go/qtls-go1-20 v0.1.1/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= -github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y0= -github.com/quic-go/quic-go v0.33.0/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA= -github.com/quic-go/webtransport-go v0.5.2 h1:GA6Bl6oZY+g/flt00Pnu0XtivSD8vukOu3lYhJjnGEk= -github.com/quic-go/webtransport-go v0.5.2/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU= -github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= -github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= -github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= -github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= -github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= -github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= -github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= -github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= -github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= -github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= -github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= -github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= -github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= -github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= -github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= -github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= -github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= -github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= -github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= -github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= -github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= -github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/dig v1.16.1 h1:+alNIBsl0qfY0j6epRubp/9obgtrObRAc5aD+6jbWY8= -go.uber.org/dig v1.16.1/go.mod h1:557JTAUZT5bUK0SvCwikmLPPtdQhfvLYtO5tJgQSbnk= -go.uber.org/fx v1.19.2 h1:SyFgYQFr1Wl0AYstE8vyYIzP4bFz2URrScjwC4cwUvY= -go.uber.org/fx v1.19.2/go.mod h1:43G1VcqSzbIv77y00p1DRAsyZS8WdzuYdhZXmEUkMyQ= -go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= -go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= -golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= -golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20221010152910-d6f0a8c073c2/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220531201128-c960675eff93/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= -google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= -lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= -nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= -nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= -sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/main.go b/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/main.go deleted file mode 100644 index a5f99e6f25..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/main.go +++ /dev/null @@ -1,95 +0,0 @@ -package main - -import ( - "bufio" - "fmt" - "log" - "net" - "os" - "os/signal" - "syscall" - - "github.com/libp2p/go-libp2p" - "github.com/libp2p/go-libp2p/core/host" - "github.com/libp2p/go-libp2p/core/network" - "github.com/libp2p/go-libp2p/core/peer" - webrtc "github.com/libp2p/go-libp2p/p2p/transport/webrtc" -) - -var listenerIp = net.IPv4(127, 0, 0, 1) - -func init() { - ifaces, err := net.Interfaces() - if err != nil { - return - } - for _, iface := range ifaces { - if iface.Flags&net.FlagUp == 0 { - continue - } - addrs, err := iface.Addrs() - if err != nil { - return - } - for _, addr := range addrs { - // bind to private non-loopback ip - if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.IsPrivate() { - if ipnet.IP.To4() != nil { - listenerIp = ipnet.IP.To4() - return - } - } - } - } -} - -func echoHandler(stream network.Stream) { - for { - reader := bufio.NewReader(stream) - str, err := reader.ReadString('\n') - log.Printf("err: %s", err) - if err != nil { - return - } - log.Printf("echo: %s", str) - _, err = stream.Write([]byte(str)) - if err != nil { - log.Printf("err: %v", err) - return - } - } -} - -func main() { - host := createHost() - host.SetStreamHandler("/echo/1.0.0", echoHandler) - defer host.Close() - remoteInfo := peer.AddrInfo{ - ID: host.ID(), - Addrs: host.Network().ListenAddresses(), - } - - remoteAddrs, _ := peer.AddrInfoToP2pAddrs(&remoteInfo) - fmt.Println("p2p addr: ", remoteAddrs[0]) - - fmt.Println("press Ctrl+C to quit") - ch := make(chan os.Signal, 1) - signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT) - <-ch -} - -func createHost() host.Host { - h, err := libp2p.New( - libp2p.Transport(webrtc.New), - libp2p.ListenAddrStrings( - fmt.Sprintf("/ip4/%s/udp/0/webrtc-direct", listenerIp), - ), - libp2p.DisableRelay(), - libp2p.Ping(true), - ) - if err != nil { - panic(err) - } - - return h -} diff --git a/examples/libp2p-in-the-browser/websockets/LICENSE b/examples/libp2p-in-the-browser/websockets/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/libp2p-in-the-browser/websockets/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/libp2p-in-the-browser/websockets/LICENSE-APACHE b/examples/libp2p-in-the-browser/websockets/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/libp2p-in-the-browser/websockets/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/libp2p-in-the-browser/websockets/LICENSE-MIT b/examples/libp2p-in-the-browser/websockets/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/libp2p-in-the-browser/websockets/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/libp2p-in-the-browser/websockets/README.md b/examples/libp2p-in-the-browser/websockets/README.md deleted file mode 100644 index 427409863c..0000000000 --- a/examples/libp2p-in-the-browser/websockets/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# @libp2p/example-libp2p-in-the-browser - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> A libp2p node running in the browser - -## Table of contents - -- [Setup](#setup) -- [Running the examples](#running-the-examples) -- [License](#license) -- [Contribution](#contribution) - -## Setup - -In order to run the example: - -- Install dependencey at the root of the js-libp2p repository (if not already done), -- then, install the dependencies from same directory as this README: - - - - npm install - npm run build - cd ./examples/libp2p-in-the-browser - npm install - -## Running the examples - -Start by running the vite server: - - npm start - -The output should look something like this: - -```log -$ npm start - -> libp2p-in-browser@1.0.0 start -> vite index.html - -Server running at http://localhost:1234 -✨ Built in 1000ms. -``` - -This will compile the code and start a server listening on port . Now open your browser to `http://localhost:1234`. You should see a log of your node's Peer ID, the discovered peers from the Bootstrap module, and connections to those peers as they are created. - -Now, if you open a second browser tab to `http://localhost:1234`, you should discover your node from the previous tab. - -**Note**: In the example we assign libp2p to `window.libp2p`, in case you would like to play around with the API directly in the browser. You can of course make changes to `index.js` and vite will automatically rebuild and reload the browser tabs. - - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/libp2p-in-the-browser/websockets/index.html b/examples/libp2p-in-the-browser/websockets/index.html deleted file mode 100644 index 2a1fbe7820..0000000000 --- a/examples/libp2p-in-the-browser/websockets/index.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - js-libp2p vite browser example - - - -
      -

      Starting libp2p...

      -
      - -
      -
      
      -    
      - - - - - - \ No newline at end of file diff --git a/examples/libp2p-in-the-browser/websockets/index.js b/examples/libp2p-in-the-browser/websockets/index.js deleted file mode 100644 index 28ea0a93bd..0000000000 --- a/examples/libp2p-in-the-browser/websockets/index.js +++ /dev/null @@ -1,92 +0,0 @@ -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { bootstrap } from '@libp2p/bootstrap' -import { kadDHT } from '@libp2p/kad-dht' -import { webRTCDirect, webRTC } from '@libp2p/webrtc' -import { webSockets } from '@libp2p/websockets' -import { webTransport } from '@libp2p/webtransport' -import { createLibp2p } from 'libp2p' -import { circuitRelayTransport } from 'libp2p/circuit-relay' -import { identifyService } from 'libp2p/identify' - -document.addEventListener('DOMContentLoaded', async () => { - // Create our libp2p node - const libp2p = await createLibp2p({ - // transports allow us to dial peers that support certain types of addresses - transports: [ - webSockets(), - webTransport(), - webRTC(), - webRTCDirect(), - circuitRelayTransport({ - // use content routing to find a circuit relay server we can reserve a - // slot on - discoverRelays: 1 - }) - ], - connectionEncryption: [noise()], - streamMuxers: [yamux()], - peerDiscovery: [ - bootstrap({ - list: [ - '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt' - ] - }) - ], - services: { - // the identify service is used by the DHT and the circuit relay transport - // to find peers that support the relevant protocols - identify: identifyService(), - - // the DHT is used to find circuit relay servers we can reserve a slot on - dht: kadDHT({ - // browser node ordinarily shouldn't be DHT servers - clientMode: true - }) - } - }) - - // UI elements - const status = document.getElementById('status') - const output = document.getElementById('output') - - output.textContent = '' - - function log (txt) { - console.info(txt) - output.textContent += `${txt.trim()}\n` - } - - // Listen for new peers - libp2p.addEventListener('peer:discovery', (evt) => { - const peerInfo = evt.detail - log(`Found peer ${peerInfo.id.toString()}`) - - // dial them when we discover them - libp2p.dial(peerInfo.id).catch(err => { - log(`Could not dial ${peerInfo.id.toString()}`, err) - }) - }) - - // Listen for new connections to peers - libp2p.addEventListener('peer:connect', (evt) => { - const peerId = evt.detail - log(`Connected to ${peerId.toString()}`) - }) - - // Listen for peers disconnecting - libp2p.addEventListener('peer:disconnect', (evt) => { - const peerId = evt.detail - log(`Disconnected from ${peerId.toString()}`) - }) - - status.innerText = 'libp2p started!' - log(`libp2p id is ${libp2p.peerId.toString()}`) - - // Export libp2p to the window so you can play with the API - window.libp2p = libp2p -}) diff --git a/examples/libp2p-in-the-browser/websockets/package.json b/examples/libp2p-in-the-browser/websockets/package.json deleted file mode 100644 index e42fa7b487..0000000000 --- a/examples/libp2p-in-the-browser/websockets/package.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "name": "@libp2p/example-libp2p-in-the-browser", - "version": "1.0.0", - "description": "A libp2p node running in the browser", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/libp2p-in-the-browser#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "start": "vite", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-gossipsub": "^10.0.0", - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/bootstrap": "^9.0.0", - "@libp2p/kad-dht": "^10.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/webrtc": "^3.0.0", - "@libp2p/websockets": "^7.0.0", - "@libp2p/webtransport": "^3.0.0", - "libp2p": "^0.46.0" - }, - "devDependencies": { - "aegir": "^40.0.1", - "execa": "^7.1.1", - "playwright": "^1.35.1", - "vite": "^2.8.6" - }, - "private": true -} diff --git a/examples/libp2p-in-the-browser/websockets/test.js b/examples/libp2p-in-the-browser/websockets/test.js deleted file mode 100644 index 4e639cc419..0000000000 --- a/examples/libp2p-in-the-browser/websockets/test.js +++ /dev/null @@ -1,40 +0,0 @@ -/* eslint-disable no-console */ - -import path from 'path' -import { fileURLToPath } from 'url' -import { execa } from 'execa' -import { chromium } from 'playwright' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -const url = 'http://localhost:3000' - -const proc = execa('vite', [], { - preferLocal: true, - localDir: __dirname, - cwd: __dirname, - all: true -}) - -proc.all.on('data', async (chunk) => { - /** @type {string} */ - const out = chunk.toString() - - if (out.includes('ready in')) { - try { - const browser = await chromium.launch() - const page = await browser.newPage() - await page.goto(url) - await page.waitForFunction(selector => document.querySelector(selector).innerText === 'libp2p started!', '#status') - await page.waitForFunction(selector => document.querySelector(selector).innerText.includes('libp2p id is'), '#output') - await page.waitForFunction(selector => document.querySelector(selector).innerText.includes('Found peer'), '#output') - await page.waitForFunction(selector => document.querySelector(selector).innerText.includes('Connected to'), '#output') - await browser.close() - } catch (err) { - console.error(err) - process.exit(1) - } finally { - proc.cancel() - } - } -}) diff --git a/examples/libp2p-in-the-browser/websockets/vite.config.js b/examples/libp2p-in-the-browser/websockets/vite.config.js deleted file mode 100644 index b40b89518d..0000000000 --- a/examples/libp2p-in-the-browser/websockets/vite.config.js +++ /dev/null @@ -1,5 +0,0 @@ -export default { - build: { - target: 'es2020' - } -} diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/.gitignore b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/.gitignore deleted file mode 100644 index a547bf36d8..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/README.md b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/README.md deleted file mode 100644 index c02db34408..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/README.md +++ /dev/null @@ -1,121 +0,0 @@ -

      - - IPFS in JavaScript logo - -

      - -

      js-libp2p with WebTransport

      - -

      - js-libp2p using WebTransport! -
      -
      - -
      - Explore the docs - · - Report Bug - · - Request Feature/Example -

      - -## Table of Contents - -- [About The Project](#about-the-project) -- [Getting Started](#getting-started) - - [Prerequisites](#prerequisites) - - [Installation and Running example](#installation-and-running-example) -- [Usage](#usage) -- [References](#references) -- [Documentation](#documentation) -- [Contributing](#contributing) -- [Want to hack on IPFS?](#want-to-hack-on-ipfs) - -## About The Project - -- Read the [docs](https://github.com/ipfs/js-ipfs/tree/master/docs) -- Look into other [examples](https://github.com/ipfs-examples/js-ipfs-examples) to learn how to spawn an IPFS node in Node.js and in the Browser -- Consult the [Core API docs](https://github.com/ipfs/js-ipfs/tree/master/docs/core-api) to see what you can do with an IPFS node -- Visit https://dweb-primer.ipfs.io to learn about IPFS and the concepts that underpin it -- Head over to https://proto.school to take interactive tutorials that cover core IPFS APIs -- Check out https://docs.ipfs.io for tips, how-tos and more -- See https://blog.ipfs.io for news and more -- Need help? Please ask 'How do I?' questions on https://discuss.ipfs.io - -## Getting Started - -### Prerequisites - -Make sure you have installed all of the following prerequisites on your development machine: - -- Git - [Download & Install Git](https://git-scm.com/downloads). OSX and Linux machines typically have this already installed. -- Node.js - [Download & Install Node.js](https://nodejs.org/en/download/) and the npm package manager. - -### Installation and Running example - -**Pre-requisite**: Because this example is in a subfolder of @libp2p/webtransport, if you are running the example inside https://github.com/libp2p/js-libp2p-webtransport, you must build at the root first. If you are running the code outside of https://github.com/libp2p/js-libp2p-webtransport, you must run `npm install --save @libp2p/webtransport` first. - -```console -> npm install -> npm start -``` - -Now open your browser at `http://localhost:8888` - -## Usage - -In this example, you will find a boilerplate you can use to guide yourself into bundling js-ipfs with [browserify](http://browserify.org/), so that you can use it in your own web app! - -You should see the following: - -![](./img/img1.png) -![](./img/img2.png) - -This example demonstrates the `Regular API`, top-level API for add, cat, get and ls Files on IPFS - -_For more examples, please refer to the [Documentation](#documentation)_ - -## References - -- Documentation: - - [IPFS CONFIG](https://github.com/ipfs/js-ipfs/blob/master/docs/CONFIG.md) - - [MISCELLANEOUS](https://github.com/ipfs/js-ipfs/blob/master/docs/core-api/MISCELLANEOUS.md) - - [FILES](https://github.com/ipfs/js-ipfs/blob/master/docs/core-api/FILES.md) -- Tutorials: - - [MFS API](https://proto.school/mutable-file-system) - - [Regular File API](https://proto.school/regular-files-api) - -## Documentation - -- [Config](https://docs.ipfs.io/) -- [Core API](https://github.com/ipfs/js-ipfs/tree/master/docs/core-api) -- [Examples](https://github.com/ipfs-examples/js-ipfs-examples) -- [Development](https://github.com/ipfs/js-ipfs/blob/master/docs/DEVELOPMENT.md) -- [Tutorials](https://proto.school) - -## Contributing - -Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. - -1. Fork the IPFS Project -2. Create your Feature Branch (`git checkout -b feature/amazing-feature`) -3. Commit your Changes (`git commit -a -m 'feat: add some amazing feature'`) -4. Push to the Branch (`git push origin feature/amazing-feature`) -5. Open a Pull Request - -## Want to hack on IPFS? - -[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md) - -The IPFS implementation in JavaScript needs your help! There are a few things you can do right now to help out: - -Read the [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md) and [JavaScript Contributing Guidelines](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md). - -- **Check out existing issues** The [issue list](https://github.com/ipfs/js-ipfs/issues) has many that are marked as ['help wanted'](https://github.com/ipfs/js-ipfs/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22help+wanted%22) or ['difficulty:easy'](https://github.com/ipfs/js-ipfs/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Adifficulty%3Aeasy) which make great starting points for development, many of which can be tackled with no prior IPFS knowledge -- **Look at the [IPFS Roadmap](https://github.com/ipfs/roadmap)** This are the high priority items being worked on right now -- **Perform code reviews** More eyes will help - a. speed the project along - b. ensure quality, and - c. reduce possible future bugs. -- **Add tests**. There can never be enough tests. -- **Join the [Weekly Core Implementations Call](https://github.com/ipfs/team-mgmt/issues/992)** it's where everyone discusses what's going on with IPFS and what's next diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/img/img1.png b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/img/img1.png deleted file mode 100644 index 6460e27446..0000000000 Binary files a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/img/img1.png and /dev/null differ diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/img/img2.png b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/img/img2.png deleted file mode 100644 index d04212d2d7..0000000000 Binary files a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/img/img2.png and /dev/null differ diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/index.html b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/index.html deleted file mode 100644 index 99e6e29be8..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/index.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - js-libp2p WebTransport - - - -
      -
      -

      Connect to (multiaddr with p2p):

      - - -
      - - -
      - - -
      - -
      - - - - \ No newline at end of file diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/package.json b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/package.json deleted file mode 100644 index 139ddfa1c3..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "fetch-file-from-kubo", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "start": "vite", - "build": "tsc && vite build", - "preview": "vite preview", - "test": "npm run build && test-browser-example tests" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.1", - "@libp2p/webtransport": "../..", - "@multiformats/multiaddr": "^12.1.2", - "blockstore-core": "^4.1.0", - "ipfs-bitswap": "^18.0.1", - "libp2p": "^0.46.0", - "multiformats": "^12.0.1" - }, - "devDependencies": { - "test-ipfs-example": "^1.0.0", - "typescript": "^4.6.4", - "vite": "^3.1.0" - } -} diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/libp2p.ts b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/libp2p.ts deleted file mode 100644 index 3d97d38243..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/libp2p.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { webTransport } from '@libp2p/webtransport' -import { noise } from '@chainsafe/libp2p-noise' -import { createLibp2p, Libp2p } from 'libp2p' -import { createBitswap } from 'ipfs-bitswap' -import { MemoryBlockstore } from 'blockstore-core/memory' - -type Bitswap = ReturnType - -export async function setup (): Promise<{ libp2p: Libp2p, bitswap: Bitswap }> { - const store = new MemoryBlockstore() - - const node = await createLibp2p({ - transports: [webTransport()], - connectionEncryption: [noise()], - // this is only necessary when dialing local addresses - connectionGater: { - denyDialMultiaddr: async () => false - } - }) - - await node.start() - - const bitswap = createBitswap(node, store) - await bitswap.start() - - return { libp2p: node, bitswap } -} diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/main.ts b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/main.ts deleted file mode 100644 index e2279bdf4c..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/main.ts +++ /dev/null @@ -1,64 +0,0 @@ -import './style.css' -import { multiaddr } from '@multiformats/multiaddr' -import { setup as libp2pSetup } from './libp2p' -import { CID } from 'multiformats/cid' - -localStorage.debug = '*' - -declare global { - interface Window { - fetchBtn: HTMLButtonElement - connectBtn: HTMLButtonElement - peerInput: HTMLInputElement - cidInput: HTMLInputElement - statusEl: HTMLParagraphElement - downloadEl: HTMLAnchorElement - downloadCidWrapperEl: HTMLDivElement - connlistWrapperEl: HTMLDivElement - connlistEl: HTMLUListElement - } -} - -(async function () { - const { libp2p, bitswap } = await libp2pSetup() - window.connectBtn.onclick = async () => { - const ma = multiaddr(window.peerInput.value) - await libp2p.dial(ma) - } - - libp2p.addEventListener('peer:connect', (_connection) => { - updateConnList() - }) - libp2p.addEventListener('peer:disconnect', (_connection) => { - updateConnList() - }) - - function updateConnList () { - const addrs = libp2p.getConnections().map(c => c.remoteAddr.toString()) - if (addrs.length > 0) { - window.downloadCidWrapperEl.hidden = false - window.connlistWrapperEl.hidden = false - window.connlistEl.innerHTML = '' - addrs.forEach(a => { - const li = document.createElement('li') - li.innerText = a - window.connlistEl.appendChild(li) - }) - } else { - window.downloadCidWrapperEl.hidden = true - window.connlistWrapperEl.hidden = true - window.connlistEl.innerHTML = '' - } - } - - window.fetchBtn.onclick = async () => { - const c = CID.parse(window.cidInput.value) - window.statusEl.hidden = false - const val = await bitswap.want(c) - window.statusEl.hidden = true - - window.downloadEl.href = window.URL.createObjectURL(new Blob([val], { type: 'bytes' })) - window.downloadEl.hidden = false - } -// eslint-disable-next-line no-console -})().catch(err => console.error(err)) diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/style.css b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/style.css deleted file mode 100644 index 072f654118..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/style.css +++ /dev/null @@ -1,109 +0,0 @@ -:root { - font-family: Inter, Avenir, Helvetica, Arial, sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -body { - margin: 0; - display: flex; - place-items: center; - min-width: 320px; - min-height: 100vh; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #646cffaa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #3178c6aa); -} - -.card { - padding: 2em; -} - -.read-the-docs { - color: #888; -} - -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} - -button:hover { - border-color: #646cff; -} - -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - -#connlistWrapperEl ul { - max-width: 400px; - overflow-x: auto; -} \ No newline at end of file diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/vite-env.d.ts b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a0..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/tests/test.spec.js b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/tests/test.spec.js deleted file mode 100644 index edebee8011..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/tests/test.spec.js +++ /dev/null @@ -1,76 +0,0 @@ -/* eslint-disable no-console */ -import { setup, expect } from 'test-ipfs-example/browser' -import { spawn, exec } from 'child_process' -import { existsSync } from 'fs' - -// Setup -const test = setup() - -async function spinUpGoLibp2p() { - if (!existsSync('../../go-libp2p-webtransport-server/main')) { - await new Promise((resolve, reject) => { - exec('go build -o main main.go', - { cwd: '../../go-libp2p-webtransport-server' }, - (error, stdout, stderr) => { - if (error) { - reject(error) - console.error(`exec error: ${error}`) - return - } - resolve() - }) - }) - } - - const server = spawn('./main', [], { cwd: '../../go-libp2p-webtransport-server', killSignal: 'SIGINT' }) - server.stderr.on('data', (data) => { - console.log(`stderr: ${data}`, typeof data) - }) - const serverAddr = await (new Promise(resolve => { - server.stdout.on('data', (data) => { - console.log(`stdout: ${data}`, typeof data) - if (data.includes('addr=')) { - // Parse the addr out - resolve((String(data)).match(/addr=([^\s]*)/)[1]) - } - }) - })) - return { server, serverAddr } -} - -test.describe('bundle ipfs with parceljs:', () => { - // DOM - const connectBtn = '#connectBtn' - const connectAddr = '#peerInput' - const connList = '#connlistEl' - - let server - let serverAddr - - // eslint-disable-next-line no-empty-pattern - test.beforeAll(async ({ }, testInfo) => { - testInfo.setTimeout(5 * 60_000) - const s = await spinUpGoLibp2p() - server = s.server - serverAddr = s.serverAddr - console.log('Server addr:', serverAddr) - }, {}) - - test.afterAll(() => { - server.kill('SIGINT') - }) - - test.beforeEach(async ({ servers, page }) => { - await page.goto(servers[0].url) - }) - - test('should connect to a go-libp2p node over webtransport', async ({ page }) => { - await page.fill(connectAddr, serverAddr) - await page.click(connectBtn) - - await page.waitForSelector('#connlistEl:has(li)') - - const connections = await page.textContent(connList) - expect(connections).toContain(serverAddr) - }) -}) diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/tsconfig.json b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/tsconfig.json deleted file mode 100644 index fbd022532d..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "target": "ESNext", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ESNext", "DOM"], - "moduleResolution": "Node", - "strict": true, - "sourceMap": true, - "resolveJsonModule": true, - "isolatedModules": true, - "esModuleInterop": true, - "noEmit": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noImplicitReturns": true, - "skipLibCheck": true - }, - "include": ["src"] -} diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/vite.config.js b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/vite.config.js deleted file mode 100644 index bcbaff69d7..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/vite.config.js +++ /dev/null @@ -1,8 +0,0 @@ -export default { - build: { - target: 'es2020' - }, - optimizeDeps: { - esbuildOptions: { target: 'es2020', supported: { bigint: true } } - } -} diff --git a/examples/peer-and-content-routing/1.js b/examples/peer-and-content-routing/1.js deleted file mode 100644 index 6edd96b356..0000000000 --- a/examples/peer-and-content-routing/1.js +++ /dev/null @@ -1,59 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { kadDHT } from '@libp2p/kad-dht' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import delay from 'delay' -import { createLibp2p } from 'libp2p' -import { identifyService } from 'libp2p/identify' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - services: { - dht: kadDHT({ - // this is necessary because this node is not connected to the public network - // it can be removed if, for example bootstrappers are configured - allowQueryWithZeroPeers: true - }), - identify: identifyService() - } - }) - - return node -} - -;(async () => { - const [node1, node2, node3] = await Promise.all([ - createNode(), - createNode(), - createNode() - ]) - - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - await node2.peerStore.patch(node3.peerId, { - multiaddrs: node3.getMultiaddrs() - }) - - await Promise.all([ - node1.dial(node2.peerId), - node2.dial(node3.peerId) - ]) - - // The DHT routing tables need a moment to populate - await delay(1000) - - const peer = await node1.peerRouting.findPeer(node3.peerId) - - console.log('Found it, multiaddrs are:') - peer.multiaddrs.forEach((ma) => console.log(ma.toString())) -})() diff --git a/examples/peer-and-content-routing/2.js b/examples/peer-and-content-routing/2.js deleted file mode 100644 index 7c7c2ab643..0000000000 --- a/examples/peer-and-content-routing/2.js +++ /dev/null @@ -1,68 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { kadDHT } from '@libp2p/kad-dht' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import delay from 'delay' -import all from 'it-all' -import { createLibp2p } from 'libp2p' -import { identifyService } from 'libp2p/identify' -import { CID } from 'multiformats/cid' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - services: { - dht: kadDHT({ - // this is necessary because this node is not connected to the public network - // it can be removed if, for example bootstrappers are configured - allowQueryWithZeroPeers: true - }), - identify: identifyService() - } - }) - - return node -} - -;(async () => { - const [node1, node2, node3] = await Promise.all([ - createNode(), - createNode(), - createNode() - ]) - - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - await node2.peerStore.patch(node3.peerId, { - multiaddrs: node3.getMultiaddrs() - }) - - await Promise.all([ - node1.dial(node2.peerId), - node2.dial(node3.peerId) - ]) - - // Wait for onConnect handlers in the DHT - await delay(1000) - - const cid = CID.parse('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnL') - await node1.contentRouting.provide(cid) - - console.log('Node %s is providing %s', node1.peerId.toString(), cid.toString()) - - // wait for propagation - await delay(300) - - const providers = await all(node3.contentRouting.findProviders(cid, { timeout: 3000 })) - - console.log('Found provider:', providers[0].id.toString()) -})() diff --git a/examples/peer-and-content-routing/LICENSE b/examples/peer-and-content-routing/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/peer-and-content-routing/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/peer-and-content-routing/LICENSE-APACHE b/examples/peer-and-content-routing/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/peer-and-content-routing/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/peer-and-content-routing/LICENSE-MIT b/examples/peer-and-content-routing/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/peer-and-content-routing/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/peer-and-content-routing/README.md b/examples/peer-and-content-routing/README.md deleted file mode 100644 index ce482db5bf..0000000000 --- a/examples/peer-and-content-routing/README.md +++ /dev/null @@ -1,143 +0,0 @@ -# @libp2p/example-peer-and-content-routing - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> How to use peer and content routing - -## Table of contents - -- [1. Using Peer Routing to find other peers](#1-using-peer-routing-to-find-other-peers) -- [2. Using Content Routing to find providers of content](#2-using-content-routing-to-find-providers-of-content) -- [3. Future Work](#3-future-work) -- [License](#license) -- [Contribution](#contribution) - -Peer Routing is the category of modules that offer a way to find other peers in the network by intentionally issuing queries, iterative or recursive, until a Peer is found or the closest Peers, given the Peer Routing algorithm strategy are found. - -Content Routing is the category of modules that offer a way to find where content lives in the network, it works in two steps: 1) Peers provide (announce) to the network that they are holders of specific content (multihashes) and 2) Peers issue queries to find where that content lives. A Content Routing mechanism could be as complex as a Kademlia DHT or a simple registry somewhere in the network. - -## 1. Using Peer Routing to find other peers - -This example builds on top of the [Protocol and Stream Muxing](../protocol-and-stream-muxing). We need to install `@libp2p/kad-dht`, go ahead and `npm install @libp2p/kad-dht`. If you want to see the final version, open [1.js](./1.js). - -First, let's update our config to support Peer Routing and Content Routing. - -```JavaScript -import { createLibp2p } from 'libp2p' -import { kadDHT } from '@libp2p/kad-dht' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' -import { noise } from '@chainsafe/libp2p-noise' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - services: { - dht: kadDHT() - } - }) - - return node -} -``` - -Once that is done, we can use the createNode function we developed in the previous example to create 3 nodes. Connect node 1 to node 2 and node 2 to node 3. We will use node 2 as a way to find the whereabouts of node 3 - -```JavaScript -const [node1, node2, node3] = await Promise.all([ - createNode(), - createNode(), - createNode() -]) - -await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() -}) -await node2.peerStore.patch(node3.peerId, { - mulitaddrs: node3.getMultiaddrs() -}) - -await Promise.all([ - node1.dial(node2.peerId), - node2.dial(node3.peerId) -]) - -// Set up of the cons might take time -await new Promise(resolve => setTimeout(resolve, 100)) - -const peer = await node1.peerRouting.findPeer(node3.peerId) - -console.log('Found it, multiaddrs are:') -peer.multiaddrs.forEach((ma) => console.log(ma.toString())) -``` - -You should see the output being something like: - -```Bash -> node 1.js -Found it, multiaddrs are: -/ip4/127.0.0.1/tcp/63617 -/ip4/192.168.86.41/tcp/63617 -``` - -You have successfully used Peer Routing to find a peer that you were not directly connected. Now all you have to do is to dial to the multiaddrs you discovered. - -## 2. Using Content Routing to find providers of content - -With Content Routing, you can create records that are stored in multiple points in the network, these records can be resolved by you or other peers and they act as memos or rendezvous points. A great usage of this feature is to support discovery of content, where one node holds a file and instead of using a centralized tracker to inform other nodes that it holds that file, it simply puts a record in the network that can be resolved by other peers. Peer Routing and Content Routing are commonly known as Distributed Hash Tables, DHT. - -You can find this example completed in [2.js](./2.js), however as you will see it is very simple to update the previous example. - -Instead of calling `peerRouting.findPeer`, we will use `contentRouting.provide` and `contentRouting.findProviders`. - -```JavaScript -import { CID } from 'multiformats/cid' -import all from 'it-all' - -const cid = CID.parse('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnL') -await node1.contentRouting.provide(cid) - -console.log('Node %s is providing %s', node1.peerId.toString(), cid.toString()) - -const providers = await all(node3.contentRouting.findProviders(cid, { timeout: 5000 })) - -console.log('Found provider:', providers[0].id.toString()) -``` - -The output of your program should look like: - -```bash -> node 2.js -Node QmSsmVPoTy3WpzwiNPnsKmonBaZjK2HitFs2nWUvwK31Pz is providing QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnL -Found provider: QmSsmVPoTy3WpzwiNPnsKmonBaZjK2HitFs2nWUvwK31Pz -``` - -That's it, now you know how to find peers that have pieces of information that interest you! - -## 3. Future Work - -Currently, the only mechanisms for Peer and Content Routing come from the DHT, however we do have the intention to support: - -- Multiple Peer Routing Mechanisms, including ones that do recursive searches (i.e [webrtc-explorer](http://daviddias.me/blog/webrtc-explorer-2-0-0-alpha-release/) like packet switching or [CJDNS](https://github.com/cjdelisle/cjdns) path finder) -- Content Routing via PubSub -- Content Routing via centralized index (i.e a tracker) - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/peer-and-content-routing/package.json b/examples/peer-and-content-routing/package.json deleted file mode 100644 index 0218be3139..0000000000 --- a/examples/peer-and-content-routing/package.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "name": "@libp2p/example-peer-and-content-routing", - "version": "0.0.0", - "description": "How to use peer and content routing", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/peer-and-content-routing#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/kad-dht": "^10.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/tcp": "^8.0.0", - "delay": "^6.0.0", - "it-all": "^3.0.2", - "libp2p": "^0.46.0", - "multiformats": "^12.0.1" - }, - "devDependencies": { - "aegir": "^41.0.2", - "test-ipfs-example": "^1.0.0" - }, - "private": true -} diff --git a/examples/peer-and-content-routing/test-1.js b/examples/peer-and-content-routing/test-1.js deleted file mode 100644 index 3d9fd4e220..0000000000 --- a/examples/peer-and-content-routing/test-1.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('1.js\n') - - await waitForOutput('Found it, multiaddrs are:', 'node', [path.join(__dirname, '1.js')], { - cwd: __dirname - }) -} diff --git a/examples/peer-and-content-routing/test-2.js b/examples/peer-and-content-routing/test-2.js deleted file mode 100644 index 1c73889e6f..0000000000 --- a/examples/peer-and-content-routing/test-2.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('2.js\n') - - await waitForOutput('Found provider:', 'node', [path.join(__dirname, '2.js')], { - cwd: __dirname - }) -} diff --git a/examples/peer-and-content-routing/test.js b/examples/peer-and-content-routing/test.js deleted file mode 100644 index 07acb00823..0000000000 --- a/examples/peer-and-content-routing/test.js +++ /dev/null @@ -1,5 +0,0 @@ -import { test as test1 } from './test-1.js' -import { test as test2 } from './test-2.js' - -await test1() -await test2() diff --git a/examples/pnet/LICENSE b/examples/pnet/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/pnet/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/pnet/LICENSE-APACHE b/examples/pnet/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/pnet/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/pnet/LICENSE-MIT b/examples/pnet/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/pnet/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/pnet/README.md b/examples/pnet/README.md deleted file mode 100644 index 2e3104fef9..0000000000 --- a/examples/pnet/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# @libp2p/example-pnet - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> How to configure a libp2p private network - -## Table of contents - -- [Setup](#setup) -- [Run](#run) - - [Using different keys](#using-different-keys) - - [Exploring the repos](#exploring-the-repos) -- [License](#license) -- [Contribution](#contribution) - -## Setup - -1. Install the modules in the libp2p root directory, `npm install` and `npm run build`. - -## Run - -Running the example will cause two nodes with the same swarm key to be started and exchange basic information. - - node index.js - -### Using different keys - -This example includes `TASK` comments that can be used to try the example with different swarm keys. This will -allow you to see how nodes will fail to connect if they are on different private networks and try to connect to -one another. - -To change the swarm key of one of the nodes, look through `index.js` for comments starting with `TASK` to indicate -where lines are that pertain to changing the swarm key of node 2. - -### Exploring the repos - -Once you've run the example you can take a look at the repos in the `./tmp` directory to see how they differ, including -the swarm keys. You should see a `swarm.key` file in each of the repos and when the nodes are on the same private network -this contents of the `swarm.key` files should be the same. - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/pnet/index.js b/examples/pnet/index.js deleted file mode 100644 index 115d7f1792..0000000000 --- a/examples/pnet/index.js +++ /dev/null @@ -1,49 +0,0 @@ -/* eslint no-console: ["off"] */ - -import { pipe } from 'it-pipe' -import { generateKey } from 'libp2p/pnet' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import { privateLibp2pNode } from './libp2p-node.js' - -// Create a Uint8Array and write the swarm key to it -const swarmKey = new Uint8Array(95) -generateKey(swarmKey) - -// This key is for testing a different key not working -const otherSwarmKey = new Uint8Array(95) -generateKey(otherSwarmKey) - -;(async () => { - const node1 = await privateLibp2pNode(swarmKey) - - // TASK: switch the commented out line below so we're using a different key, to see the nodes fail to connect - const node2 = await privateLibp2pNode(swarmKey) - // const node2 = await privateLibp2pNode(otherSwarmKey) - - console.log('nodes started...') - - // Add node 2 data to node1's PeerStore - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - await node1.dial(node2.peerId) - - node2.handle('/private', ({ stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) - }) - - const stream = await node1.dialProtocol(node2.peerId, '/private') - - await pipe( - [uint8ArrayFromString('This message is sent on a private network')], - stream - ) -})() diff --git a/examples/pnet/libp2p-node.js b/examples/pnet/libp2p-node.js deleted file mode 100644 index 8b6b5e817f..0000000000 --- a/examples/pnet/libp2p-node.js +++ /dev/null @@ -1,34 +0,0 @@ -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { createLibp2p } from 'libp2p' -import { preSharedKey } from 'libp2p/pnet' - -/** - * privateLibp2pNode returns a libp2p node function that will use the swarm - * key with the given `swarmKey` to create the Protector - * - * @param {any} swarmKey - */ -export async function privateLibp2pNode (swarmKey) { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], // We're only using the TCP transport for this example - streamMuxers: [yamux(), mplex()], // We're only using mplex muxing - // Let's make sure to use identifying crypto in our pnet since the protector doesn't - // care about node identity, and only the presence of private keys - connectionEncryption: [noise()], - // Leave peer discovery empty, we don't want to find peers. We could omit the property, but it's - // being left in for explicit readability. - // We should explicitly dial pnet peers, or use a custom discovery service for finding nodes in our pnet - peerDiscovery: [], - connectionProtector: preSharedKey({ - psk: swarmKey - }) - }) - - return node -} diff --git a/examples/pnet/package.json b/examples/pnet/package.json deleted file mode 100644 index e619f3fe9a..0000000000 --- a/examples/pnet/package.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "name": "@libp2p/example-pnet", - "version": "0.0.0", - "description": "How to configure a libp2p private network", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/pnet#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/tcp": "^8.0.0", - "it-pipe": "^3.0.1", - "libp2p": "^0.46.0", - "uint8arrays": "^4.0.6" - }, - "devDependencies": { - "aegir": "^41.0.2", - "test-ipfs-example": "^1.0.0" - }, - "private": true -} diff --git a/examples/pnet/test.js b/examples/pnet/test.js deleted file mode 100644 index eb78f5a6f9..0000000000 --- a/examples/pnet/test.js +++ /dev/null @@ -1,9 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -await waitForOutput('This message is sent on a private network', 'node', [path.join(__dirname, 'index.js')], { - cwd: __dirname -}) diff --git a/examples/protocol-and-stream-muxing/1.js b/examples/protocol-and-stream-muxing/1.js deleted file mode 100644 index 0b3bf5b1e7..0000000000 --- a/examples/protocol-and-stream-muxing/1.js +++ /dev/null @@ -1,80 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { pipe } from 'it-pipe' -import { createLibp2p } from 'libp2p' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()] - }) - - return node -} - -;(async () => { - const [node1, node2] = await Promise.all([ - createNode(), - createNode() - ]) - - // Add node's 2 data to the PeerStore - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - - // exact matching - node2.handle('/your-protocol', ({ stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) - }) - - // multiple protocols - /* - node2.handle(['/another-protocol/1.0.0', '/another-protocol/2.0.0'], ({ protocol, stream }) => { - if (protocol === '/another-protocol/2.0.0') { - // handle backwards compatibility - } - - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg)) - } - } - ) - }) - */ - - const stream = await node1.dialProtocol(node2.peerId, ['/your-protocol']) - await pipe( - [uint8ArrayFromString('my own protocol, wow!')], - stream - ) - - /* - const stream = node1.dialProtocol(node2.peerId, ['/another-protocol/1.0.0']) - - await pipe( - ['my own protocol, wow!'], - stream - ) - */ -})() diff --git a/examples/protocol-and-stream-muxing/2.js b/examples/protocol-and-stream-muxing/2.js deleted file mode 100644 index 57e86294d4..0000000000 --- a/examples/protocol-and-stream-muxing/2.js +++ /dev/null @@ -1,67 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { pipe } from 'it-pipe' -import { createLibp2p } from 'libp2p' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()] - }) - - return node -} - -;(async () => { - const [node1, node2] = await Promise.all([ - createNode(), - createNode() - ]) - - // Add node's 2 data to the PeerStore - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - - node2.handle(['/a', '/b'], ({ protocol, stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(`from: ${protocol}, msg: ${uint8ArrayToString(msg.subarray())}`) - } - } - ).finally(() => { - // clean up resources - stream.close() - }) - }) - - const stream1 = await node1.dialProtocol(node2.peerId, ['/a']) - await pipe( - [uint8ArrayFromString('protocol (a)')], - stream1 - ) - - const stream2 = await node1.dialProtocol(node2.peerId, ['/b']) - await pipe( - [uint8ArrayFromString('protocol (b)')], - stream2 - ) - - const stream3 = await node1.dialProtocol(node2.peerId, ['/b']) - await pipe( - [uint8ArrayFromString('another stream on protocol (b)')], - stream3 - ) -})() diff --git a/examples/protocol-and-stream-muxing/3.js b/examples/protocol-and-stream-muxing/3.js deleted file mode 100644 index eb88137a42..0000000000 --- a/examples/protocol-and-stream-muxing/3.js +++ /dev/null @@ -1,69 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { pipe } from 'it-pipe' -import { createLibp2p } from 'libp2p' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()] - }) - - return node -} - -;(async () => { - const [node1, node2] = await Promise.all([ - createNode(), - createNode() - ]) - - // Add node's 2 data to the PeerStore - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - - node1.handle('/node-1', ({ stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) - }) - - node2.handle('/node-2', ({ stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) - }) - - const stream1 = await node1.dialProtocol(node2.peerId, ['/node-2']) - await pipe( - [uint8ArrayFromString('from 1 to 2')], - stream1 - ) - - const stream2 = await node2.dialProtocol(node1.peerId, ['/node-1']) - await pipe( - [uint8ArrayFromString('from 2 to 1')], - stream2 - ) -})() diff --git a/examples/protocol-and-stream-muxing/LICENSE b/examples/protocol-and-stream-muxing/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/protocol-and-stream-muxing/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/protocol-and-stream-muxing/LICENSE-APACHE b/examples/protocol-and-stream-muxing/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/protocol-and-stream-muxing/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/protocol-and-stream-muxing/LICENSE-MIT b/examples/protocol-and-stream-muxing/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/protocol-and-stream-muxing/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/protocol-and-stream-muxing/README.md b/examples/protocol-and-stream-muxing/README.md deleted file mode 100644 index beda3b2b37..0000000000 --- a/examples/protocol-and-stream-muxing/README.md +++ /dev/null @@ -1,305 +0,0 @@ -# @libp2p/example-protocol-and-stream-muxing - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> How to use multiplex protocols streams - -## Table of contents - -- [1. Handle multiple protocols](#1-handle-multiple-protocols) -- [2. Reuse existing connection](#2-reuse-existing-connection) -- [3. Bidirectional connections](#3-bidirectional-connections) -- [License](#license) -- [Contribution](#contribution) - -The feature of agreeing on a protocol over an established connection is what we call *protocol multiplexing* and it is possible through [multistream-select](https://github.com/multiformats/multistream), another protocol that lets you agree per connection (or stream) which protocol is going to be talked over that connection (select), it also enables you to request the other end to tell you which protocols it supports (ls). You can learn more about multistream-select at its [specification repo](https://github.com/multiformats/multistream). - -## 1. Handle multiple protocols - -Let's see *protocol multiplexing* in action! You will need the following modules for this example: `libp2p`, `@libp2p/tcp`, `@libp2p/peer-id`, `it-pipe`, `it-buffer` and `streaming-iterables`. This example reuses the base left by the [Transports](../transports) example. You can see the complete solution at [1.js](./1.js). - -After creating the nodes, we need to tell libp2p which protocols to handle. - -```JavaScript -import { pipe } from 'it-pipe' -import { map } from 'streaming-iterables' -import { toBuffer } from 'it-buffer' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -// ... -const [node1, node2] = await Promise.all([ - createNode(), - createNode() -]) - -// Add node's 2 data to the PeerStore -await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() -}) - -// Here we are telling libp2p that if someone dials this node to talk with the `/your-protocol` -// multicodec, the protocol identifier, please call this handler and give it the stream -// so that incomming data can be handled -node2.handle('/your-protocol', ({ stream }) => { - pipe( - stream, - source => (async function () { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - })() - ) -}) -``` - -After the protocol is *handled*, now we can dial to it. - -```JavaScript -const stream = await node1.dialProtocol(node2.peerId, ['/your-protocol']) - -await pipe( - [uint8ArrayFromString('my own protocol, wow!')], - stream -) -``` - -You might have seen this in the [Transports](../transports) examples. However, what it was not explained is that you can do more than exact string matching, for example, you can use semver. - -```JavaScript -node2.handle('/another-protocol/1.0.1', ({ stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) -}) -// ... -const stream = await node1.dialProtocol(node2.peerId, ['/another-protocol/1.0.0']) - -await pipe( - [uint8ArrayFromString('my own protocol, wow!')], - stream -) -``` - -This feature is super power for network protocols. It works in the same way as versioning your RPC/REST API, but for anything that goes in the wire. We had to use this feature to upgrade protocols within the IPFS Stack (i.e Bitswap) and we successfully managed to do so without any network splits. - -There is still one last feature, you can provide multiple protocols for the same handler. If you have a backwards incompatible change, but it only requires minor changes to the code, you may prefer to do protocol checking instead of having multiple handlers - -```JavaScript -node2.handle(['/another-protocol/1.0.0', '/another-protocol/2.0.0'], ({ stream }) => { - if (stream.protocol === '/another-protocol/2.0.0') { - // handle backwards compatibility - } - - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) -}) -``` - -Try all of this out by executing [1.js](./1.js). - -## 2. Reuse existing connection - -The examples above would require a node to create a whole new connection for every time it dials in one of the protocols, this is a waste of resources and also it might be simply not possible (e.g lack of file descriptors, not enough ports being open, etc). What we really want is to dial a connection once and then multiplex several virtual connections (stream) over a single connection, this is where *stream multiplexing* comes into play. - -Stream multiplexing is an old concept, in fact it happens in many of the layers of the [OSI System](https://en.wikipedia.org/wiki/OSI_model). In libp2p, we make this feature to our avail by letting the user pick which module for stream multiplexing to use. - -Currently, we have [libp2p-mplex](https://github.com/libp2p/js-libp2p-mplex) and pluging it in is as easy as adding a transport. Let's revisit our libp2p configuration. - -```JavaScript -import { createLibp2p } from 'libp2p' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' - -//... - -createLibp2p({ - //... - transports: [ - tcp() - ], - streamMuxers: [ - yamux(), - mplex() - ] -}) - -``` - -With this, we can dial as many times as we want to a peer and always reuse the same established underlying connection. - -```JavaScript -node2.handle(['/a', '/b'], ({ stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(`from: ${stream.protocol}, msg: ${uint8ArrayToString(msg.subarray())}`) - } - } - ) -}) - -const stream = await node1.dialProtocol(node2.peerId, ['/a']) -await pipe( - [uint8ArrayFromString('protocol (a)')], - stream -) - -const stream2 = await node1.dialProtocol(node2.peerId, ['/b']) -await pipe( - [uint8ArrayFromString('protocol (b)')], - stream2 -) - -const stream3 = await node1.dialProtocol(node2.peerId, ['/b']) -await pipe( - [uint8ArrayFromString('another stream on protocol (b)')], - stream3 -) -``` - -By running [2.js](./2.js) you should see the following result: - - > node 2.js - from: /a, msg: protocol (a) - from: /b, msg: protocol (b) - from: /b, msg: another stream on protocol (b) - -## 3. Bidirectional connections - -There is one last trick on *protocol and stream multiplexing* that libp2p uses to make everyone's life easier and that is *bidirectional connection*. - -With the aid of both mechanisms, we can reuse an incomming connection to dial streams out too, this is specially useful when you are behind tricky NAT, firewalls or if you are running in a browser, where you can't have listening addrs, but you can dial out. By dialing out, you enable other peers to talk with you in Protocols that they want, simply by opening a new multiplexed stream. - -You can see this working on example [3.js](./3.js). - -As we've seen earlier, we can create our node with this createNode function. - -```js -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - }) - - return node -} -``` - -We can now create our two nodes for this example. - -```js -const [node1, node2] = await Promise.all([ - createNode(), - createNode() -]) -``` - -Since, we want to connect these nodes `node1` & `node2`, we add our `node2` multiaddr in key-value pair in `node1` peer store. - -```js -await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() -}) -``` - -You may notice that we are only adding `node2` to `node1` peer store. This is because we want to dial up a bidirectional connection between these two nodes. - -Finally, let's create protocols for `node1` & `node2` and dial those protocols. - -```js -node1.handle('/node-1', ({ stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) -}) - -node2.handle('/node-2', ({ stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) -}) - -// Dialing node2 from node1 -const stream1 = await node1.dialProtocol(node2.peerId, ['/node-2']) -await pipe( - [uint8ArrayFromString('from 1 to 2')], - stream1 -) - -// Dialing node1 from node2 -const stream2 = await node2.dialProtocol(node1.peerId, ['/node-1']) -await pipe( - [uint8ArrayFromString('from 2 to 1')], - stream2 -) -``` - -If we run this code, the result should look like the following: - -```Bash -> node 3.js -from 1 to 2 -from 2 to 1 -``` - -So, we have successfully set up a bidirectional connection with protocol muxing. But you should be aware that we were able to dial from `node2` to `node1` even we haven't added the `node1` peerId to node2 address book is because we dialed node2 from node1 first. Then, we just dialed back our stream out from `node2` to `node1`. So, if we dial from `node2` to `node1` before dialing from `node1` to `node2` we will get an error. - -The code below will result into an error as `the dial address is not valid`. - -```js -// Dialing from node2 to node1 -const stream2 = await node2.dialProtocol(node1.peerId, ['/node-1']) -await pipe( - [uint8ArrayFromString('from 2 to 1')], - stream2 -) - -// Dialing from node1 to node2 -const stream1 = await node1.dialProtocol(node2.peerId, ['/node-2']) -await pipe( - [uint8ArrayFromString('from 1 to 2')], - stream1 -) -``` - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/protocol-and-stream-muxing/package.json b/examples/protocol-and-stream-muxing/package.json deleted file mode 100644 index d8d8086336..0000000000 --- a/examples/protocol-and-stream-muxing/package.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "name": "@libp2p/example-protocol-and-stream-muxing", - "version": "0.0.0", - "description": "How to use multiplex protocols streams", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/protocol-and-stream-muxing#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/tcp": "^8.0.0", - "it-pipe": "^3.0.1", - "libp2p": "^0.46.0", - "uint8arrays": "^4.0.6" - }, - "devDependencies": { - "aegir": "^41.0.2", - "test-ipfs-example": "^1.0.0" - }, - "private": true -} diff --git a/examples/protocol-and-stream-muxing/test-1.js b/examples/protocol-and-stream-muxing/test-1.js deleted file mode 100644 index 5e13eb6ed2..0000000000 --- a/examples/protocol-and-stream-muxing/test-1.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('1.js\n') - - await waitForOutput('my own protocol, wow!', 'node', [path.join(__dirname, '1.js')], { - cwd: __dirname - }) -} diff --git a/examples/protocol-and-stream-muxing/test-2.js b/examples/protocol-and-stream-muxing/test-2.js deleted file mode 100644 index 885d54117b..0000000000 --- a/examples/protocol-and-stream-muxing/test-2.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('2.js\n') - - await waitForOutput('another stream on protocol (b)', 'node', [path.join(__dirname, '2.js')], { - cwd: __dirname - }) -} diff --git a/examples/protocol-and-stream-muxing/test-3.js b/examples/protocol-and-stream-muxing/test-3.js deleted file mode 100644 index 0748b259db..0000000000 --- a/examples/protocol-and-stream-muxing/test-3.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('3.js\n') - - await waitForOutput('from 2 to 1', 'node', [path.join(__dirname, '3.js')], { - cwd: __dirname - }) -} diff --git a/examples/protocol-and-stream-muxing/test.js b/examples/protocol-and-stream-muxing/test.js deleted file mode 100644 index fd441b83ed..0000000000 --- a/examples/protocol-and-stream-muxing/test.js +++ /dev/null @@ -1,7 +0,0 @@ -import { test as test1 } from './test-1.js' -import { test as test2 } from './test-2.js' -import { test as test3 } from './test-3.js' - -await test1() -await test2() -await test3() diff --git a/examples/pubsub/1.js b/examples/pubsub/1.js deleted file mode 100644 index 0e15e87ddb..0000000000 --- a/examples/pubsub/1.js +++ /dev/null @@ -1,61 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { floodsub } from '@libp2p/floodsub' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { createLibp2p } from 'libp2p' -import { identifyService } from 'libp2p/identify' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - services: { - pubsub: floodsub(), - identify: identifyService() - } - }) - - return node -} - -;(async () => { - const topic = 'news' - - const [node1, node2] = await Promise.all([ - createNode(), - createNode() - ]) - - // Add node's 2 data to the PeerStore - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - await node1.dial(node2.peerId) - - node1.services.pubsub.subscribe(topic) - node1.services.pubsub.addEventListener('message', (evt) => { - console.log(`node1 received: ${uint8ArrayToString(evt.detail.data)} on topic ${evt.detail.topic}`) - }) - - // Will not receive own published messages by default - node2.services.pubsub.subscribe(topic) - node2.services.pubsub.addEventListener('message', (evt) => { - console.log(`node2 received: ${uint8ArrayToString(evt.detail.data)} on topic ${evt.detail.topic}`) - }) - - // node2 publishes "news" every second - setInterval(() => { - node2.services.pubsub.publish(topic, uint8ArrayFromString('Bird bird bird, bird is the word!')).catch(err => { - console.error(err) - }) - }, 1000) -})() diff --git a/examples/pubsub/LICENSE b/examples/pubsub/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/pubsub/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/pubsub/LICENSE-APACHE b/examples/pubsub/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/pubsub/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/pubsub/LICENSE-MIT b/examples/pubsub/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/pubsub/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/pubsub/README.md b/examples/pubsub/README.md deleted file mode 100644 index 538e3c5dbd..0000000000 --- a/examples/pubsub/README.md +++ /dev/null @@ -1,140 +0,0 @@ -# @libp2p/example-pubsub - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> An example using libp2p pubsub - -## Table of contents - -- [0. Set up the example](#0-set-up-the-example) -- [1. Setting up a simple PubSub network on top of libp2p](#1-setting-up-a-simple-pubsub-network-on-top-of-libp2p) -- [2. Future work](#2-future-work) -- [License](#license) -- [Contribution](#contribution) - -We've seen many interesting use cases appear with this, here are some highlights: - -- [Collaborative Text Editing](https://www.youtube.com/watch?v=-kdx8rJd8rQ) -- [IPFS PubSub (using libp2p-floodsub) for IoT](https://www.youtube.com/watch?v=qLpM5pBDGiE). -- [Real Time distributed Applications](https://www.youtube.com/watch?v=vQrbxyDPSXg) - -## 0. Set up the example - -Before moving into the examples, you should run `npm install` and `npm run build` on the top level `js-libp2p` folder, in order to install all the dependencies needed for this example. In addition, you will need to install the example related dependencies by doing `cd examples && npm install`. Once the install finishes, you should move into the example folder with `cd pubsub`. - -## 1. Setting up a simple PubSub network on top of libp2p - -For this example, we will use MulticastDNS for automatic Peer Discovery. This example is based the previous examples found in [Discovery Mechanisms](../discovery-mechanisms). You can find the complete version at [1.js](./1.js). - -Using PubSub is super simple, you only need to provide the implementation of your choice and you are ready to go. No need for extra configuration. - -First, let's update our libp2p configuration with a pubsub implementation. - -```JavaScript -import { createLibp2p } from 'libp2p' -import { GossipSub } from '@chainsafe/libp2p-gossipsub' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' -import { noise } from '@chainsafe/libp2p-noise' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - services: { - // we add the Pubsub module we want - pubsub: gossipsub({ allowPublishToZeroPeers: true }) - } - }) - - return node -} -``` - -Once that is done, we only need to create a few libp2p nodes, connect them and everything is ready to start using pubsub. - -```JavaScript -import { fromString as uint8ArrayFromString } from "uint8arrays/from-string"; -import { toString as uint8ArrayToString } from "uint8arrays/to-string"; - -const topic = 'news' - -const [node1, node2] = await Promise.all([ - createNode(), - createNode() -]) - -// Add node's 2 data to the PeerStore -await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() -}) -await node1.dial(node2.peerId) - -node1.services.pubsub.addEventListener("message", (evt) => { - console.log(`node1 received: ${uint8ArrayToString(evt.detail.data)} on topic ${evt.detail.topic}`) -}) -await node1.services.pubsub.subscribe(topic) - -// Will not receive own published messages by default -node2.services.pubsub.addEventListener("message", (evt) => { - console.log(`node2 received: ${uint8ArrayToString(evt.detail.data)} on topic ${evt.detail.topic}`) -}) -await node2.services.pubsub.subscribe(topic) - -// node2 publishes "news" every second -setInterval(() => { - node2.services.pubsub.publish(topic, uint8ArrayFromString('Bird bird bird, bird is the word!')).catch(err => { - console.error(err) - }) -}, 1000) -``` - -The output of the program should look like: - - > node 1.js - connected to QmWpvkKm6qHLhoxpWrTswY6UMNWDyn8hN265Qp9ZYvgS82 - node1 received: Bird bird bird, bird is the word! - node1 received: Bird bird bird, bird is the word! - -You can change the pubsub `emitSelf` option if you want the publishing node to receive its own messages. - -```JavaScript -gossipsub({ allowPublishToZeroPeers: true, emitSelf: true }) -``` - -The output of the program should look like: - - > node 1.js - connected to QmWpvkKm6qHLhoxpWrTswY6UMNWDyn8hN265Qp9ZYvgS82 - node1 received: Bird bird bird, bird is the word! - node2 received: Bird bird bird, bird is the word! - node1 received: Bird bird bird, bird is the word! - node2 received: Bird bird bird, bird is the word! - -## 2. Future work - -libp2p/IPFS PubSub is enabling a whole set of Distributed Real Time applications using CRDT (Conflict-Free Replicated Data Types). It is still going through heavy research (and hacking) and we invite you to join the conversation at [research-CRDT](https://github.com/ipfs/research-CRDT). Here is a list of some of the exciting examples: - -- [PubSub Room](https://github.com/ipfs-labs/ipfs-pubsub-room) -- [Live DB - A always in Sync DB using CRDT](https://github.com/ipfs-labs/ipfs-live-db) -- [IIIF Annotations over IPFS, CRDT and libp2p](https://www.youtube.com/watch?v=hmAniA6g9D0\&feature=youtu.be\&t=10m40s) -- [orbit.chat - p2p chat application, fully running in the browser with js-ipfs, js-libp2p and orbit-db](http://orbit.chat/) - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/pubsub/message-filtering/1.js b/examples/pubsub/message-filtering/1.js deleted file mode 100644 index 03f7cff285..0000000000 --- a/examples/pubsub/message-filtering/1.js +++ /dev/null @@ -1,131 +0,0 @@ -/* eslint-disable no-console */ - -import { createLibp2p } from 'libp2p' -import { identifyService } from 'libp2p/identify' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' -import { noise } from '@chainsafe/libp2p-noise' -import { floodsub } from '@libp2p/floodsub' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - services: { - pubsub: floodsub(), - identify: identifyService() - } - }) - - return node -} - -(async () => { - const topic = 'fruit' - - const [node1, node2, node3] = await Promise.all([ - createNode(), - createNode(), - createNode() - ]) - - // node1 conect to node2 and node2 conect to node3 - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - await node1.dial(node2.peerId) - - await node2.peerStore.patch(node3.peerId, { - multiaddrs: node3.getMultiaddrs() - }) - await node2.dial(node3.peerId) - - // subscribe - node1.services.pubsub.addEventListener('message', (evt) => { - if (evt.detail.topic !== topic) { - return - } - - // Will not receive own published messages by default - console.log(`node1 received: ${uint8ArrayToString(evt.detail.data)}`) - }) - node1.services.pubsub.subscribe(topic) - - node2.services.pubsub.addEventListener('message', (evt) => { - if (evt.detail.topic !== topic) { - return - } - - console.log(`node2 received: ${uint8ArrayToString(evt.detail.data)}`) - }) - node2.services.pubsub.subscribe(topic) - - node3.services.pubsub.addEventListener('message', (evt) => { - if (evt.detail.topic !== topic) { - return - } - - console.log(`node3 received: ${uint8ArrayToString(evt.detail.data)}`) - }) - node3.services.pubsub.subscribe(topic) - - // wait for subscriptions to propagate - await hasSubscription(node1, node2, topic) - await hasSubscription(node2, node3, topic) - - const validateFruit = (msgTopic, msg) => { - const fruit = uint8ArrayToString(msg.data) - const validFruit = ['banana', 'apple', 'orange'] - - // car is not a fruit ! - if (!validFruit.includes(fruit)) { - throw new Error('no valid fruit received') - } - } - - // validate fruit - node1.services.pubsub.topicValidators.set(topic, validateFruit) - node2.services.pubsub.topicValidators.set(topic, validateFruit) - node3.services.pubsub.topicValidators.set(topic, validateFruit) - - // node1 publishes "fruits" - for (const fruit of ['banana', 'apple', 'car', 'orange']) { - console.log('############## fruit ' + fruit + ' ##############') - await node1.services.pubsub.publish(topic, uint8ArrayFromString(fruit)) - } - - console.log('############## all messages sent ##############') -})() - -async function delay (ms) { - await new Promise((resolve) => { - setTimeout(() => resolve(), ms) - }) -} - -/** - * Wait for node1 to see that node2 has subscribed to the topic - * - * @param node1 - * @param node2 - * @param topic - */ -async function hasSubscription (node1, node2, topic) { - while (true) { - const subs = await node1.services.pubsub.getSubscribers(topic) - - if (subs.map(peer => peer.toString()).includes(node2.peerId.toString())) { - return - } - - // wait for subscriptions to propagate - await delay(100) - } -} diff --git a/examples/pubsub/message-filtering/README.md b/examples/pubsub/message-filtering/README.md deleted file mode 100644 index 7b9dba1309..0000000000 --- a/examples/pubsub/message-filtering/README.md +++ /dev/null @@ -1,135 +0,0 @@ -# Filter Messages - -To prevent undesired data from being propagated on the network, we can apply a filter to Gossipsub. Messages that fail validation in the filter will not be re-shared. - -## 1. Setting up a PubSub network with three nodes - -First, let's update our libp2p configuration with a pubsub implementation. - -```JavaScript -import { createLibp2p } from 'libp2p' -import { gossipsub } from '@chainsafe/libp2p-gossipsub' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' -import { noise } from '@chainsafe/libp2p-noise' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - // we add the Pubsub module we want - services: { - pubsub: gossipsub({ allowPublishToZeroPeers: true }) - } - }) - - return node -} -``` - -Then, create three nodes and connect them together. In this example, we will connect the nodes in series. Node 1 connected with node 2 and node 2 connected with node 3. - -```JavaScript -const [node1, node2, node3] = await Promise.all([ - createNode(), - createNode(), - createNode(), -]) - -await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() -}) -await node1.dial(node2.peerId) - -await node2.peerStore.patch(node3.peerId, { - multiaddrs: node3.getMultiaddrs() -}) -await node2.dial(node3.peerId) -``` - -Now we' can subscribe to the fruit topic and log incoming messages. - -```JavaScript -import { fromString as uint8ArrayFromString } from "uint8arrays/from-string"; -import { toString as uint8ArrayToString } from "uint8arrays/to-string"; - -const topic = 'fruit' - -node1.services.pubsub.addEventListener('message', (msg) => { - if (msg.detail.topic !== topic) { - return - } - - console.log(`node1 received: ${uint8ArrayToString(msg.data)}`) -}) -await node1.services.pubsub.subscribe(topic) - -node2.services.pubsub.addEventListener('message', (msg) => { - if (msg.detail.topic !== topic) { - return - } - - console.log(`node2 received: ${uint8ArrayToString(msg.data)}`) -}) -await node2.services.pubsub.subscribe(topic) - -node3.services.pubsub.addEventListener('message', (msg) => { - if (msg.detail.topic !== topic) { - return - } - -console.log(`node3 received: ${uint8ArrayToString(msg.data)}`) -}) -await node3.services.pubsub.subscribe(topic) -``` -Finally, let's define the additional filter in the fruit topic. - -```JavaScript -import { TopicValidatorResult } from '@libp2p/interface/pubsub' - -const validateFruit = (msgTopic, msg) => { - const fruit = uint8ArrayToString(msg.data) - const validFruit = ['banana', 'apple', 'orange'] - - // car is not a fruit ! - if (!validFruit.includes(fruit)) { - throw new Error('no valid fruit received') - } - return TopicValidatorResult.Accept -} - -node1.services.pubsub.topicValidators.set(topic, validateFruit) -node2.services.pubsub.topicValidators.set(topic, validateFruit) -node3.services.pubsub.topicValidators.set(topic, validateFruit) -``` - -In this example, node one has an outdated version of the system, or is a malicious node. When it tries to publish fruit, the messages are re-shared and all the nodes share the message. However, when it tries to publish a vehicle the message is not re-shared. - -```JavaScript -for (const fruit of ['banana', 'apple', 'car', 'orange']) { - console.log('############## fruit ' + fruit + ' ##############') - await node1.services.pubsub.publish(topic, uint8ArrayFromString(fruit)) -} -``` - -Result - -``` -> node 1.js -############## fruit banana ############## -node2 received: banana -node3 received: banana -############## fruit apple ############## -node2 received: apple -node3 received: apple -############## fruit car ############## -############## fruit orange ############## -node1 received: orange -node2 received: orange -node3 received: orange -``` diff --git a/examples/pubsub/message-filtering/test.js b/examples/pubsub/message-filtering/test.js deleted file mode 100644 index d0ddc95b7c..0000000000 --- a/examples/pubsub/message-filtering/test.js +++ /dev/null @@ -1,56 +0,0 @@ -import path from 'path' -import { execa } from 'execa' -import pDefer from 'p-defer' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import { fileURLToPath } from 'url' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -// holds messages received by peers -const messages = {} - -export async function test () { - const defer = pDefer() - - process.stdout.write('message-filtering/1.js\n') - - const proc = execa('node', [path.join(__dirname, '1.js')], { - cwd: path.resolve(__dirname), - all: true - }) - - let output = '' - - const expected = [ - 'node2 received: banana', - 'node2 received: apple', - 'node2 received: orange', - 'node3 received: banana', - 'node3 received: apple', - 'node3 received: orange' - ] - - proc.all.on('data', async (data) => { - process.stdout.write(data) - output += uint8ArrayToString(data) - - if (output.includes('received: car')) { - defer.reject(new Error('Message validation failed - peers failed to filter car messages')) - } - - let allMessagesReceived = true - - expected.forEach(message => { - if (!output.includes(message)) { - allMessagesReceived = false - } - }) - - if (allMessagesReceived) { - defer.resolve() - } - }) - - await defer.promise - proc.kill() -} diff --git a/examples/pubsub/package.json b/examples/pubsub/package.json deleted file mode 100644 index 97c909fc67..0000000000 --- a/examples/pubsub/package.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "@libp2p/example-pubsub", - "version": "0.0.0", - "description": "An example using libp2p pubsub", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/pubsub#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/floodsub": "^8.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/tcp": "^8.0.0", - "libp2p": "^0.46.0", - "uint8arrays": "^4.0.6" - }, - "devDependencies": { - "aegir": "^41.0.2", - "execa": "^8.0.1", - "p-defer": "^4.0.0" - }, - "private": true -} diff --git a/examples/pubsub/test-1.js b/examples/pubsub/test-1.js deleted file mode 100644 index 064f4aecf6..0000000000 --- a/examples/pubsub/test-1.js +++ /dev/null @@ -1,29 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { execa } from 'execa' -import pDefer from 'p-defer' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - const defer = pDefer() - process.stdout.write('1.js\n') - - const proc = execa('node', [path.join(__dirname, '1.js')], { - cwd: path.resolve(__dirname), - all: true - }) - - proc.all.on('data', async (data) => { - process.stdout.write(data) - const line = uint8ArrayToString(data) - - if (line.includes('node1 received: Bird bird bird, bird is the word!')) { - defer.resolve() - } - }) - - await defer.promise - proc.kill() -} diff --git a/examples/pubsub/test.js b/examples/pubsub/test.js deleted file mode 100644 index 1e35941f74..0000000000 --- a/examples/pubsub/test.js +++ /dev/null @@ -1,5 +0,0 @@ -import { test as testMessageFiltering } from './message-filtering/test.js' -import { test as test1 } from './test-1.js' - -await test1() -await testMessageFiltering() diff --git a/examples/transports/1.js b/examples/transports/1.js deleted file mode 100644 index 0ca98ea875..0000000000 --- a/examples/transports/1.js +++ /dev/null @@ -1,33 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { tcp } from '@libp2p/tcp' -import { createLibp2p } from 'libp2p' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - // To signal the addresses we want to be available, we use - // the multiaddr format, a self describable address - listen: [ - '/ip4/0.0.0.0/tcp/0' - ] - }, - transports: [ - tcp() - ], - connectionEncryption: [ - noise() - ] - }) - - return node -} - -;(async () => { - const node = await createNode() - - console.log('node has started (true/false):', node.isStarted()) - console.log('listening on:') - node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) -})() diff --git a/examples/transports/2.js b/examples/transports/2.js deleted file mode 100644 index 9cc39cfc85..0000000000 --- a/examples/transports/2.js +++ /dev/null @@ -1,64 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { pipe } from 'it-pipe' -import toBuffer from 'it-to-buffer' -import { createLibp2p } from 'libp2p' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - // To signal the addresses we want to be available, we use - // the multiaddr format, a self describable address - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - connectionEncryption: [noise()], - streamMuxers: [yamux(), mplex()] - }) - - return node -} - -function printAddrs (node, number) { - console.log('node %s is listening on:', number) - node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) -} - -(async () => { - const [node1, node2] = await Promise.all([ - createNode(), - createNode() - ]) - - printAddrs(node1, '1') - printAddrs(node2, '2') - - node2.handle('/print', async ({ stream }) => { - const result = await pipe( - stream, - async function * (source) { - for await (const list of source) { - yield list.subarray() - } - }, - toBuffer - ) - console.log(uint8ArrayToString(result)) - }) - - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - const stream = await node1.dialProtocol(node2.peerId, '/print') - - await pipe( - ['Hello', ' ', 'p2p', ' ', 'world', '!'].map(str => uint8ArrayFromString(str)), - stream - ) -})() diff --git a/examples/transports/3.js b/examples/transports/3.js deleted file mode 100644 index 4663b5563e..0000000000 --- a/examples/transports/3.js +++ /dev/null @@ -1,91 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { webSockets } from '@libp2p/websockets' -import { pipe } from 'it-pipe' -import { createLibp2p } from 'libp2p' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const createNode = async (transports, addresses = []) => { - if (!Array.isArray(addresses)) { - addresses = [addresses] - } - - const node = await createLibp2p({ - addresses: { - listen: addresses - }, - transports, - connectionEncryption: [noise()], - streamMuxers: [yamux(), mplex()] - }) - - return node -} - -function printAddrs (node, number) { - console.log('node %s is listening on:', number) - node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) -} - -function print ({ stream }) { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) -} - -(async () => { - const [node1, node2, node3] = await Promise.all([ - createNode([tcp()], '/ip4/0.0.0.0/tcp/0'), - createNode([tcp(), webSockets()], ['/ip4/0.0.0.0/tcp/0', '/ip4/127.0.0.1/tcp/10000/ws']), - createNode([webSockets()], '/ip4/127.0.0.1/tcp/20000/ws') - ]) - - printAddrs(node1, '1') - printAddrs(node2, '2') - printAddrs(node3, '3') - - node1.handle('/print', print) - node2.handle('/print', print) - node3.handle('/print', print) - - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - await node2.peerStore.patch(node3.peerId, { - multiaddrs: node3.getMultiaddrs() - }) - await node3.peerStore.patch(node1.peerId, { - multiaddrs: node1.getMultiaddrs() - }) - - // node 1 (TCP) dials to node 2 (TCP+WebSockets) - const stream = await node1.dialProtocol(node2.peerId, '/print') - await pipe( - [uint8ArrayFromString('node 1 dialed to node 2 successfully')], - stream - ) - - // node 2 (TCP+WebSockets) dials to node 3 (WebSockets) - const stream2 = await node2.dialProtocol(node3.peerId, '/print') - await pipe( - [uint8ArrayFromString('node 2 dialed to node 3 successfully')], - stream2 - ) - - // node 3 (listening WebSockets) can dial node 1 (TCP) - try { - await node3.dialProtocol(node1.peerId, '/print') - } catch (err) { - console.log('node 3 failed to dial to node 1 with:', err.message) - } -})() diff --git a/examples/transports/4.js b/examples/transports/4.js deleted file mode 100644 index 6ce792e669..0000000000 --- a/examples/transports/4.js +++ /dev/null @@ -1,81 +0,0 @@ -/* eslint-disable no-console */ - -import fs from 'fs' -import https from 'https' -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { webSockets } from '@libp2p/websockets' -import { pipe } from 'it-pipe' -import { createLibp2p } from 'libp2p' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const httpServer = https.createServer({ - cert: fs.readFileSync('./test_certs/cert.pem'), - key: fs.readFileSync('./test_certs/key.pem') -}) - -const createNode = async (addresses = []) => { - if (!Array.isArray(addresses)) { - addresses = [addresses] - } - - const node = await createLibp2p({ - addresses: { - listen: addresses - }, - transports: [ - tcp(), - webSockets({ - server: httpServer, - websocket: { - rejectUnauthorized: false - } - }) - ], - connectionEncryption: [noise()], - streamMuxers: [mplex(), yamux()] - }) - - return node -} - -function printAddrs (node, number) { - console.log('node %s is listening on:', number) - node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) -} - -function print ({ stream }) { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) -} - -(async () => { - const [node1, node2] = await Promise.all([ - createNode('/ip4/127.0.0.1/tcp/10000/wss'), - createNode([]) - ]) - - printAddrs(node1, '1') - printAddrs(node2, '2') - - node1.handle('/print', print) - node2.handle('/print', print) - - const targetAddr = node1.getMultiaddrs()[0] - - // node 2 (Secure WebSockets) dials to node 1 (Secure Websockets) - const stream = await node2.dialProtocol(targetAddr, '/print') - await pipe( - [uint8ArrayFromString('node 2 dialed to node 1 successfully')], - stream - ) -})() diff --git a/examples/transports/LICENSE b/examples/transports/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/transports/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/transports/LICENSE-APACHE b/examples/transports/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/transports/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/transports/LICENSE-MIT b/examples/transports/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/transports/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/transports/README.md b/examples/transports/README.md deleted file mode 100644 index eac5a5009a..0000000000 --- a/examples/transports/README.md +++ /dev/null @@ -1,336 +0,0 @@ -# @libp2p/example-transports - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> An example using different types of libp2p transport - -## Table of contents - -- [1. Creating a libp2p node with TCP](#1-creating-a-libp2p-node-with-tcp) -- [2. Dialing from one node to another node](#2-dialing-from-one-node-to-another-node) -- [3. Using multiple transports](#3-using-multiple-transports) -- [4. How to create a new libp2p transport](#4-how-to-create-a-new-libp2p-transport) -- [License](#license) -- [Contribution](#contribution) - -A more complete definition of what is a transport can be found on the [interface-transport] specification. A way to recognize a candidate transport is through the badge: - -![][interface-transport badge] - -## 1. Creating a libp2p node with TCP - -When using libp2p, you need properly configure it, that is, pick your set of modules and create your network stack with the properties you need. In this example, we will create a libp2p node TCP. You can find the complete solution on the file [1.js](./1.js). - -You will need 4 dependencies total, so go ahead and install all of them with: - -```bash -> npm install libp2p @libp2p/tcp @chainsafe/libp2p-noise -``` - -Then, in your favorite text editor create a file with the `.js` extension. I've called mine `1.js`. - -First thing is to create our own libp2p node! Insert: - -```JavaScript -import { createLibp2p } from 'libp2p' -import { tcp } from '@libp2p/tcp' -import { noise } from '@chainsafe/libp2p-noise' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - // To signal the addresses we want to be available, we use - // the multiaddr format, a self describable address - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [ - tcp() - ], - connectionEncryption: [ - noise() - ] - }) - - return node -} -``` - -Now that we have a function to create our own libp2p node, let's create a node with it. - -```JavaScript -const node = await createNode() - -// At this point the node has started -console.log('node has started (true/false):', node.isStarted()) -// And we can print the now listening addresses. -// If you are familiar with TCP, you might have noticed -// that we specified the node to listen in 0.0.0.0 and port -// 0, which means "listen in any network interface and pick -// a port for me -console.log('listening on:') -node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) -``` - -Running this should result in something like: - -```bash -> node 1.js -node has started (true/false): true -listening on: -/ip4/127.0.0.1/tcp/61329/p2p/QmW2cKTakTYqbQkUzBTEGXgWYFj1YEPeUndE1YWs6CBzDQ -/ip4/192.168.2.156/tcp/61329/p2p/QmW2cKTakTYqbQkUzBTEGXgWYFj1YEPeUndE1YWs6CBzDQ -``` - -That `QmW2cKTakTYqbQkUzBTEGXgWYFj1YEPeUndE1YWs6CBzDQ` is the PeerId that was created during the PeerInfo generation. - -## 2. Dialing from one node to another node - -Now that we have our `createNode` function, let's create two nodes and make them dial to each other! You can find the complete solution at [2.js](./2.js). - -For this step, we will need some more dependencies. - -```bash -> npm install it-pipe it-all @libp2p/mplex -``` - -And we also need to import the modules on our .js file: - -```js -import { pipe } from 'it-pipe' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' -import all from 'it-all' -``` - -We are going to reuse the `createNode` function from step 1, but this time add a stream multiplexer from `libp2p-mplex`. - -```js -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - // To signal the addresses we want to be available, we use - // the multiaddr format, a self describable address - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - connectionEncryption: [noise()], - streamMuxers: [yamux(), mplex()] // <--- Add this line - }) - - return node -} -``` - -We will also make things simpler by creating another function to print the multiaddresses to avoid duplicating code. - -```JavaScript -function printAddrs (node, number) { - console.log('node %s is listening on:', number) - node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) -} -``` - -Then add, - -```js -import { fromString as uint8ArrayFromString } from "uint8arrays/from-string"; -import { toString as uint8ArrayToString } from "uint8arrays/to-string"; - -const [node1, node2] = await Promise.all([ - createNode(), - createNode() -]) - -printAddrs(node1, '1') -printAddrs(node2, '2') - -node2.handle('/print', async ({ stream }) => { - const result = await pipe( - stream, - all - ) - console.log(result.map(buf => uint8ArrayToString(buf.subarray())).join("")) -}) - -await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() -}) -const stream = await node1.dialProtocol(node2.peerId, '/print') - -await pipe( - ['Hello', ' ', 'p2p', ' ', 'world', '!'].map(str => uint8ArrayFromString(str)), - stream -) -``` - -For more information refer to the [docs](https://github.com/libp2p/js-libp2p/blob/master/doc/API.md). - -The result should look like: - -```bash -> node 2.js -node 1 is listening on: -/ip4/127.0.0.1/tcp/62279/p2p/QmeM4wNWv1uci7UJjUXZYfvcy9uqAbw7G9icuxdqy88Mj9 -/ip4/192.168.2.156/tcp/62279/p2p/QmeM4wNWv1uci7UJjUXZYfvcy9uqAbw7G9icuxdqy88Mj9 -node 2 is listening on: -/ip4/127.0.0.1/tcp/62278/p2p/QmWp58xJgzbouNJcyiNNTpZuqQCJU8jf6ixc7TZT9xEZhV -/ip4/192.168.2.156/tcp/62278/p2p/QmWp58xJgzbouNJcyiNNTpZuqQCJU8jf6ixc7TZT9xEZhV -Hello p2p world! -``` - -## 3. Using multiple transports - -Next, we want nodes to have multiple transports available to increase their chances of having a common transport in the network to communicate over. A simple scenario is a node running in the browser only having access to HTTP, WebSockets and WebRTC since the browser doesn't let you open any other kind of transport. For this node to dial to some other node, that other node needs to share a common transport. - -What we are going to do in this step is to create 3 nodes: one with TCP, another with TCP+WebSockets and another one with just WebSockets. The full solution can be found on [3.js](./3.js). - -In this example, we will need to also install `@libp2p/websockets`: - -```bash -> npm install @libp2p/websockets -``` - -We want to create 3 nodes: one with TCP, one with TCP+WebSockets and one with just WebSockets. We need to update our `createNode` function to accept WebSocket connections as well. Moreover, let's upgrade our function to enable us to pick the addresses over which a node will start a listener: - -```JavaScript -// ... - -const createNode = async (transports, addresses = []) => { - if (!Array.isArray(addresses)) { - addresses = [addresses] - } - - const node = await createLibp2p({ - addresses: { - listen: addresses - }, - transports: transports, - connectionEncryption: [noise()], - streamMuxers: [yamux(), mplex()] - }) - - return node -} -``` - -As a rule, a libp2p node will only be capable of using a transport if: a) it has the module for it and b) it was given a multiaddr to listen on. The only exception to this rule is WebSockets in the browser, where a node can dial out, but unfortunately cannot open a socket. - -Let's update our flow to create nodes and see how they behave when dialing to each other: - -```JavaScript -import { webSockets } from '@libp2p/websockets' -import { tcp } from '@libp2p/tcp' - -const [node1, node2, node3] = await Promise.all([ - createNode([tcp()], '/ip4/0.0.0.0/tcp/0'), - createNode([tcp(), webSockets()], ['/ip4/0.0.0.0/tcp/0', '/ip4/127.0.0.1/tcp/10000/ws']), - createNode([webSockets()], '/ip4/127.0.0.1/tcp/20000/ws') -]) - -printAddrs(node1, '1') -printAddrs(node2, '2') -printAddrs(node3, '3') - -node1.handle('/print', print) -node2.handle('/print', print) -node3.handle('/print', print) - -await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() -}) -await node2.peerStore.patch(node3.peerId, { - multiaddrs: node3.getMultiaddrs() -}) -await node3.peerStore.patch(node1.peerId, { - multiaddrs: node1.getMultiaddrs() -}) - -// node 1 (TCP) dials to node 2 (TCP+WebSockets) -const stream = await node1.dialProtocol(node2.peerId, '/print') -await pipe( - ['node 1 dialed to node 2 successfully'].map(str => uint8ArrayFromString(str)), - stream -) - -// node 2 (TCP+WebSockets) dials to node 3 (WebSockets) -const stream2 = await node2.dialProtocol(node3.peerId, '/print') -await pipe( - ['node 2 dialed to node 3 successfully'].map(str => uint8ArrayFromString(str)), - stream2 -) - -// node 3 (WebSockets) attempts to dial to node 1 (TCP) -try { - await node3.dialProtocol(node1.peerId, '/print') -} catch (err) { - console.log('node 3 failed to dial to node 1 with:', err.message) -} -``` - -`print` is a function that prints each piece of data from a stream onto a new line but factored into its own function to save lines: - -```JavaScript -function print ({ stream }) { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) -} -``` - -If everything was set correctly, you now should see something similar to the following after running the script: - -```Bash -> node 3.js -node 1 is listening on: -/ip4/127.0.0.1/tcp/62620/p2p/QmWpWmcVJkF6EpmAaVDauku8g1uFGuxPsGP35XZp9GYEqs -/ip4/192.168.2.156/tcp/62620/p2p/QmWpWmcVJkF6EpmAaVDauku8g1uFGuxPsGP35XZp9GYEqs -node 2 is listening on: -/ip4/127.0.0.1/tcp/10000/ws/p2p/QmWAQtWdzWXibgfyc7WRHhhv6MdqVKzXvyfSTnN2aAvixX -/ip4/127.0.0.1/tcp/62619/p2p/QmWAQtWdzWXibgfyc7WRHhhv6MdqVKzXvyfSTnN2aAvixX -/ip4/192.168.2.156/tcp/62619/p2p/QmWAQtWdzWXibgfyc7WRHhhv6MdqVKzXvyfSTnN2aAvixX -node 3 is listening on: -/ip4/127.0.0.1/tcp/20000/ws/p2p/QmVq1PWh3VSDYdFqYMtqp4YQyXcrH27N7968tGdM1VQPj1 -node 1 dialed to node 2 successfully -node 2 dialed to node 3 successfully -node 3 failed to dial to node 1 with: - Error: No transport available for address /ip4/127.0.0.1/tcp/51482 -``` - -As expected, we created 3 nodes: node 1 with TCP, node 2 with TCP+WebSockets and node 3 with just WebSockets. node 1 -> node 2 and node 2 -> node 3 managed to dial correctly because they shared a common transport; however, node 3 -> node 1 failed because they didn't share any. - -## 4. How to create a new libp2p transport - -Today there are already several transports available and plenty to come. You can find these at [interface-transport implementations] list. - -Adding more transports is done through the same way as you added TCP and WebSockets. Some transports might offer extra functionalities, but as far as libp2p is concerned, if it follows the interface defined in the [spec][interface-transport api] it will be able to use it. - -If you decide to implement a transport yourself, please consider adding to the list so that others can use it as well. - -Hope this tutorial was useful. We are always looking to improve it, so contributions are welcome! - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. - -[interface-transport]: https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/transport - -[interface-transport badge]: https://raw.githubusercontent.com/libp2p/js-libp2p-interfaces/master/packages/libp2p-interfaces/src/transport/img/badge.png - -[interface-transport implementations]: https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/transport#modules-that-implement-the-interface - -[interface-transport api]: https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/transport#api diff --git a/examples/transports/package.json b/examples/transports/package.json deleted file mode 100644 index c5c06b6f19..0000000000 --- a/examples/transports/package.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "name": "@libp2p/example-transports", - "version": "0.0.0", - "description": "An example using different types of libp2p transport", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/transports#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/tcp": "^8.0.0", - "@libp2p/websockets": "^7.0.0", - "it-pipe": "^3.0.1", - "it-to-buffer": "^4.0.2", - "libp2p": "^0.46.0", - "uint8arrays": "^4.0.6" - }, - "devDependencies": { - "aegir": "^41.0.2", - "test-ipfs-example": "^1.0.0" - }, - "private": true -} diff --git a/examples/transports/test-1.js b/examples/transports/test-1.js deleted file mode 100644 index d94544ce17..0000000000 --- a/examples/transports/test-1.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('1.js\n') - - await waitForOutput('/p2p/', 'node', [path.join(__dirname, '1.js')], { - cwd: __dirname - }) -} diff --git a/examples/transports/test-2.js b/examples/transports/test-2.js deleted file mode 100644 index f254851cb9..0000000000 --- a/examples/transports/test-2.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('2.js\n') - - await waitForOutput('Hello p2p world!', 'node', [path.join(__dirname, '2.js')], { - cwd: __dirname - }) -} diff --git a/examples/transports/test-3.js b/examples/transports/test-3.js deleted file mode 100644 index 242af9a737..0000000000 --- a/examples/transports/test-3.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('3.js\n') - - await waitForOutput('node 3 failed to dial to node 1 with:', 'node', [path.join(__dirname, '3.js')], { - cwd: __dirname - }) -} diff --git a/examples/transports/test-4.js b/examples/transports/test-4.js deleted file mode 100644 index 6c4850e08b..0000000000 --- a/examples/transports/test-4.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('4.js\n') - - await waitForOutput('node 2 dialed to node 1 successfully', 'node', [path.join(__dirname, '4.js')], { - cwd: __dirname - }) -} diff --git a/examples/transports/test.js b/examples/transports/test.js deleted file mode 100644 index bc53a61f46..0000000000 --- a/examples/transports/test.js +++ /dev/null @@ -1,9 +0,0 @@ -import { test as test1 } from './test-1.js' -import { test as test2 } from './test-2.js' -import { test as test3 } from './test-3.js' -import { test as test4 } from './test-4.js' - -await test1() -await test2() -await test3() -await test4() diff --git a/examples/transports/test_certs/cert.pem b/examples/transports/test_certs/cert.pem deleted file mode 100644 index 0574192b2c..0000000000 --- a/examples/transports/test_certs/cert.pem +++ /dev/null @@ -1,32 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFlzCCA3+gAwIBAgIUMYedwb9L/BtvZ7Lhu71iSKrXsa4wDQYJKoZIhvcNAQEL -BQAwajELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMREwDwYDVQQHDAhTb21lQ2l0 -eTESMBAGA1UECgwJTXlDb21wYW55MRMwEQYDVQQLDApNeURpdmlzaW9uMRIwEAYD -VQQDDAkxMjcuMC4wLjEwHhcNMjEwNDI4MDIzMjA5WhcNMjIwNDI4MDIzMjA5WjBq -MQswCQYDVQQGEwJVUzELMAkGA1UECAwCVkExETAPBgNVBAcMCFNvbWVDaXR5MRIw -EAYDVQQKDAlNeUNvbXBhbnkxEzARBgNVBAsMCk15RGl2aXNpb24xEjAQBgNVBAMM -CTEyNy4wLjAuMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANNhXBu0 -GH1Kzl9iaQxCxEnyyAShS5FYScdKxqpYsgJT4poLWLQBZQEFLEqbdillIlTZqMss -jWqkFL2xmjqdcnOKFEZUarntVE2hxFYYQex2Fi8MYwFj+Pvt74d02xPyfzFNFgyX -a1EakoGBwClaf3I7jW7raPudjcf4HnwQ7r/NwiO8FqHFZgLcTnwI8bk+cxDoDAqu -mhqMB5nnerqvKEyR9Fb2PoL+8PwOPJOOKTDVwLMeMJu2WLR8AU2FzOj5SVI2qsu9 -Ps5azysD8KQAMcw4y9s6do36SaMQS85fbvXBV7XBqMD34HPBUbFiCoFoaCzK9Zfb -pCXyVJMUNmw5hyq9nbjUt4Kvr/58bU2gjUKSdPf6KhBxFnDZwl+2qqPdVIb/qtwz -HExtJWq3upklXNOg3HoR6vcr1O9ReJHrzLRMEb51WP1aN/qJ2/lRskcZ4A806qwr -W67BvnOg6s3ZtxHN9v3bsyfsvC66w8PEfCnCVxugC7cUW0gtW54AU75T3ukg7X+m -vECr/+qIzNEBIxxCPgefCG/JAdJhQ5SCvoARAVPStUIWDmigDeOt7go5nKbdVIJ4 -7bbBFUhHT2mTHu30fHhRqSDcHzwE7Zz6YJIJmKq29UmzUazFnKlLU67MjLJwiDPm -fC3GyOdAWkkZE5hjtkiy+3yWoEHhaJYRI1u3AgMBAAGjNTAzMAsGA1UdDwQEAwIE -MDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHREECDAGhwR/AAABMA0GCSqGSIb3 -DQEBCwUAA4ICAQCx/ynu4iCQAK8VId/QQe7GqgOpFgx+6Mce9GQC6ZVEjAPgapsS -Pl+l6+11cFjHKv0+Z/iN2JgkFmNXfwJcfYI0tHbMK+0U9hgKb1eFgiIwCqb4cPOz -wMwusZ95BjIbtcEbL/+pMUpNhmjPz1fOILJZtDVq++lqJCv7t8+SoAmMVYtlcLNg -muuV/UYR3uqvnAJmjgJVWs4otDGrxCYJE48M+9L2Gm05Htpi9WL1bZaQ+fJ85m85 -daedLc6R1/ZRTIH6i73sD4rYs0bx1fCJvkbcgXtKMHEkiHuG/MzR7Pa4cJAVKCx9 -lRTgrO7Gkllt2+jp4qg0YhdNq89e0DNA5cyB9H4udRgHQOcrlVRiX9OD/Kz+F5m/ -fQwMdbnqdg3ar5DSa8Q5g3bdLbNSCcI9sjCLTkNxUC/XTWGdG03RCVIt1qvBvZHk -JaG6xGpbRZ5CN0T9eindd38JBrkPAPfgl6qhwvcqh6uVFYua+7KmF9K+mKarlmMw -6RWaw2j4sMgUyRIS6fR9vDc20SrtoNvKQM1U6+0VYs1nizfkmsqqqRODmERKbKwc -ahKJFubXfr8gz+PipAKFZbxr2EPAyoiNkx+0eM6Eedo55oP2BoGHEfXEoAonyMFM -F/xTbpFtdRYE2hwsZCk86fpbcPTmdCY8txeZ7+4Bme2d9XXsTAxF64usqQ== ------END CERTIFICATE----- diff --git a/examples/transports/test_certs/key.pem b/examples/transports/test_certs/key.pem deleted file mode 100644 index dfee30176f..0000000000 --- a/examples/transports/test_certs/key.pem +++ /dev/null @@ -1,52 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDTYVwbtBh9Ss5f -YmkMQsRJ8sgEoUuRWEnHSsaqWLICU+KaC1i0AWUBBSxKm3YpZSJU2ajLLI1qpBS9 -sZo6nXJzihRGVGq57VRNocRWGEHsdhYvDGMBY/j77e+HdNsT8n8xTRYMl2tRGpKB -gcApWn9yO41u62j7nY3H+B58EO6/zcIjvBahxWYC3E58CPG5PnMQ6AwKrpoajAeZ -53q6ryhMkfRW9j6C/vD8DjyTjikw1cCzHjCbtli0fAFNhczo+UlSNqrLvT7OWs8r -A/CkADHMOMvbOnaN+kmjEEvOX271wVe1wajA9+BzwVGxYgqBaGgsyvWX26Ql8lST -FDZsOYcqvZ241LeCr6/+fG1NoI1CknT3+ioQcRZw2cJftqqj3VSG/6rcMxxMbSVq -t7qZJVzToNx6Eer3K9TvUXiR68y0TBG+dVj9Wjf6idv5UbJHGeAPNOqsK1uuwb5z -oOrN2bcRzfb927Mn7LwuusPDxHwpwlcboAu3FFtILVueAFO+U97pIO1/prxAq//q -iMzRASMcQj4HnwhvyQHSYUOUgr6AEQFT0rVCFg5ooA3jre4KOZym3VSCeO22wRVI -R09pkx7t9Hx4Uakg3B88BO2c+mCSCZiqtvVJs1GsxZypS1OuzIyycIgz5nwtxsjn -QFpJGROYY7ZIsvt8lqBB4WiWESNbtwIDAQABAoICAQCpGV3iG7Trpohp7gQzdsYo -kjxI1+/oGkULVVqQs9vT2N+SdDlF50eyBT1lgfCJNQq97lIGF2IaSaD+D7Jd6c7B -d1i42pd2ndGvORYj+cvjKqSchsA9QIjSoYnZRzZrQrdV7WESOZ/0hdlmGTJs4qTJ -8bI3ZcPaZjQiIO/iOHmGn0gL5lAEojH1X+C5gT4+/yJ2B+x6LyvAyPzbtj6MUctf -VfOuDdf8W47VVV5IfJWfJ6C8qg4gw0M7P2ibZ8qBJcvuJSWFT6OK2UKaGtDLogw0 -X8tVWfO1qOB3vnWmZtoRZ9aO5JnnpWS9tY1w5gmZdLjB/Kt0DJXIdZALCURwV6U0 -q5XR0SETEgdRrNX92PA2lmxO9fAgXRSjP/OoeDjAVhnRfYyShDbEIb8GHk7nE+is -6ak5ufxKE53S8wB9L7MTPqTvxusBHi8saLevdnPBMQPvtEVkg2Iw/iPBsegUuUjD -uzXlq4WUMCUBJEMVPuYEsaQizxpp2oM6AZj/ecuTKFX5CirFFWKOQ4cp+O8lrfI5 -ruwHrMkfjowDYcQaOLHq13anvt8+8LBlngVw+jiAGB/bGwrAwEZWUc8i1HbH/G8e -sm0kMuCqV1GbRyMCUO3pWjzrsz8LEy74Jr0z7KZn52vLWrTkiD4NRXahxTBhHpXb -AVclJ+a4BKk2rRJVRFRRQQKCAQEA7+uTl2ZHp1v7A8/I2zPIxoVz0fiwxwAjuv34 -cV+uxG0n5Tko4PKMxavddRFKNeGvrz0aO/GNX8NIW7pDqZ2CwHyskgUX/bFAqGKF -Z/z2DmiZ2rdSUH89O3ysq+OF3RjX/FBNJ0SVdwtrpz3kCSWpa4PnmN7+IevL6zxY -8gLrs07Ge+ci94FZaDHBNrkGQ00krbOmwIvnc90hyRPCKfMS+u2/ejKZ5QDyRG+H -jbQ008ZV2OqUdS6h1twfoJ1Q4QhHijB6PegRLGdZGuUXIQfFP8dIUsQluKSUFyOy -bL9W2yBwtbn3EwYDHLJQnLICxfcTBWg/2vOIucsSjxG7KNY0yQKCAQEA4YwcVpi3 -D+8OcnbpRBRlHo84DRZorp0RO8vhxevvB1CcBnkLRIYXlS2JIfrnhZAI/5jBk1ei -FmgRFyAjZ8gDdkDCiDMQMDUwUhLGSVurI9sk16B4TQKCM+iE0LDrXIy9ezJRJkj0 -rOt8sqo2/TOttm2KEXY8Cco59tU4bMZg5Tr9l7SMTTj4skTO6Jn6/6hX3XuFkJw7 -B0DsSzIqXyRHAzOidagIEoIr7k4cEGXsrSWoSiHg/eky1ihCyUw3vDDOmoViBR7s -h5nLjQNNAzOtyoKLqST7B7uXkdUo5nV2IUHSGD5LNxlTaNp0XL9Ph3EBtcuwNuB6 -zyKXc+O5iNfMfwKCAQEA5/RJKCnRgsORxpif5xWEujIRzOHz/yFqagHarbnFHNEv -rhT6Kak2YnIL1H/X0IoWsYSQlX2uofQKQ+ysOBM5c2HV8gKMtFAnY+SEeAn/1eRZ -QzTTl1G84INj6Xc6V40KXD1CqoFLQ+G9vd4/Vnyb9H99bLXC2wa+ivo4QBqEyEGT -8fyAOOxMhUj9NSvjGzQ9DtbOk/9u0PztChtZL/d61TEAW2MKmHW2xGVTl7OvE0QA -gYwh5b0k6La+uSj/JeE8USUXOjzgRZ7RbggouV1q3YOMr8BFe+NZ7Zksiqjej1Io -xfk6H6FDZv4ao7QSrFR4hlTIz6V9/aqQkdOhsBSQyQKCAQEAzHwz4Qr5xVduGLbY -S6HV/7vHDI6Jf+3lBvqUidWa013w5yls3sZXsSckkgshRoVMszayIbystnXJMNcx -YlEDWn3iIItzHNHMKkzdOvsCETMIlvnkt6UTmK4xY+dSq4jp7Ty0N+qi8fdaCb2q -tyrYTnHHYId6bUHMBY5QZsYAaTNvYNAO96A0UaNyl42q84iTiLkJYg9SsQPad15W -7gU84Jk6rEMYdndQDvEAHpnZ1y0yA2vtySZYsbK0wj34tgTl+0/8izn7JgF4ezNH -6iQ7Z0OuDT763IrmIxBH0ZEi9YnwSYyIsr6iUYjlQIUuPFRnQYQXEdm5Xfw1pZsL -xhYoTwKCAQB9edDe4LX+0z9i4qr0iHV8H/WoyI5UD/Pc217PKkYM3+ewR9SL9D9z -TS78Sl7HgRgEmIu+MR/u5B2ePf7jkvB/oxyPwqAzJeJ72mV3Mevm27G/Ndd8lt5W -FBCGOx7ZeP4/Cv4mvPD979ix2IalDoWMSWJnpQPN+B1jGeCrUYAXQc1k/vU99gLa -8Tuu3WfBpVAsO7hAC9mu6tuLyfKVqiMOVs2aky9xLqiqW/6uIcGu+owrr+gkDDY/ -JfBSUfxYKcjtJiHOEbFGrrRe93XsngmaTz/Hv9A/QLVCuJgWEHlt4WHSc+BtAtaV -9avp6VlyVNfe4KEKW7IekrI0cmfMdXkl ------END PRIVATE KEY----- diff --git a/interop/CHANGELOG.md b/interop/CHANGELOG.md index fb517accc5..e2788114ec 100644 --- a/interop/CHANGELOG.md +++ b/interop/CHANGELOG.md @@ -1,5 +1,30 @@ # Changelog +### [1.0.8](https://www.github.com/libp2p/js-libp2p/compare/multidim-interop-v1.0.7...multidim-interop-v1.0.8) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/mplex bumped from ^9.0.8 to ^9.0.9 + * @libp2p/tcp bumped from ^8.0.9 to ^8.0.10 + * @libp2p/webrtc bumped from ^3.2.4 to ^3.2.5 + * @libp2p/websockets bumped from ^7.0.9 to ^7.0.10 + * @libp2p/webtransport bumped from ^3.1.4 to ^3.1.5 + * libp2p bumped from ^0.46.15 to ^0.46.16 + +### [1.0.7](https://www.github.com/libp2p/js-libp2p/compare/multidim-interop-v1.0.6...multidim-interop-v1.0.7) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/webrtc bumped from ^3.2.3 to ^3.2.4 + * @libp2p/webtransport bumped from ^3.1.3 to ^3.1.4 + * libp2p bumped from ^0.46.14 to ^0.46.15 + ### [1.0.6](https://www.github.com/libp2p/js-libp2p/compare/multidim-interop-v1.0.5...multidim-interop-v1.0.6) (2023-10-10) diff --git a/interop/package.json b/interop/package.json index 3ab015c03a..a3b0ff64c5 100644 --- a/interop/package.json +++ b/interop/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/multidim-interop", - "version": "1.0.6", + "version": "1.0.8", "description": "Multidimensional interop tests", "author": "Glen De Cauwsemaecker / @marcopolo", "license": "Apache-2.0 OR MIT", @@ -47,20 +47,21 @@ "start": "node index.js", "build": "aegir build", "lint": "aegir lint", - "test:interop:multidim": "aegir test" + "test:interop:multidim": "aegir test", + "test:transport:interop": "aegir test" }, "dependencies": { "@chainsafe/libp2p-noise": "^13.0.0", "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/mplex": "^9.0.8", - "@libp2p/tcp": "^8.0.9", - "@libp2p/webrtc": "^3.2.3", - "@libp2p/websockets": "^7.0.9", - "@libp2p/webtransport": "^3.1.3", + "@libp2p/mplex": "^9.0.9", + "@libp2p/tcp": "^8.0.10", + "@libp2p/webrtc": "^3.2.5", + "@libp2p/websockets": "^7.0.10", + "@libp2p/webtransport": "^3.1.5", "@multiformats/mafmt": "^12.1.2", "@multiformats/multiaddr": "^12.1.5", "aegir": "^41.0.2", - "libp2p": "^0.46.14", + "libp2p": "^0.46.16", "redis": "^4.5.1" }, "browser": { diff --git a/package.json b/package.json index bb6e033168..c36b0ac005 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ }, "private": true, "scripts": { - "reset": "aegir run clean && aegir clean interop/node_modules examples/*/node_modules packages/*/node_modules node_modules package-lock.json packages/*/package-lock.json examples/*/package-lock.json interop/*/package-lock.json", + "reset": "aegir run clean && aegir clean interop/node_modules packages/*/node_modules node_modules package-lock.json packages/*/package-lock.json interop/*/package-lock.json", "test": "aegir run test", "test:node": "aegir run test:node", "test:chrome": "aegir run test:chrome", @@ -21,10 +21,8 @@ "test:firefox": "aegir run test:firefox", "test:firefox-webworker": "aegir run test:firefox-webworker", "test:electron-main": "aegir run test:electron-main", - "test:external": "aegir run test:external", "test:cli": "aegir run test:cli", "test:interop": "aegir run test:interop", - "test:example": "aegir run test:example", "coverage": "aegir run coverage", "build": "aegir run build", "clean": "aegir run clean", @@ -33,8 +31,8 @@ "release": "run-s build docs:no-publish npm:release docs", "npm:release": "aegir exec --bail false npm -- publish", "release:rc": "aegir release-rc", - "docs": "NODE_OPTIONS=--max_old_space_size=8192 aegir docs -- --exclude interop --exclude examples/auto-relay --exclude examples/chat --exclude examples/connection-encryption --exclude examples/delegated-routing --exclude examples/discovery-mechanisms --exclude examples/echo --exclude examples/peer-and-content-routing --exclude examples/pnet --exclude examples/protocol-and-stream-muxing --exclude examples/pubsub --exclude examples/transports --exclude doc", - "docs:no-publish": "NODE_OPTIONS=--max_old_space_size=8192 aegir docs --publish false -- --exclude interop --exclude examples/auto-relay --exclude examples/chat --exclude examples/connection-encryption --exclude examples/delegated-routing --exclude examples/discovery-mechanisms --exclude examples/echo --exclude examples/peer-and-content-routing --exclude examples/pnet --exclude examples/protocol-and-stream-muxing --exclude examples/pubsub --exclude examples/transports --exclude doc" + "docs": "aegir docs", + "docs:no-publish": "aegir docs --publish false -- --exclude interop --exclude doc" }, "devDependencies": { "aegir": "^41.0.2" @@ -47,7 +45,6 @@ }, "workspaces": [ "doc", - "examples/*", "interop", "packages/*" ] diff --git a/packages/crypto/CHANGELOG.md b/packages/crypto/CHANGELOG.md index 4f89fc5f0e..3c06dbad1d 100644 --- a/packages/crypto/CHANGELOG.md +++ b/packages/crypto/CHANGELOG.md @@ -5,6 +5,15 @@ * **dev:** bump aegir from 38.1.8 to 39.0.5 ([#320](https://github.com/libp2p/js-libp2p-crypto/issues/320)) ([f0b4c06](https://github.com/libp2p/js-libp2p-crypto/commit/f0b4c068a23d78b1376865c6adf6cce21ab91196)) +### [2.0.6](https://www.github.com/libp2p/js-libp2p/compare/crypto-v2.0.5...crypto-v2.0.6) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + ### [2.0.5](https://www.github.com/libp2p/js-libp2p/compare/crypto-v2.0.4...crypto-v2.0.5) (2023-10-06) diff --git a/packages/crypto/README.md b/packages/crypto/README.md index a1ab936c74..740c1e2074 100644 --- a/packages/crypto/README.md +++ b/packages/crypto/README.md @@ -1,5 +1,3 @@ -# @libp2p/crypto - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,45 +5,13 @@ > Crypto primitives for libp2p -## Table of contents - -- [Install](#install) - - [Browser ` ``` -This repo contains the JavaScript implementation of the crypto primitives needed for libp2p. This is based on this [go implementation](https://github.com/libp2p/go-libp2p-crypto). - -## Lead Maintainer - -[Jacob Heun](https://github.com/jacobheun/) - -## Usage - -```js -const crypto = require('libp2p-crypto') - -// Now available to you: -// -// crypto.aes -// crypto.hmac -// crypto.keys -// etc. -// -// See full API details below... -``` - -### Web Crypto API - -The `libp2p-crypto` library depends on the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) in the browser. Web Crypto is available in all modern browsers, however browsers restrict its usage to [Secure Contexts](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts). - -**This means you will not be able to use some `libp2p-crypto` functions in the browser when the page is served over HTTP.** To enable the Web Crypto API and allow `libp2p-crypto` to work fully, please serve your page over HTTPS. - -## API - -### `crypto.aes` - -Exposes an interface to AES encryption (formerly Rijndael), as defined in U.S. Federal Information Processing Standards Publication 197. - -This uses `CTR` mode. - -#### `crypto.aes.create(key, iv)` - -- `key: Uint8Array` The key, if length `16` then `AES 128` is used. For length `32`, `AES 256` is used. -- `iv: Uint8Array` Must have length `16`. - -Returns `Promise<{decrypt, encrypt}>` - -##### `decrypt(data)` - -- `data: Uint8Array` - -Returns `Promise` - -##### `encrypt(data)` - -- `data: Uint8Array` - -Returns `Promise` - -```js -const crypto = require('libp2p-crypto') - -// Setting up Key and IV - -// A 16 bytes array, 128 Bits, AES-128 is chosen -const key128 = Uint8Array.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) - -// A 16 bytes array, 128 Bits, -const IV = Uint8Array.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) - -async function main () { - const decryptedMessage = 'Hello, world!' - - // Encrypting - const cipher = await crypto.aes.create(key128, IV) - const encryptedBuffer = await cipher.encrypt(Uint8Array.from(decryptedMessage)) - console.log(encryptedBuffer) - // prints: - - // Decrypting - const decipher = await crypto.aes.create(key128, IV) - const decryptedBuffer = await cipher.decrypt(encryptedBuffer) - - console.log(decryptedBuffer) - // prints: - - console.log(decryptedBuffer.toString('utf-8')) - // prints: Hello, world! -} - -main() -``` - -### `crypto.hmac` - -Exposes an interface to the Keyed-Hash Message Authentication Code (HMAC) as defined in U.S. Federal Information Processing Standards Publication 198. An HMAC is a cryptographic hash that uses a key to sign a message. The receiver verifies the hash by recomputing it using the same key. - -#### `crypto.hmac.create(hash, secret)` - -- `hash: String` -- `secret: Uint8Array` - -Returns `Promise<{digest}>` - -##### `digest(data)` - -- `data: Uint8Array` - -Returns `Promise` - -Example: - -```js -const crypto = require('libp2p-crypto') - -async function main () { - const hash = 'SHA1' // 'SHA256' || 'SHA512' - const hmac = await crypto.hmac.create(hash, uint8ArrayFromString('secret')) - const sig = await hmac.digest(uint8ArrayFromString('hello world')) - console.log(sig) -} - -main() -``` - -### `crypto.keys` - -**Supported Key Types** - -The [`generateKeyPair`](#generatekeypairtype-bits), [`marshalPublicKey`](#marshalpublickeykey-type), and [`marshalPrivateKey`](#marshalprivatekeykey-type) functions accept a string `type` argument. - -Currently the `'RSA'`, `'ed25519'`, and `secp256k1` types are supported, although ed25519 and secp256k1 keys support only signing and verification of messages. For encryption / decryption support, RSA keys should be used. - -### `crypto.keys.generateKeyPair(type, bits)` - -- `type: String`, see [Supported Key Types](#supported-key-types) above. -- `bits: Number` Minimum of 1024 - -Returns `Promise<{privateKey, publicKey}>` - -Generates a keypair of the given type and bitsize. - -### `crypto.keys.generateEphemeralKeyPair(curve)` - -- `curve: String`, one of `'P-256'`, `'P-384'`, `'P-521'` is currently supported - -Returns `Promise` - -Generates an ephemeral public key and returns a function that will compute the shared secret key. - -Focuses only on ECDH now, but can be made more general in the future. - -Resolves to an object of the form: - -```js -{ - key: Uint8Array, - genSharedKey: Function -} -``` - -### `crypto.keys.keyStretcher(cipherType, hashType, secret)` - -- `cipherType: String`, one of `'AES-128'`, `'AES-256'`, `'Blowfish'` -- `hashType: String`, one of `'SHA1'`, `SHA256`, `SHA512` -- `secret: Uint8Array` - -Returns `Promise` - -Generates a set of keys for each party by stretching the shared key. - -Resolves to an object of the form: - -```js -{ - k1: { - iv: Uint8Array, - cipherKey: Uint8Array, - macKey: Uint8Array - }, - k2: { - iv: Uint8Array, - cipherKey: Uint8Array, - macKey: Uint8Array - } -} -``` - -### `crypto.keys.marshalPublicKey(key, [type])` - -- `key: keys.rsa.RsaPublicKey | keys.ed25519.Ed25519PublicKey | keys.secp256k1.Secp256k1PublicKey` -- `type: String`, see [Supported Key Types](#supported-key-types) above. Defaults to 'rsa'. - -Returns `Uint8Array` - -Converts a public key object into a protobuf serialized public key. - -### `crypto.keys.unmarshalPublicKey(buf)` - -- `buf: Uint8Array` - -Returns `RsaPublicKey|Ed25519PublicKey|Secp256k1PublicKey` - -Converts a protobuf serialized public key into its representative object. - -### `crypto.keys.marshalPrivateKey(key, [type])` - -- `key: keys.rsa.RsaPrivateKey | keys.ed25519.Ed25519PrivateKey | keys.secp256k1.Secp256k1PrivateKey` -- `type: String`, see [Supported Key Types](#supported-key-types) above. - -Returns `Uint8Array` - -Converts a private key object into a protobuf serialized private key. - -### `crypto.keys.unmarshalPrivateKey(buf)` - -- `buf: Uint8Array` - -Returns `Promise` - -Converts a protobuf serialized private key into its representative object. - -### `crypto.keys.import(encryptedKey, password)` - -- `encryptedKey: string` -- `password: string` - -Returns `Promise` - -Converts an exported private key into its representative object. Supported formats are 'pem' (RSA only) and 'libp2p-key'. - -### `privateKey.export(password, format)` - -- `password: string` -- `format: string` the format to export to: 'pem' (rsa only), 'libp2p-key' - -Returns `string` - -Exports the password protected `PrivateKey`. RSA keys will be exported as password protected PEM by default. Ed25519 and Secp256k1 keys will be exported as password protected AES-GCM base64 encoded strings ('libp2p-key' format). - -### `crypto.randomBytes(number)` - -- `number: Number` - -Returns `Uint8Array` - -Generates a Uint8Array with length `number` populated by random bytes. - -### `crypto.pbkdf2(password, salt, iterations, keySize, hash)` - -- `password: String` -- `salt: String` -- `iterations: Number` -- `keySize: Number` in bytes -- `hash: String` the hashing algorithm ('sha1', 'sha2-512', ...) - -Computes the Password Based Key Derivation Function 2; returning a new password. - -## Contribute +# Contribute Feel free to join in. All welcome. Open an [issue](https://github.com/libp2p/js-libp2p-crypto/issues)! @@ -314,17 +27,17 @@ This repository falls under the IPFS [Code of Conduct](https://github.com/ipfs/c [![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/contributing.md) -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/crypto/package.json b/packages/crypto/package.json index 785f3f720d..953a660bfa 100644 --- a/packages/crypto/package.json +++ b/packages/crypto/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/crypto", - "version": "2.0.5", + "version": "2.0.6", "description": "Crypto primitives for libp2p", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/crypto#readme", @@ -86,7 +86,7 @@ "generate": "protons ./src/keys/keys.proto" }, "dependencies": { - "@libp2p/interface": "^0.1.3", + "@libp2p/interface": "^0.1.4", "@noble/curves": "^1.1.0", "@noble/hashes": "^1.3.1", "multiformats": "^12.0.1", diff --git a/packages/crypto/src/aes/index.ts b/packages/crypto/src/aes/index.ts index cf1dd8b875..6a453cf074 100644 --- a/packages/crypto/src/aes/index.ts +++ b/packages/crypto/src/aes/index.ts @@ -1,3 +1,44 @@ +/** + * @packageDocumentation + * + * Exposes an interface to AES encryption (formerly Rijndael), as defined in U.S. Federal Information Processing Standards Publication 197. + * + * This uses `CTR` mode. + * + * /** + * @example + * + * ```js + * import { create } from '@libp2p/crypto/aes' + * + * // Setting up Key and IV + * + * // A 16 bytes array, 128 Bits, AES-128 is chosen + * const key128 = Uint8Array.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) + * + * // A 16 bytes array, 128 Bits, + * const IV = Uint8Array.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) + * + * const decryptedMessage = 'Hello, world!' + * + * // Encrypting + * const cipher = await crypto.aes.create(key128, IV) + * const encryptedBuffer = await encrypt(Uint8Array.from(decryptedMessage)) + * console.log(encryptedBuffer) + * // prints: + * + * // Decrypting + * const decipher = await crypto.aes.create(key128, IV) + * const decryptedBuffer = await decrypt(encryptedBuffer) + * + * console.log(decryptedBuffer) + * // prints: + * + * console.log(decryptedBuffer.toString('utf-8')) + * // prints: Hello, world! + * ``` + */ + import { cipherMode } from './cipher-mode.js' import * as ciphers from './ciphers.js' @@ -6,6 +47,10 @@ export interface AESCipher { decrypt(data: Uint8Array): Promise } +/** + * @param key - The key, if length `16` then `AES 128` is used. For length `32`, `AES 256` is used + * @param iv - Must have length `16` + */ export async function create (key: Uint8Array, iv: Uint8Array): Promise { const mode = cipherMode(key) const cipher = ciphers.createCipheriv(mode, key, iv) diff --git a/packages/crypto/src/hmac/index.ts b/packages/crypto/src/hmac/index.ts index dc2ec68894..f61e3c28fc 100644 --- a/packages/crypto/src/hmac/index.ts +++ b/packages/crypto/src/hmac/index.ts @@ -1,3 +1,20 @@ +/** + * @packageDocumentation + * + * Exposes an interface to the Keyed-Hash Message Authentication Code (HMAC) as defined in U.S. Federal Information Processing Standards Publication 198. An HMAC is a cryptographic hash that uses a key to sign a message. The receiver verifies the hash by recomputing it using the same key. + * + * @example + * + * ```js + * import { create } from '@libp2p/hmac' + * + * const hash = 'SHA1' // 'SHA256' || 'SHA512' + * const hmac = await crypto.hmac.create(hash, uint8ArrayFromString('secret')) + * const sig = await hmac.digest(uint8ArrayFromString('hello world')) + * console.log(sig) + * ``` + */ + import crypto from 'crypto' import lengths from './lengths.js' diff --git a/packages/crypto/src/index.ts b/packages/crypto/src/index.ts index 9e368358eb..6396d1dbd4 100644 --- a/packages/crypto/src/index.ts +++ b/packages/crypto/src/index.ts @@ -1,3 +1,13 @@ +/** + * @packageDocumentation + * + * The `libp2p-crypto` library depends on the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) in the browser. Web Crypto is available in all modern browsers, however browsers restrict its usage to [Secure Contexts](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts). + * + * *This means you will not be able to use some `@libp2p/crypto` functions in the browser when the page is served over HTTP.* + * + * To enable the Web Crypto API and allow `@libp2p/crypto` to work fully, please serve your page over HTTPS. + */ + import * as aes from './aes/index.js' import * as hmac from './hmac/index.js' import * as keys from './keys/index.js' diff --git a/packages/crypto/src/keys/ecdh.ts b/packages/crypto/src/keys/ecdh.ts index 3e0fd30a75..992ee4777b 100644 --- a/packages/crypto/src/keys/ecdh.ts +++ b/packages/crypto/src/keys/ecdh.ts @@ -11,6 +11,11 @@ const curves = { const curveTypes = Object.keys(curves) const names = curveTypes.join(' / ') +/** + * Generates an ephemeral public key and returns a function that will compute the shared secret key. + * + * Focuses only on ECDH now, but can be made more general in the future. + */ export async function generateEphmeralKeyPair (curve: string): Promise { if (curve !== 'P-256' && curve !== 'P-384' && curve !== 'P-521') { throw new CodeError(`Unknown curve: ${curve}. Must be ${names}`, 'ERR_INVALID_CURVE') diff --git a/packages/crypto/src/keys/index.ts b/packages/crypto/src/keys/index.ts index d8192d5abb..f805d81afa 100644 --- a/packages/crypto/src/keys/index.ts +++ b/packages/crypto/src/keys/index.ts @@ -1,3 +1,15 @@ +/** + * @packageDocumentation + * + * **Supported Key Types** + * + * The {@link generateKeyPair}, {@link marshalPublicKey}, and {@link marshalPrivateKey} functions accept a string `type` argument. + * + * Currently the `'RSA'`, `'ed25519'`, and `secp256k1` types are supported, although ed25519 and secp256k1 keys support only signing and verification of messages. + * + * For encryption / decryption support, RSA keys should be used. + */ + import 'node-forge/lib/asn1.js' import 'node-forge/lib/pbe.js' import { CodeError } from '@libp2p/interface/errors' @@ -40,13 +52,21 @@ function typeToKey (type: string): typeof RSA | typeof Ed25519 | typeof Secp256k throw unsupportedKey(type) } -// Generates a keypair of the given type and bitsize +/** + * Generates a keypair of the given type and bitsize + * + * @param type + * @param bits - Minimum of 1024 + */ export async function generateKeyPair (type: KeyTypes, bits?: number): Promise { return typeToKey(type).generateKeyPair(bits ?? 2048) } -// Generates a keypair of the given type and bitsize -// seed is a 32 byte uint8array +/** + * Generates a keypair of the given type and bitsize. + * + * Seed is a 32 byte uint8array + */ export async function generateKeyPairFromSeed (type: KeyTypes, seed: Uint8Array, bits?: number): Promise { if (type.toLowerCase() !== 'ed25519') { throw new CodeError('Seed key derivation is unimplemented for RSA or secp256k1', 'ERR_UNSUPPORTED_KEY_DERIVATION_TYPE') @@ -55,8 +75,9 @@ export async function generateKeyPairFromSeed (type: KeyTypes, seed: Uint8Array, return Ed25519.generateKeyPairFromSeed(seed) } -// Converts a protobuf serialized public key into its -// representative object +/** + * Converts a protobuf serialized public key into its representative object + */ export function unmarshalPublicKey (buf: Uint8Array): PublicKey { const decoded = keysPBM.PublicKey.decode(buf) const data = decoded.Data ?? new Uint8Array() @@ -73,15 +94,18 @@ export function unmarshalPublicKey (buf: Uint8Array): PublicKey { } } -// Converts a public key object into a protobuf serialized public key +/** + * Converts a public key object into a protobuf serialized public key + */ export function marshalPublicKey (key: { bytes: Uint8Array }, type?: string): Uint8Array { type = (type ?? 'rsa').toLowerCase() typeToKey(type) // check type return key.bytes } -// Converts a protobuf serialized private key into its -// representative object +/** + * Converts a protobuf serialized private key into its representative object + */ export async function unmarshalPrivateKey (buf: Uint8Array): Promise { const decoded = keysPBM.PrivateKey.decode(buf) const data = decoded.Data ?? new Uint8Array() @@ -98,7 +122,9 @@ export async function unmarshalPrivateKey (buf: Uint8Array): Promise } } -// Converts a private key object into a protobuf serialized private key +/** + * Converts a private key object into a protobuf serialized private key + */ export function marshalPrivateKey (key: { bytes: Uint8Array }, type?: string): Uint8Array { type = (type ?? 'rsa').toLowerCase() typeToKey(type) // check type @@ -106,9 +132,9 @@ export function marshalPrivateKey (key: { bytes: Uint8Array }, type?: string): U } /** + * Converts an exported private key into its representative object. * - * @param {string} encryptedKey - * @param {string} password + * Supported formats are 'pem' (RSA only) and 'libp2p-key'. */ export async function importKey (encryptedKey: string, password: string): Promise { try { diff --git a/packages/crypto/src/random-bytes.ts b/packages/crypto/src/random-bytes.ts index a85542661c..5de614474b 100644 --- a/packages/crypto/src/random-bytes.ts +++ b/packages/crypto/src/random-bytes.ts @@ -1,6 +1,9 @@ import { CodeError } from '@libp2p/interface/errors' import { randomBytes as randB } from '@noble/hashes/utils' +/** + * Generates a Uint8Array with length `number` populated by random bytes + */ export default function randomBytes (length: number): Uint8Array { if (isNaN(length) || length <= 0) { throw new CodeError('random bytes length must be a Number bigger than 0', 'ERR_INVALID_LENGTH') diff --git a/packages/interface-compliance-tests/CHANGELOG.md b/packages/interface-compliance-tests/CHANGELOG.md index a9ef37cb25..f5e6c0fc60 100644 --- a/packages/interface-compliance-tests/CHANGELOG.md +++ b/packages/interface-compliance-tests/CHANGELOG.md @@ -5,6 +5,27 @@ * bump aegir from 38.1.8 to 39.0.5 ([#393](https://github.com/libp2p/js-libp2p-interfaces/issues/393)) ([31f3797](https://github.com/libp2p/js-libp2p-interfaces/commit/31f3797b24f7c23f3f16e9db3a230bd5f7cd5175)) +### [4.1.2](https://www.github.com/libp2p/js-libp2p/compare/interface-compliance-tests-v4.1.1...interface-compliance-tests-v4.1.2) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/interface-internal bumped from ^0.1.6 to ^0.1.7 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/multistream-select bumped from ^4.0.3 to ^4.0.4 + * @libp2p/peer-collections bumped from ^4.0.5 to ^4.0.6 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + ### [4.1.1](https://www.github.com/libp2p/js-libp2p/compare/interface-compliance-tests-v4.1.0...interface-compliance-tests-v4.1.1) (2023-10-06) @@ -656,4 +677,4 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline ### BREAKING CHANGES -* the tests now live in the libp2p-interfaces-compliance-tests module +* the tests now live in the libp2p-interfaces-compliance-tests module \ No newline at end of file diff --git a/packages/interface-compliance-tests/README.md b/packages/interface-compliance-tests/README.md index 906d059731..04270ac05e 100644 --- a/packages/interface-compliance-tests/README.md +++ b/packages/interface-compliance-tests/README.md @@ -1,5 +1,3 @@ -# @libp2p/interface-compliance-tests - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,22 +5,13 @@ > Compliance tests for JS libp2p interfaces -## Table of contents - -- [Install](#install) - - [Browser ` ``` -## Usage +# Usage Each [interface](https://npmjs.org/packages/@libp2p/interfaces) has its documentation on how to use the compliance tests and should be used as the source of truth. -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-compliance-tests/package.json b/packages/interface-compliance-tests/package.json index f467311297..2080d453c8 100644 --- a/packages/interface-compliance-tests/package.json +++ b/packages/interface-compliance-tests/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/interface-compliance-tests", - "version": "4.1.1", + "version": "4.1.2", "description": "Compliance tests for JS libp2p interfaces", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/interface-compliance-tests#readme", @@ -103,13 +103,13 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/interface-internal": "^0.1.6", - "@libp2p/logger": "^3.0.3", - "@libp2p/multistream-select": "^4.0.3", - "@libp2p/peer-collections": "^4.0.5", - "@libp2p/peer-id": "^3.0.3", - "@libp2p/peer-id-factory": "^3.0.5", + "@libp2p/interface": "^0.1.4", + "@libp2p/interface-internal": "^0.1.7", + "@libp2p/logger": "^3.0.4", + "@libp2p/multistream-select": "^4.0.4", + "@libp2p/peer-collections": "^4.0.6", + "@libp2p/peer-id": "^3.0.4", + "@libp2p/peer-id-factory": "^3.0.6", "@multiformats/multiaddr": "^12.1.5", "abortable-iterator": "^5.0.1", "aegir": "^41.0.2", @@ -131,7 +131,7 @@ "p-limit": "^4.0.0", "p-wait-for": "^5.0.2", "protons-runtime": "^5.0.0", - "sinon": "^16.0.0", + "sinon": "^17.0.0", "uint8arraylist": "^2.4.3", "uint8arrays": "^4.0.6" }, diff --git a/packages/interface-compliance-tests/src/mocks/connection-manager.ts b/packages/interface-compliance-tests/src/mocks/connection-manager.ts index 4f5cecbac0..81904d407f 100644 --- a/packages/interface-compliance-tests/src/mocks/connection-manager.ts +++ b/packages/interface-compliance-tests/src/mocks/connection-manager.ts @@ -6,7 +6,7 @@ import { isMultiaddr, type Multiaddr } from '@multiformats/multiaddr' import { connectionPair } from './connection.js' import type { Libp2pEvents, PendingDial } from '@libp2p/interface' import type { Connection } from '@libp2p/interface/connection' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PubSub } from '@libp2p/interface/pubsub' import type { Startable } from '@libp2p/interface/startable' import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager' @@ -16,7 +16,7 @@ export interface MockNetworkComponents { peerId: PeerId registrar: Registrar connectionManager: ConnectionManager - events: EventEmitter + events: TypedEventTarget pubsub?: PubSub } @@ -51,7 +51,7 @@ export const mockNetwork = new MockNetwork() export interface MockConnectionManagerComponents { peerId: PeerId registrar: Registrar - events: EventEmitter + events: TypedEventTarget } class MockConnectionManager implements ConnectionManager, Startable { diff --git a/packages/interface-compliance-tests/src/mocks/peer-discovery.ts b/packages/interface-compliance-tests/src/mocks/peer-discovery.ts index eab17bea6d..69bd2afc29 100644 --- a/packages/interface-compliance-tests/src/mocks/peer-discovery.ts +++ b/packages/interface-compliance-tests/src/mocks/peer-discovery.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import * as PeerIdFactory from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' @@ -12,7 +12,7 @@ interface MockDiscoveryInit { /** * Emits 'peer' events on discovery. */ -export class MockDiscovery extends EventEmitter implements PeerDiscovery { +export class MockDiscovery extends TypedEventEmitter implements PeerDiscovery { public readonly options: MockDiscoveryInit private _isRunning: boolean private _timer: any diff --git a/packages/interface-compliance-tests/src/mocks/upgrader.ts b/packages/interface-compliance-tests/src/mocks/upgrader.ts index b4ef88002d..4f69268071 100644 --- a/packages/interface-compliance-tests/src/mocks/upgrader.ts +++ b/packages/interface-compliance-tests/src/mocks/upgrader.ts @@ -1,18 +1,18 @@ import { mockConnection } from './connection.js' import type { Libp2pEvents } from '@libp2p/interface' import type { Connection, MultiaddrConnection } from '@libp2p/interface/connection' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { Upgrader, UpgraderOptions } from '@libp2p/interface/transport' import type { Registrar } from '@libp2p/interface-internal/registrar' export interface MockUpgraderInit { registrar?: Registrar - events?: EventEmitter + events?: TypedEventTarget } class MockUpgrader implements Upgrader { private readonly registrar?: Registrar - private readonly events?: EventEmitter + private readonly events?: TypedEventTarget constructor (init: MockUpgraderInit) { this.registrar = init.registrar diff --git a/packages/interface-compliance-tests/src/pubsub/utils.ts b/packages/interface-compliance-tests/src/pubsub/utils.ts index 79bf894479..fdd7c2552c 100644 --- a/packages/interface-compliance-tests/src/pubsub/utils.ts +++ b/packages/interface-compliance-tests/src/pubsub/utils.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { pEvent } from 'p-event' import pWaitFor from 'p-wait-for' @@ -19,7 +19,7 @@ export async function createComponents (): Promise { const components: any = { peerId: await createEd25519PeerId(), registrar: mockRegistrar(), - events: new EventEmitter() + events: new TypedEventEmitter() } components.connectionManager = mockConnectionManager(components) diff --git a/packages/interface-compliance-tests/src/transport/dial-test.ts b/packages/interface-compliance-tests/src/transport/dial-test.ts index 2139a755d0..98035d9aa5 100644 --- a/packages/interface-compliance-tests/src/transport/dial-test.ts +++ b/packages/interface-compliance-tests/src/transport/dial-test.ts @@ -1,5 +1,5 @@ import { AbortError } from '@libp2p/interface/errors' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { expect } from 'aegir/chai' import all from 'it-all' import drain from 'it-drain' @@ -27,7 +27,7 @@ export default (common: TestSetup): void => { registrar = mockRegistrar() upgrader = mockUpgrader({ registrar, - events: new EventEmitter() + events: new TypedEventEmitter() }); ({ addrs, transport, connector } = await common.setup()) diff --git a/packages/interface-compliance-tests/src/transport/listen-test.ts b/packages/interface-compliance-tests/src/transport/listen-test.ts index d518511dc7..d9f3a17c22 100644 --- a/packages/interface-compliance-tests/src/transport/listen-test.ts +++ b/packages/interface-compliance-tests/src/transport/listen-test.ts @@ -1,5 +1,5 @@ /* eslint max-nested-callbacks: ["error", 8] */ -import { CustomEvent, EventEmitter } from '@libp2p/interface/events' +import { CustomEvent, TypedEventEmitter } from '@libp2p/interface/events' import { expect } from 'aegir/chai' import drain from 'it-drain' import { pipe } from 'it-pipe' @@ -27,7 +27,7 @@ export default (common: TestSetup): void => { registrar = mockRegistrar() upgrader = mockUpgrader({ registrar, - events: new EventEmitter() + events: new TypedEventEmitter() }); ({ transport, addrs } = await common.setup()) diff --git a/packages/interface-internal/CHANGELOG.md b/packages/interface-internal/CHANGELOG.md index 4d159c1220..d8331595b2 100644 --- a/packages/interface-internal/CHANGELOG.md +++ b/packages/interface-internal/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +### [0.1.7](https://www.github.com/libp2p/js-libp2p/compare/interface-internal-v0.1.6...interface-internal-v0.1.7) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/peer-collections bumped from ^4.0.5 to ^4.0.6 + ### [0.1.6](https://www.github.com/libp2p/js-libp2p/compare/interface-internal-v0.1.5...interface-internal-v0.1.6) (2023-10-06) diff --git a/packages/interface-internal/README.md b/packages/interface-internal/README.md index 4d6b738f26..dafd72596c 100644 --- a/packages/interface-internal/README.md +++ b/packages/interface-internal/README.md @@ -1,5 +1,3 @@ -# @libp2p/interface-internal - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,30 +5,23 @@ > Interfaces implemented by internal libp2p components -## Table of contents - -- [Install](#install) -- [API Docs](#api-docs) -- [License](#license) -- [Contribution](#contribution) - -## Install +# Install ```console $ npm i @libp2p/interface-internal ``` -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-internal/package.json b/packages/interface-internal/package.json index f8ea476d52..8903560eae 100644 --- a/packages/interface-internal/package.json +++ b/packages/interface-internal/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/interface-internal", - "version": "0.1.6", + "version": "0.1.7", "description": "Interfaces implemented by internal libp2p components", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/interface-internal#readme", @@ -79,8 +79,8 @@ "build": "aegir build" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/peer-collections": "^4.0.5", + "@libp2p/interface": "^0.1.4", + "@libp2p/peer-collections": "^4.0.6", "@multiformats/multiaddr": "^12.1.5", "uint8arraylist": "^2.4.3" }, diff --git a/packages/interface/CHANGELOG.md b/packages/interface/CHANGELOG.md index 145ba5c8bc..a37155f64b 100644 --- a/packages/interface/CHANGELOG.md +++ b/packages/interface/CHANGELOG.md @@ -5,6 +5,14 @@ * add start/stop events to libp2p interface ([#407](https://github.com/libp2p/js-libp2p-interfaces/issues/407)) ([016c1e8](https://github.com/libp2p/js-libp2p-interfaces/commit/016c1e82b060c93c80546cd8c493ec6e6c97cbec)) +### [0.1.4](https://www.github.com/libp2p/js-libp2p/compare/interface-v0.1.3...interface-v0.1.4) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + ### [0.1.3](https://www.github.com/libp2p/js-libp2p/compare/interface-v0.1.2...interface-v0.1.3) (2023-10-06) diff --git a/packages/interface/README.md b/packages/interface/README.md index 384bcb1b91..2ed3298f4a 100644 --- a/packages/interface/README.md +++ b/packages/interface/README.md @@ -1,5 +1,3 @@ -# @libp2p/interface - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,21 +5,13 @@ > The interface implemented by a libp2p node -## Table of contents - -- [Install](#install) - - [Browser ` ``` -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface/package.json b/packages/interface/package.json index 25e4b96c14..5c57784506 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/interface", - "version": "0.1.3", + "version": "0.1.4", "description": "The interface implemented by a libp2p node", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/interface#readme", @@ -39,6 +39,9 @@ "!dist/test", "!**/*.tsbuildinfo" ], + "browser": { + "events": "./dist/src/events.browser.js" + }, "exports": { ".": { "types": "./dist/src/index.d.ts", @@ -173,7 +176,7 @@ "delay": "^6.0.0", "it-all": "^3.0.3", "it-drain": "^3.0.3", - "sinon": "^16.0.0", - "sinon-ts": "^1.0.0" + "sinon": "^17.0.0", + "sinon-ts": "^2.0.0" } } diff --git a/packages/interface/src/events.browser.ts b/packages/interface/src/events.browser.ts new file mode 100644 index 0000000000..7c1fabd36c --- /dev/null +++ b/packages/interface/src/events.browser.ts @@ -0,0 +1,2 @@ +/** Noop for browser compatibility */ +export function setMaxListeners (): void {} diff --git a/packages/interface/src/events.ts b/packages/interface/src/events.ts index 4fff7e8f91..4c4a498fc3 100644 --- a/packages/interface/src/events.ts +++ b/packages/interface/src/events.ts @@ -1,3 +1,5 @@ +import { setMaxListeners as nodeSetMaxListeners } from 'events' + export interface EventCallback { (evt: EventType): void } export interface EventObject { handleEvent: EventCallback } export type EventHandler = EventCallback | EventObject @@ -15,7 +17,23 @@ interface Listener { * https://github.com/microsoft/TypeScript/issues/299 * etc */ -export class EventEmitter> extends EventTarget { +export interface TypedEventTarget > extends EventTarget { + addEventListener(type: K, listener: EventHandler | null, options?: boolean | AddEventListenerOptions): void + + listenerCount (type: string): number + + removeEventListener(type: K, listener?: EventHandler | null, options?: boolean | EventListenerOptions): void + + removeEventListener (type: string, listener?: EventHandler, options?: boolean | EventListenerOptions): void + + safeDispatchEvent(type: keyof EventMap, detail: CustomEventInit): boolean +} + +/** + * An implementation of a typed event target + * etc + */ +export class TypedEventEmitter> extends EventTarget implements TypedEventTarget { #listeners = new Map() listenerCount (type: string): number { @@ -98,3 +116,15 @@ class CustomEventPolyfill extends Event { } export const CustomEvent = globalThis.CustomEvent ?? CustomEventPolyfill + +// TODO: remove this in v1 +export { TypedEventEmitter as EventEmitter } + +// create a setMaxListeners that doesn't break browser usage +export const setMaxListeners: typeof nodeSetMaxListeners = (n, ...eventTargets) => { + try { + nodeSetMaxListeners(n, ...eventTargets) + } catch { + // swallow error, gulp + } +} diff --git a/packages/interface/src/index.ts b/packages/interface/src/index.ts index 0dd02078f8..5b1463e4c2 100644 --- a/packages/interface/src/index.ts +++ b/packages/interface/src/index.ts @@ -16,7 +16,7 @@ import type { Connection, NewStreamOptions, Stream } from './connection/index.js' import type { ContentRouting } from './content-routing/index.js' -import type { EventEmitter } from './events.js' +import type { TypedEventTarget } from './events.js' import type { KeyChain } from './keychain/index.js' import type { Metrics } from './metrics/index.js' import type { PeerId } from './peer-id/index.js' @@ -99,6 +99,11 @@ export interface IdentifyResult { * If sent by the remote peer this is the deserialized signed peer record */ signedPeerRecord?: SignedPeerRecord + + /** + * The connection that the identify protocol ran over + */ + connection: Connection } /** @@ -303,7 +308,7 @@ export interface PendingDial { /** * Libp2p nodes implement this interface. */ -export interface Libp2p extends Startable, EventEmitter> { +export interface Libp2p extends Startable, TypedEventTarget> { /** * The PeerId is a unique identifier for a node on the network. * diff --git a/packages/interface/src/peer-discovery/index.ts b/packages/interface/src/peer-discovery/index.ts index 4b8aa9c258..55b1227eb1 100644 --- a/packages/interface/src/peer-discovery/index.ts +++ b/packages/interface/src/peer-discovery/index.ts @@ -1,4 +1,4 @@ -import type { EventEmitter } from '../events.js' +import type { TypedEventTarget } from '../events.js' import type { PeerInfo } from '../peer-info/index.js' /** @@ -26,4 +26,4 @@ export interface PeerDiscoveryEvents { 'peer': CustomEvent } -export interface PeerDiscovery extends EventEmitter {} +export interface PeerDiscovery extends TypedEventTarget {} diff --git a/packages/interface/src/pubsub/index.ts b/packages/interface/src/pubsub/index.ts index 6fd94382a1..1ce9464b6b 100644 --- a/packages/interface/src/pubsub/index.ts +++ b/packages/interface/src/pubsub/index.ts @@ -1,5 +1,5 @@ import type { Stream } from '../connection/index.js' -import type { EventEmitter } from '../events.js' +import type { TypedEventTarget } from '../events.js' import type { PeerId } from '../peer-id/index.js' import type { Pushable } from 'it-pushable' import type { Uint8ArrayList } from 'uint8arraylist' @@ -65,7 +65,7 @@ export interface PubSubRPC { messages: PubSubRPCMessage[] } -export interface PeerStreams extends EventEmitter { +export interface PeerStreams extends TypedEventTarget { id: PeerId protocol: string outboundStream?: Pushable @@ -152,7 +152,7 @@ export interface TopicValidatorFn { (peer: PeerId, message: Message): TopicValidatorResult | Promise } -export interface PubSub = PubSubEvents> extends EventEmitter { +export interface PubSub = PubSubEvents> extends TypedEventTarget { /** * The global signature policy controls whether or not we sill send and receive * signed or unsigned messages. diff --git a/packages/interface/src/topology/index.ts b/packages/interface/src/topology/index.ts index 0772df3b38..25c321201b 100644 --- a/packages/interface/src/topology/index.ts +++ b/packages/interface/src/topology/index.ts @@ -5,6 +5,21 @@ export interface Topology { min?: number max?: number + /** + * If true, invoke `onConnect` for this topology on transient (e.g. short-lived + * and/or data-limited) connections. (default: false) + */ + notifyOnTransient?: boolean + + /** + * Invoked when a new connection is opened to a peer that supports the + * registered protocol + */ onConnect?(peerId: PeerId, conn: Connection): void + + /** + * Invoked when the last connection to a peer that supports the registered + * protocol closes + */ onDisconnect?(peerId: PeerId): void } diff --git a/packages/interface/src/transport/index.ts b/packages/interface/src/transport/index.ts index 5acbfcc50e..22ab1a803b 100644 --- a/packages/interface/src/transport/index.ts +++ b/packages/interface/src/transport/index.ts @@ -1,5 +1,5 @@ import type { Connection, MultiaddrConnection } from '../connection/index.js' -import type { EventEmitter } from '../events.js' +import type { TypedEventTarget } from '../events.js' import type { AbortOptions } from '../index.js' import type { StreamMuxerFactory } from '../stream-muxer/index.js' import type { Multiaddr } from '@multiformats/multiaddr' @@ -11,7 +11,7 @@ export interface ListenerEvents { 'close': CustomEvent } -export interface Listener extends EventEmitter { +export interface Listener extends TypedEventTarget { /** * Start a listener */ diff --git a/packages/kad-dht/CHANGELOG.md b/packages/kad-dht/CHANGELOG.md index 9cbeb5a94c..d19f8dd633 100644 --- a/packages/kad-dht/CHANGELOG.md +++ b/packages/kad-dht/CHANGELOG.md @@ -5,6 +5,38 @@ * skip self-query if not running ([#479](https://github.com/libp2p/js-libp2p-kad-dht/issues/479)) ([7095290](https://github.com/libp2p/js-libp2p-kad-dht/commit/70952907a27fd8778773172059879656b4f08855)) +### [10.0.11](https://www.github.com/libp2p/js-libp2p/compare/kad-dht-v10.0.10...kad-dht-v10.0.11) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^2.0.5 to ^2.0.6 + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/interface-internal bumped from ^0.1.6 to ^0.1.7 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-collections bumped from ^4.0.5 to ^4.0.6 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + * @libp2p/peer-store bumped from ^9.0.6 to ^9.0.7 + +### [10.0.10](https://www.github.com/libp2p/js-libp2p/compare/kad-dht-v10.0.9...kad-dht-v10.0.10) (2023-10-25) + + +### Bug Fixes + +* allow DHT self-query to time out ([#2169](https://www.github.com/libp2p/js-libp2p/issues/2169)) ([ce0e38d](https://www.github.com/libp2p/js-libp2p/commit/ce0e38d28240303f7afc7f37de441b067e3e855e)) +* export DHT record class ([#2168](https://www.github.com/libp2p/js-libp2p/issues/2168)) ([2f6a239](https://www.github.com/libp2p/js-libp2p/commit/2f6a2397f7e8ec7cf2edda7c9996be263a423661)) + ### [10.0.9](https://www.github.com/libp2p/js-libp2p/compare/kad-dht-v10.0.8...kad-dht-v10.0.9) (2023-10-06) @@ -1814,4 +1846,4 @@ Co-Authored-By: vasco-santos ### Features -* v0.1.0 ([4bd1fbc](https://github.com/libp2p/js-libp2p-kad-dht/commit/4bd1fbc)) +* v0.1.0 ([4bd1fbc](https://github.com/libp2p/js-libp2p-kad-dht/commit/4bd1fbc)) \ No newline at end of file diff --git a/packages/kad-dht/README.md b/packages/kad-dht/README.md index bd231f8c1d..e9fd6de682 100644 --- a/packages/kad-dht/README.md +++ b/packages/kad-dht/README.md @@ -1,5 +1,3 @@ -# @libp2p/kad-dht - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,28 +5,13 @@ > JavaScript implementation of the Kad-DHT for libp2p -## Table of contents - -- [Install](#install) - - [Browser ` -``` - -## Features +# About - Manages the lifecycle of a key - Keys are encrypted at rest @@ -43,7 +15,7 @@ Loading this module through a script tag will make it's exports available as `Li - Enforces NIST SP 800-131A and NIST SP 800-132 - Delays reporting errors to slow down brute force attacks -### KeyInfo +## KeyInfo The key management and naming service API all return a `KeyInfo` object. The `id` is a universally unique identifier for the key. The `name` is local to the key chain. @@ -54,9 +26,11 @@ The key management and naming service API all return a `KeyInfo` object. The `i } ``` -The **key id** is the SHA-256 [multihash](https://github.com/multiformats/multihash) of its public key. The *public key* is a [protobuf encoding](https://github.com/libp2p/js-libp2p-crypto/blob/master/src/keys/keys.proto.js) containing a type and the [DER encoding](https://en.wikipedia.org/wiki/X.690) of the PKCS [SubjectPublicKeyInfo](https://www.ietf.org/rfc/rfc3279.txt). +The **key id** is the SHA-256 [multihash](https://github.com/multiformats/multihash) of its public key. -### Private key storage +The *public key* is a [protobuf encoding](https://github.com/libp2p/js-libp2p-crypto/blob/master/src/keys/keys.proto.js) containing a type and the [DER encoding](https://en.wikipedia.org/wiki/X.690) of the PKCS [SubjectPublicKeyInfo](https://www.ietf.org/rfc/rfc3279.txt). + +## Private key storage A private key is stored as an encrypted PKCS 8 structure in the PEM format. It is protected by a key generated from the key chain's *passPhrase* using **PBKDF2**. @@ -64,7 +38,7 @@ The default options for generating the derived encryption key are in the `dek` o ```js const defaultOptions = { - //See https://cryptosense.com/parameter-choice-for-pbkdf2/ +// See https://cryptosense.com/parameter-choice-for-pbkdf2/ dek: { keyLength: 512 / 8, iterationCount: 1000, @@ -76,9 +50,25 @@ const defaultOptions = { ![key storage](./doc/private-key.png?raw=true) -### Physical storage +## Physical storage + +The actual physical storage of an encrypted key is left to implementations of [interface-datastore](https://github.com/ipfs/interface-datastore/). + +A key benefit is that now the key chain can be used in browser with the [js-datastore-level](https://github.com/ipfs/js-datastore-level) implementation. + +# Install + +```console +$ npm i @libp2p/keychain +``` + +## Browser ` +``` ## API Docs diff --git a/packages/keychain/package.json b/packages/keychain/package.json index 0ac5a359f4..acb2dcbb73 100644 --- a/packages/keychain/package.json +++ b/packages/keychain/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/keychain", - "version": "3.0.5", + "version": "3.0.6", "description": "Key management and cryptographically protected messages", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/keychain#readme", @@ -54,17 +54,17 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/crypto": "^2.0.5", - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", - "@libp2p/peer-id": "^3.0.3", + "@libp2p/crypto": "^2.0.6", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", + "@libp2p/peer-id": "^3.0.4", "interface-datastore": "^8.2.0", "merge-options": "^3.0.4", "sanitize-filename": "^1.6.3", "uint8arrays": "^4.0.6" }, "devDependencies": { - "@libp2p/peer-id-factory": "^3.0.5", + "@libp2p/peer-id-factory": "^3.0.6", "aegir": "^41.0.2", "datastore-core": "^9.1.1", "multiformats": "^12.0.1" diff --git a/packages/keychain/src/index.ts b/packages/keychain/src/index.ts index f13cc0367f..8507c4c7bf 100644 --- a/packages/keychain/src/index.ts +++ b/packages/keychain/src/index.ts @@ -1,3 +1,55 @@ +/** + * @packageDocumentation + * + * - Manages the lifecycle of a key + * - Keys are encrypted at rest + * - Enforces the use of safe key names + * - Uses encrypted PKCS 8 for key storage + * - Uses PBKDF2 for a "stetched" key encryption key + * - Enforces NIST SP 800-131A and NIST SP 800-132 + * - Delays reporting errors to slow down brute force attacks + * + * ## KeyInfo + * + * The key management and naming service API all return a `KeyInfo` object. The `id` is a universally unique identifier for the key. The `name` is local to the key chain. + * + * ```js + * { + * name: 'rsa-key', + * id: 'QmYWYSUZ4PV6MRFYpdtEDJBiGs4UrmE6g8wmAWSePekXVW' + * } + * ``` + * + * The **key id** is the SHA-256 [multihash](https://github.com/multiformats/multihash) of its public key. + * + * The *public key* is a [protobuf encoding](https://github.com/libp2p/js-libp2p-crypto/blob/master/src/keys/keys.proto.js) containing a type and the [DER encoding](https://en.wikipedia.org/wiki/X.690) of the PKCS [SubjectPublicKeyInfo](https://www.ietf.org/rfc/rfc3279.txt). + * + * ## Private key storage + * + * A private key is stored as an encrypted PKCS 8 structure in the PEM format. It is protected by a key generated from the key chain's *passPhrase* using **PBKDF2**. + * + * The default options for generating the derived encryption key are in the `dek` object. This, along with the passPhrase, is the input to a `PBKDF2` function. + * + * ```js + * const defaultOptions = { + * // See https://cryptosense.com/parameter-choice-for-pbkdf2/ + * dek: { + * keyLength: 512 / 8, + * iterationCount: 1000, + * salt: 'at least 16 characters long', + * hash: 'sha2-512' + * } + * } + * ``` + * ![key storage](./doc/private-key.png?raw=true) + * + * ## Physical storage + * + * The actual physical storage of an encrypted key is left to implementations of [interface-datastore](https://github.com/ipfs/interface-datastore/). + * + * A key benefit is that now the key chain can be used in browser with the [js-datastore-level](https://github.com/ipfs/js-datastore-level) implementation. + */ + /* eslint max-nested-callbacks: ["error", 5] */ import { pbkdf2, randomBytes } from '@libp2p/crypto' diff --git a/packages/libp2p/CHANGELOG.md b/packages/libp2p/CHANGELOG.md index 36d4003014..44ec7ce1a6 100644 --- a/packages/libp2p/CHANGELOG.md +++ b/packages/libp2p/CHANGELOG.md @@ -20,6 +20,55 @@ * @libp2p/tcp bumped from ^8.0.5 to ^8.0.6 * @libp2p/websockets bumped from ^7.0.5 to ^7.0.6 +### [0.46.16](https://www.github.com/libp2p/js-libp2p/compare/libp2p-v0.46.15...libp2p-v0.46.16) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^2.0.5 to ^2.0.6 + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/interface-internal bumped from ^0.1.6 to ^0.1.7 + * @libp2p/keychain bumped from ^3.0.5 to ^3.0.6 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/multistream-select bumped from ^4.0.3 to ^4.0.4 + * @libp2p/peer-collections bumped from ^4.0.5 to ^4.0.6 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + * @libp2p/peer-record bumped from ^6.0.6 to ^6.0.7 + * @libp2p/peer-store bumped from ^9.0.6 to ^9.0.7 + * @libp2p/utils bumped from ^4.0.4 to ^4.0.5 + * devDependencies + * @libp2p/bootstrap bumped from ^9.0.8 to ^9.0.9 + * @libp2p/floodsub bumped from ^8.0.9 to ^8.0.10 + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + * @libp2p/kad-dht bumped from ^10.0.10 to ^10.0.11 + * @libp2p/mdns bumped from ^9.0.10 to ^9.0.11 + * @libp2p/mplex bumped from ^9.0.8 to ^9.0.9 + * @libp2p/tcp bumped from ^8.0.9 to ^8.0.10 + * @libp2p/websockets bumped from ^7.0.9 to ^7.0.10 + +### [0.46.15](https://www.github.com/libp2p/js-libp2p/compare/libp2p-v0.46.14...libp2p-v0.46.15) (2023-10-25) + + +### Bug Fixes + +* remove relay:removed event listener after relay is removed ([#1998](https://www.github.com/libp2p/js-libp2p/issues/1998)) ([ab2c1f6](https://www.github.com/libp2p/js-libp2p/commit/ab2c1f6731ccfe21a39482bdab217a8abd3f027b)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @libp2p/kad-dht bumped from ^10.0.9 to ^10.0.10 + ### [0.46.14](https://www.github.com/libp2p/js-libp2p/compare/libp2p-v0.46.13...libp2p-v0.46.14) (2023-10-10) @@ -2546,4 +2595,4 @@ for subscribe to see how it should be used. -## [0.5.5](https://github.com/libp2p/js-libp2p/compare/v0.5.4...v0.5.5) (2017-03-21) +## [0.5.5](https://github.com/libp2p/js-libp2p/compare/v0.5.4...v0.5.5) (2017-03-21) \ No newline at end of file diff --git a/packages/libp2p/README.md b/packages/libp2p/README.md index 4e5f48828a..8e2c9bb35d 100644 --- a/packages/libp2p/README.md +++ b/packages/libp2p/README.md @@ -1,48 +1,3 @@ -# libp2p - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> JavaScript implementation of libp2p, a modular peer to peer network stack - -## Table of contents - -- [Install](#install) - - [Browser ` -``` -

      libp2p hex logo

      @@ -71,18 +26,20 @@ Loading this module through a script tag will make it's exports available as `Li

      -### Project status +> JavaScript implementation of libp2p, a modular peer to peer network stack + +# Project status We've come a long way, but this project is still in Alpha, lots of development is happening, API might change, beware of the Dragons 🐉.. The documentation in the master branch may contain changes from a pre-release. If you are looking for the documentation of the latest release, you can view the latest release on [**npm**](https://www.npmjs.com/package/libp2p), or select the tag in github that matches the version you are looking for. -**Want to get started?** Check our [GETTING\_STARTED.md](./doc/GETTING_STARTED.md) guide and [examples folder](/examples). +**Want to get started?** Check our [GETTING\_STARTED.md](./doc/GETTING_STARTED.md) guide and [examples repo](https://github.com/libp2p/js-libp2p-examples). **Want to update libp2p in your project?** Check our [migrations folder](./doc/migrations). -## Background +# Background libp2p is the product of a long and arduous quest to understand the evolution of the Internet networking stack. In order to build P2P applications, devs have long had to make custom ad-hoc solutions to fit their needs, sometimes making some hard assumptions about their runtimes and the state of the network at the time of their development. Today, looking back more than 20 years, we see a clear pattern in the types of mechanisms built around the Internet Protocol, IP, which can be found throughout many layers of the OSI layer system, libp2p distils these mechanisms into flat categories and defines clear interfaces that once exposed, enable other protocols and applications to use and swap them, enabling upgradability and adaptability for the runtime, without breaking the API. @@ -99,7 +56,7 @@ We are in the process of writing better documentation, blog posts, tutorials and To sum up, libp2p is a "network stack" -- a protocol suite -- that cleanly separates concerns, and enables sophisticated applications to only use the protocols they absolutely need, without giving up interoperability and upgradeability. libp2p grew out of IPFS, but it is built so that lots of people can use it, for lots of different projects. -## Roadmap +# Roadmap The js-libp2p roadmap can be found here: @@ -107,25 +64,25 @@ It represents current projects the js-libp2p maintainers are focused on and prov It is complementary to the overarching libp2p project roadmap: -## Usage +# Usage ### Configuration For all the information on how you can configure libp2p see [CONFIGURATION.md](./doc/CONFIGURATION.md). -### Limits +## Limits For help configuring your node to resist malicious network peers, see [LIMITS.md](./doc/LIMITS.md) -### Getting started +## Getting started If you are starting your journey with `js-libp2p`, read the [GETTING\_STARTED.md](./doc/GETTING_STARTED.md) guide. -### Tutorials and Examples +## Tutorials and Examples -You can find multiple examples on the [examples folder](./examples) that will guide you through using libp2p for several scenarios. +You can find multiple examples on the [examples repo](https://github.com/libp2p/js-libp2p-examples) that will guide you through using libp2p for several scenarios. -## Development +# Development **Clone and install dependencies:** @@ -136,9 +93,9 @@ You can find multiple examples on the [examples folder](./examples) that will gu > npm run build ``` -### Tests +# Tests -#### Run unit tests +## Run unit tests ```sh # run all the unit tsts @@ -151,7 +108,7 @@ You can find multiple examples on the [examples folder](./examples) that will gu > npm run test:chrome ``` -### Packages +# Packages List of packages currently in existence for libp2p @@ -195,7 +152,7 @@ List of packages currently in existence for libp2p | [`@ChainSafe/libp2p-gossipsub`](//github.com/ChainSafe/js-libp2p-gossipsub) | [![npm](https://img.shields.io/npm/v/%40ChainSafe%2Flibp2p-gossipsub.svg?maxAge=86400\&style=flat-square)](//github.com/ChainSafe/js-libp2p-gossipsub/releases) | [![Deps](https://img.shields.io/librariesio/release/npm/%40ChainSafe%2Flibp2p-gossipsub?logo=Libraries.io\&logoColor=white\&style=flat-square)](//libraries.io/npm/%40ChainSafe%2Flibp2p-gossipsub) | [![GitHub CI](https://img.shields.io/github/actions/workflow/status/ChainSafe/js-libp2p-gossipsub/main.yml?branch=master\&label=ci\&style=flat-square)](//github.com/ChainSafe/js-libp2p-gossipsub/actions?query=branch%3Amaster+workflow%3Aci+) | [![codecov](https://codecov.io/gh/ChainSafe/js-libp2p-gossipsub/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/ChainSafe/js-libp2p-gossipsub) | | [`@libp2p/floodsub`](//github.com/libp2p/js-libp2p-floodsub) | [![npm](https://img.shields.io/npm/v/%40libp2p%2Ffloodsub.svg?maxAge=86400\&style=flat-square)](//github.com/libp2p/js-libp2p-floodsub/releases) | [![Deps](https://img.shields.io/librariesio/release/npm/%40libp2p%2Ffloodsub?logo=Libraries.io\&logoColor=white\&style=flat-square)](//libraries.io/npm/%40libp2p%2Ffloodsub) | [![GitHub CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-floodsub/js-test-and-release.yml?branch=master\&label=ci\&style=flat-square)](//github.com/libp2p/js-libp2p-floodsub/actions?query=branch%3Amaster+workflow%3Aci+) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-floodsub/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-floodsub) | -## Used by +# Used by

      @@ -207,7 +164,7 @@ List of packages currently in existence for libp2p And [many others...](https://github.com/libp2p/js-libp2p/network/dependents) -## Contribute +# Contribute The libp2p implementation in JavaScript is a work in progress. As such, there are a few things you can do right now to help out: @@ -215,17 +172,17 @@ The libp2p implementation in JavaScript is a work in progress. As such, there ar - **Perform code reviews**. Most of this has been developed by @diasdavid, which means that more eyes will help a) speed the project along b) ensure quality and c) reduce possible future bugs. - **Add tests**. There can never be enough tests. -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/libp2p/package.json b/packages/libp2p/package.json index 14ec1b4da7..3a574256ae 100644 --- a/packages/libp2p/package.json +++ b/packages/libp2p/package.json @@ -1,6 +1,6 @@ { "name": "libp2p", - "version": "0.46.14", + "version": "0.46.16", "description": "JavaScript implementation of libp2p, a modular peer to peer network stack", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/libp2p#readme", @@ -100,7 +100,7 @@ "scripts": { "clean": "aegir clean", "lint": "aegir lint", - "dep-check": "aegir dep-check -i events", + "dep-check": "aegir dep-check", "prepublishOnly": "node scripts/update-version.js && npm run build", "build": "aegir build", "generate": "run-s generate:proto:*", @@ -121,25 +121,24 @@ }, "dependencies": { "@achingbrain/nat-port-mapper": "^1.0.9", - "@libp2p/crypto": "^2.0.5", - "@libp2p/interface": "^0.1.3", - "@libp2p/interface-internal": "^0.1.6", - "@libp2p/keychain": "^3.0.5", - "@libp2p/logger": "^3.0.3", - "@libp2p/multistream-select": "^4.0.3", - "@libp2p/peer-collections": "^4.0.5", - "@libp2p/peer-id": "^3.0.3", - "@libp2p/peer-id-factory": "^3.0.5", - "@libp2p/peer-record": "^6.0.6", - "@libp2p/peer-store": "^9.0.6", - "@libp2p/utils": "^4.0.4", + "@libp2p/crypto": "^2.0.6", + "@libp2p/interface": "^0.1.4", + "@libp2p/interface-internal": "^0.1.7", + "@libp2p/keychain": "^3.0.6", + "@libp2p/logger": "^3.0.4", + "@libp2p/multistream-select": "^4.0.4", + "@libp2p/peer-collections": "^4.0.6", + "@libp2p/peer-id": "^3.0.4", + "@libp2p/peer-id-factory": "^3.0.6", + "@libp2p/peer-record": "^6.0.7", + "@libp2p/peer-store": "^9.0.7", + "@libp2p/utils": "^4.0.5", "@multiformats/mafmt": "^12.1.2", "@multiformats/multiaddr": "^12.1.5", "@multiformats/multiaddr-matcher": "^1.0.0", "any-signal": "^4.1.1", "datastore-core": "^9.0.1", "delay": "^6.0.0", - "events": "^3.3.0", "interface-datastore": "^8.2.0", "it-all": "^3.0.2", "it-drain": "^3.0.2", @@ -171,17 +170,17 @@ "@chainsafe/libp2p-gossipsub": "^10.0.0", "@chainsafe/libp2p-noise": "^13.0.0", "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/bootstrap": "^9.0.8", + "@libp2p/bootstrap": "^9.0.9", "@libp2p/daemon-client": "^7.0.0", "@libp2p/daemon-server": "^6.0.0", - "@libp2p/floodsub": "^8.0.9", - "@libp2p/interface-compliance-tests": "^4.1.1", + "@libp2p/floodsub": "^8.0.10", + "@libp2p/interface-compliance-tests": "^4.1.2", "@libp2p/interop": "^9.0.0", - "@libp2p/kad-dht": "^10.0.9", - "@libp2p/mdns": "^9.0.10", - "@libp2p/mplex": "^9.0.8", - "@libp2p/tcp": "^8.0.9", - "@libp2p/websockets": "^7.0.9", + "@libp2p/kad-dht": "^10.0.11", + "@libp2p/mdns": "^9.0.11", + "@libp2p/mplex": "^9.0.9", + "@libp2p/tcp": "^8.0.10", + "@libp2p/websockets": "^7.0.10", "@types/xsalsa20": "^1.1.0", "aegir": "^41.0.2", "execa": "^8.0.1", @@ -193,8 +192,8 @@ "p-times": "^4.0.0", "p-wait-for": "^5.0.2", "protons": "^7.0.2", - "sinon": "^16.0.0", - "sinon-ts": "^1.0.0" + "sinon": "^17.0.0", + "sinon-ts": "^2.0.0" }, "browser": { "./dist/src/connection-manager/constants.js": "./dist/src/connection-manager/constants.browser.js", diff --git a/packages/libp2p/src/address-manager/index.ts b/packages/libp2p/src/address-manager/index.ts index 44a8504f51..f6bafad41f 100644 --- a/packages/libp2p/src/address-manager/index.ts +++ b/packages/libp2p/src/address-manager/index.ts @@ -3,7 +3,7 @@ import { peerIdFromString } from '@libp2p/peer-id' import { multiaddr } from '@multiformats/multiaddr' import { debounce } from './utils.js' import type { Libp2pEvents } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' import type { TransportManager } from '@libp2p/interface-internal/transport-manager' @@ -38,7 +38,7 @@ export interface DefaultAddressManagerComponents { peerId: PeerId transportManager: TransportManager peerStore: PeerStore - events: EventEmitter + events: TypedEventTarget } /** diff --git a/packages/libp2p/src/autonat/index.ts b/packages/libp2p/src/autonat/index.ts index 3f70e6a850..f958d76621 100644 --- a/packages/libp2p/src/autonat/index.ts +++ b/packages/libp2p/src/autonat/index.ts @@ -19,8 +19,8 @@ * ``` */ -import { setMaxListeners } from 'events' import { CodeError } from '@libp2p/interface/errors' +import { setMaxListeners } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { peerIdFromBytes } from '@libp2p/peer-id' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -164,10 +164,7 @@ class DefaultAutoNATService implements Startable { // this controller may be used while dialing lots of peers so prevent MaxListenersExceededWarning // appearing in the console - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, signal) - } catch {} + setMaxListeners(Infinity, signal) const ourHosts = this.components.addressManager.getAddresses() .map(ma => ma.toOptions().host) @@ -432,10 +429,7 @@ class DefaultAutoNATService implements Startable { // this controller may be used while dialing lots of peers so prevent MaxListenersExceededWarning // appearing in the console - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, signal) - } catch {} + setMaxListeners(Infinity, signal) const self = this diff --git a/packages/libp2p/src/circuit-relay/index.ts b/packages/libp2p/src/circuit-relay/index.ts index 91ab9007e4..5e8757fb10 100644 --- a/packages/libp2p/src/circuit-relay/index.ts +++ b/packages/libp2p/src/circuit-relay/index.ts @@ -35,7 +35,7 @@ */ import type { Limit } from './pb/index.js' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventEmitter } from '@libp2p/interface/events' import type { PeerMap } from '@libp2p/peer-collections' import type { Multiaddr } from '@multiformats/multiaddr' @@ -51,7 +51,7 @@ export interface CircuitRelayServiceEvents { 'relay:advert:error': CustomEvent } -export interface CircuitRelayService extends EventEmitter { +export interface CircuitRelayService extends TypedEventEmitter { reservations: PeerMap } diff --git a/packages/libp2p/src/circuit-relay/server/advert-service.ts b/packages/libp2p/src/circuit-relay/server/advert-service.ts index 5d2c61990f..4e84f41c2c 100644 --- a/packages/libp2p/src/circuit-relay/server/advert-service.ts +++ b/packages/libp2p/src/circuit-relay/server/advert-service.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import pRetry from 'p-retry' import { codes } from '../../errors.js' @@ -31,7 +31,7 @@ export interface AdvertServiceEvents { 'advert:error': CustomEvent } -export class AdvertService extends EventEmitter implements Startable { +export class AdvertService extends TypedEventEmitter implements Startable { private readonly contentRouting: ContentRouting private timeout?: any private started: boolean diff --git a/packages/libp2p/src/circuit-relay/server/index.ts b/packages/libp2p/src/circuit-relay/server/index.ts index aed3d5be8b..8da847d95b 100644 --- a/packages/libp2p/src/circuit-relay/server/index.ts +++ b/packages/libp2p/src/circuit-relay/server/index.ts @@ -1,5 +1,4 @@ -import { setMaxListeners } from 'events' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, setMaxListeners } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { peerIdFromBytes } from '@libp2p/peer-id' import { RecordEnvelope } from '@libp2p/peer-record' @@ -99,7 +98,7 @@ const defaults = { maxOutboundStopStreams: MAX_CONNECTIONS } -class CircuitRelayServer extends EventEmitter implements Startable, CircuitRelayService { +class CircuitRelayServer extends TypedEventEmitter implements Startable, CircuitRelayService { private readonly registrar: Registrar private readonly peerStore: PeerStore private readonly addressManager: AddressManager @@ -134,10 +133,7 @@ class CircuitRelayServer extends EventEmitter implements Star this.maxOutboundHopStreams = init.maxOutboundHopStreams this.maxOutboundStopStreams = init.maxOutboundStopStreams ?? defaults.maxOutboundStopStreams - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, this.shutdownController.signal) - } catch { } + setMaxListeners(Infinity, this.shutdownController.signal) if (init.advertise != null && init.advertise !== false) { this.advertService = new AdvertService(components, init.advertise === true ? undefined : init.advertise) diff --git a/packages/libp2p/src/circuit-relay/transport/discovery.ts b/packages/libp2p/src/circuit-relay/transport/discovery.ts index 58ddc80cd9..80bfa1f4d2 100644 --- a/packages/libp2p/src/circuit-relay/transport/discovery.ts +++ b/packages/libp2p/src/circuit-relay/transport/discovery.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { RELAY_RENDEZVOUS_NS, @@ -32,7 +32,7 @@ export interface RelayDiscoveryComponents { * ReservationManager automatically makes a circuit v2 reservation on any connected * peers that support the circuit v2 HOP protocol. */ -export class RelayDiscovery extends EventEmitter implements Startable { +export class RelayDiscovery extends TypedEventEmitter implements Startable { private readonly peerId: PeerId private readonly peerStore: PeerStore private readonly contentRouting: ContentRouting @@ -57,6 +57,7 @@ export class RelayDiscovery extends EventEmitter implement // register a topology listener for when new peers are encountered // that support the hop protocol this.topologyId = await this.registrar.register(RELAY_V2_HOP_CODEC, { + notifyOnTransient: true, onConnect: (peerId) => { this.safeDispatchEvent('relay:discover', { detail: peerId }) } diff --git a/packages/libp2p/src/circuit-relay/transport/index.ts b/packages/libp2p/src/circuit-relay/transport/index.ts index 483f9a0366..022b44c57e 100644 --- a/packages/libp2p/src/circuit-relay/transport/index.ts +++ b/packages/libp2p/src/circuit-relay/transport/index.ts @@ -17,7 +17,7 @@ import type { Libp2pEvents, AbortOptions } from '@libp2p/interface' import type { Connection, Stream } from '@libp2p/interface/connection' import type { ConnectionGater } from '@libp2p/interface/connection-gater' import type { ContentRouting } from '@libp2p/interface/content-routing' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' import type { AddressManager } from '@libp2p/interface-internal/address-manager' @@ -50,7 +50,7 @@ export interface CircuitRelayTransportComponents extends RelayDiscoveryComponent addressManager: AddressManager contentRouting: ContentRouting connectionGater: ConnectionGater - events: EventEmitter + events: TypedEventTarget } interface ConnectOptions { diff --git a/packages/libp2p/src/circuit-relay/transport/listener.ts b/packages/libp2p/src/circuit-relay/transport/listener.ts index dea961b5fd..29b6c6e608 100644 --- a/packages/libp2p/src/circuit-relay/transport/listener.ts +++ b/packages/libp2p/src/circuit-relay/transport/listener.ts @@ -1,5 +1,5 @@ import { CodeError } from '@libp2p/interface/errors' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { PeerMap } from '@libp2p/peer-collections' import { peerIdFromString } from '@libp2p/peer-id' @@ -18,7 +18,7 @@ export interface CircuitRelayTransportListenerComponents { relayStore: ReservationStore } -class CircuitRelayTransportListener extends EventEmitter implements Listener { +class CircuitRelayTransportListener extends TypedEventEmitter implements Listener { private readonly connectionManager: ConnectionManager private readonly relayStore: ReservationStore private readonly listeningAddrs: PeerMap @@ -31,9 +31,11 @@ class CircuitRelayTransportListener extends EventEmitter impleme this.listeningAddrs = new PeerMap() // remove listening addrs when a relay is removed - this.relayStore.addEventListener('relay:removed', (evt) => { - this.#removeRelayPeer(evt.detail) - }) + this.relayStore.addEventListener('relay:removed', this._onRemoveRelayPeer) + } + + _onRemoveRelayPeer = (evt: CustomEvent): void => { + this.#removeRelayPeer(evt.detail) } async listen (addr: Multiaddr): Promise { @@ -100,6 +102,8 @@ class CircuitRelayTransportListener extends EventEmitter impleme this.listeningAddrs.delete(peerId) if (had) { + log.trace('removing relay event listener for peer %p', peerId) + this.relayStore.removeEventListener('relay:removed', this._onRemoveRelayPeer) // Announce listen addresses change this.safeDispatchEvent('close', {}) } diff --git a/packages/libp2p/src/circuit-relay/transport/reservation-store.ts b/packages/libp2p/src/circuit-relay/transport/reservation-store.ts index 2edcd4f998..9300357240 100644 --- a/packages/libp2p/src/circuit-relay/transport/reservation-store.ts +++ b/packages/libp2p/src/circuit-relay/transport/reservation-store.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { PeerMap } from '@libp2p/peer-collections' import { multiaddr } from '@multiformats/multiaddr' @@ -32,7 +32,7 @@ export interface RelayStoreComponents { connectionManager: ConnectionManager transportManager: TransportManager peerStore: PeerStore - events: EventEmitter + events: TypedEventTarget } export interface RelayStoreInit { @@ -76,12 +76,12 @@ export interface ReservationStoreEvents { 'relay:removed': CustomEvent } -export class ReservationStore extends EventEmitter implements Startable { +export class ReservationStore extends TypedEventEmitter implements Startable { private readonly peerId: PeerId private readonly connectionManager: ConnectionManager private readonly transportManager: TransportManager private readonly peerStore: PeerStore - private readonly events: EventEmitter + private readonly events: TypedEventTarget private readonly reserveQueue: PeerJobQueue private readonly reservations: PeerMap private readonly maxDiscoveredRelays: number diff --git a/packages/libp2p/src/components.ts b/packages/libp2p/src/components.ts index f11fb2cfb6..2d65d956dc 100644 --- a/packages/libp2p/src/components.ts +++ b/packages/libp2p/src/components.ts @@ -4,7 +4,7 @@ import type { Libp2pEvents } from '@libp2p/interface' import type { ConnectionProtector } from '@libp2p/interface/connection' import type { ConnectionGater } from '@libp2p/interface/connection-gater' import type { ContentRouting } from '@libp2p/interface/content-routing' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { Metrics } from '@libp2p/interface/metrics' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerRouting } from '@libp2p/interface/peer-routing' @@ -18,7 +18,7 @@ import type { Datastore } from 'interface-datastore' export interface Components extends Record, Startable { peerId: PeerId - events: EventEmitter + events: TypedEventTarget addressManager: AddressManager peerStore: PeerStore upgrader: Upgrader @@ -35,7 +35,7 @@ export interface Components extends Record, Startable { export interface ComponentsInit { peerId?: PeerId - events?: EventEmitter + events?: TypedEventTarget addressManager?: AddressManager peerStore?: PeerStore upgrader?: Upgrader diff --git a/packages/libp2p/src/connection-manager/auto-dial.ts b/packages/libp2p/src/connection-manager/auto-dial.ts index 6d27e6f42b..a110adfd46 100644 --- a/packages/libp2p/src/connection-manager/auto-dial.ts +++ b/packages/libp2p/src/connection-manager/auto-dial.ts @@ -4,7 +4,7 @@ import { toString as uint8ArrayToString } from 'uint8arrays/to-string' import { PeerJobQueue } from '../utils/peer-job-queue.js' import { AUTO_DIAL_CONCURRENCY, AUTO_DIAL_DISCOVERED_PEERS_DEBOUNCE, AUTO_DIAL_INTERVAL, AUTO_DIAL_MAX_QUEUE_LENGTH, AUTO_DIAL_PEER_RETRY_THRESHOLD, AUTO_DIAL_PRIORITY, LAST_DIAL_FAILURE_KEY, MIN_CONNECTIONS } from './constants.js' import type { Libp2pEvents } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerStore } from '@libp2p/interface/peer-store' import type { Startable } from '@libp2p/interface/startable' import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager' @@ -24,7 +24,7 @@ interface AutoDialInit { interface AutoDialComponents { connectionManager: ConnectionManager peerStore: PeerStore - events: EventEmitter + events: TypedEventTarget } const defaultOptions = { diff --git a/packages/libp2p/src/connection-manager/connection-pruner.ts b/packages/libp2p/src/connection-manager/connection-pruner.ts index 04fb85d7fb..adbed0a56c 100644 --- a/packages/libp2p/src/connection-manager/connection-pruner.ts +++ b/packages/libp2p/src/connection-manager/connection-pruner.ts @@ -2,7 +2,7 @@ import { logger } from '@libp2p/logger' import { PeerMap } from '@libp2p/peer-collections' import { MAX_CONNECTIONS } from './constants.js' import type { Libp2pEvents } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerStore } from '@libp2p/interface/peer-store' import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager' import type { Multiaddr } from '@multiformats/multiaddr' @@ -17,7 +17,7 @@ interface ConnectionPrunerInit { interface ConnectionPrunerComponents { connectionManager: ConnectionManager peerStore: PeerStore - events: EventEmitter + events: TypedEventTarget } const defaultOptions = { @@ -33,7 +33,7 @@ export class ConnectionPruner { private readonly connectionManager: ConnectionManager private readonly peerStore: PeerStore private readonly allow: Multiaddr[] - private readonly events: EventEmitter + private readonly events: TypedEventTarget constructor (components: ConnectionPrunerComponents, init: ConnectionPrunerInit = {}) { this.maxConnections = init.maxConnections ?? defaultOptions.maxConnections diff --git a/packages/libp2p/src/connection-manager/dial-queue.ts b/packages/libp2p/src/connection-manager/dial-queue.ts index cb3c926c83..ff58ba62fd 100644 --- a/packages/libp2p/src/connection-manager/dial-queue.ts +++ b/packages/libp2p/src/connection-manager/dial-queue.ts @@ -1,5 +1,5 @@ -import { setMaxListeners } from 'events' import { AbortError, CodeError } from '@libp2p/interface/errors' +import { setMaxListeners } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { defaultAddressSort } from '@libp2p/utils/address-sort' import { type Multiaddr, type Resolver, resolvers } from '@multiformats/multiaddr' @@ -96,10 +96,7 @@ export class DialQueue { this.transportManager = components.transportManager this.shutDownController = new AbortController() - try { - // This emitter gets listened to a lot - setMaxListeners?.(Infinity, this.shutDownController.signal) - } catch {} + setMaxListeners(Infinity, this.shutDownController.signal) this.pendingDialCount = components.metrics?.registerMetric('libp2p_dialler_pending_dials') this.inProgressDialCount = components.metrics?.registerMetric('libp2p_dialler_in_progress_dials') diff --git a/packages/libp2p/src/connection-manager/index.ts b/packages/libp2p/src/connection-manager/index.ts index d94612fd9f..c13e49a53a 100644 --- a/packages/libp2p/src/connection-manager/index.ts +++ b/packages/libp2p/src/connection-manager/index.ts @@ -15,7 +15,7 @@ import { DialQueue } from './dial-queue.js' import type { PendingDial, AddressSorter, Libp2pEvents, AbortOptions } from '@libp2p/interface' import type { Connection, MultiaddrConnection } from '@libp2p/interface/connection' import type { ConnectionGater } from '@libp2p/interface/connection-gater' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { Metrics } from '@libp2p/interface/metrics' import type { PeerId } from '@libp2p/interface/peer-id' import type { Peer, PeerStore } from '@libp2p/interface/peer-store' @@ -165,7 +165,7 @@ export interface DefaultConnectionManagerComponents { peerStore: PeerStore transportManager: TransportManager connectionGater: ConnectionGater - events: EventEmitter + events: TypedEventTarget } /** @@ -187,7 +187,7 @@ export class DefaultConnectionManager implements ConnectionManager, Startable { private readonly peerStore: PeerStore private readonly metrics?: Metrics - private readonly events: EventEmitter + private readonly events: TypedEventTarget constructor (components: DefaultConnectionManagerComponents, init: ConnectionManagerInit = {}) { this.maxConnections = init.maxConnections ?? defaultOptions.maxConnections diff --git a/packages/libp2p/src/connection-manager/utils.ts b/packages/libp2p/src/connection-manager/utils.ts index e195e48bf6..0bec4506ab 100644 --- a/packages/libp2p/src/connection-manager/utils.ts +++ b/packages/libp2p/src/connection-manager/utils.ts @@ -1,4 +1,4 @@ -import { setMaxListeners } from 'events' +import { setMaxListeners } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { type AbortOptions, multiaddr, type Multiaddr } from '@multiformats/multiaddr' import { type ClearableSignal, anySignal } from 'any-signal' @@ -55,10 +55,7 @@ export function combineSignals (...signals: Array): Cle for (const sig of signals) { if (sig != null) { - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, sig) - } catch { } + setMaxListeners(Infinity, sig) sigs.push(sig) } } @@ -66,10 +63,7 @@ export function combineSignals (...signals: Array): Cle // let any signal abort the dial const signal = anySignal(sigs) - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, signal) - } catch {} + setMaxListeners(Infinity, signal) return signal } diff --git a/packages/libp2p/src/connection/index.ts b/packages/libp2p/src/connection/index.ts index 4066e78c93..3aca11759b 100644 --- a/packages/libp2p/src/connection/index.ts +++ b/packages/libp2p/src/connection/index.ts @@ -1,6 +1,6 @@ -import { setMaxListeners } from 'events' import { symbol } from '@libp2p/interface/connection' import { CodeError } from '@libp2p/interface/errors' +import { setMaxListeners } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import type { AbortOptions } from '@libp2p/interface' import type { Direction, Connection, Stream, ConnectionTimeline, ConnectionStatus, NewStreamOptions } from '@libp2p/interface/connection' @@ -93,6 +93,10 @@ export class ConnectionImpl implements Connection { this.encryption = init.encryption this.transient = init.transient ?? false + if (this.remoteAddr.getPeerId() == null) { + this.remoteAddr = this.remoteAddr.encapsulate(`/p2p/${this.remotePeer}`) + } + this._newStream = newStream this._close = close this._abort = abort @@ -152,10 +156,7 @@ export class ConnectionImpl implements Connection { options.signal = options?.signal ?? AbortSignal.timeout(CLOSE_TIMEOUT) - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, options.signal) - } catch { } + setMaxListeners(Infinity, options.signal) try { log.trace('closing all streams') diff --git a/packages/libp2p/src/dcutr/dcutr.ts b/packages/libp2p/src/dcutr/dcutr.ts index e6852b6d03..ce9146d593 100644 --- a/packages/libp2p/src/dcutr/dcutr.ts +++ b/packages/libp2p/src/dcutr/dcutr.ts @@ -1,12 +1,11 @@ import { CodeError } from '@libp2p/interface/errors' import { logger } from '@libp2p/logger' import { type Multiaddr, multiaddr } from '@multiformats/multiaddr' -import { Circuit, IP, DNS } from '@multiformats/multiaddr-matcher' import delay from 'delay' import { pbStream } from 'it-protobuf-stream' -import isPrivate from 'private-ip' import { codes } from '../errors.js' import { HolePunch } from './pb/message.js' +import { isPublicAndDialable } from './utils.js' import { multicodec } from './index.js' import type { DCUtRServiceComponents, DCUtRServiceInit } from './index.js' import type { Connection, Stream } from '@libp2p/interface/connection' @@ -72,6 +71,7 @@ export class DefaultDCUtRService implements Startable { // register for notifications of when peers that support DCUtR connect // nb. requires the identify service to be enabled this.topologyId = await this.registrar.register(multicodec, { + notifyOnTransient: true, onConnect: (peerId, connection) => { if (!connection.transient) { // the connection is already direct, no upgrade is required @@ -241,7 +241,7 @@ export class DefaultDCUtRService implements Startable { return ma }) .filter(ma => { - return this.isPublicAndDialable(ma) + return isPublicAndDialable(ma, this.transportManager) }) if (publicAddresses.length > 0) { @@ -365,7 +365,7 @@ export class DefaultDCUtRService implements Startable { try { const ma = multiaddr(addr) - if (!this.isPublicAndDialable(ma)) { + if (!isPublicAndDialable(ma, this.transportManager)) { continue } @@ -375,35 +375,4 @@ export class DefaultDCUtRService implements Startable { return output } - - /** - * Returns true if the passed multiaddr is public, not relayed and we have a - * transport that can dial it - */ - isPublicAndDialable (ma: Multiaddr): boolean { - // ignore circuit relay - if (Circuit.matches(ma)) { - return false - } - - // dns addresses are probably public? - if (DNS.matches(ma)) { - return true - } - - // ensure we have only IPv4/IPv6 addresses - if (!IP.matches(ma)) { - return false - } - - const transport = this.transportManager.transportForMultiaddr(ma) - - if (transport == null) { - return false - } - - const options = ma.toOptions() - - return isPrivate(options.host) === false - } } diff --git a/packages/libp2p/src/dcutr/utils.ts b/packages/libp2p/src/dcutr/utils.ts new file mode 100644 index 0000000000..c56a139778 --- /dev/null +++ b/packages/libp2p/src/dcutr/utils.ts @@ -0,0 +1,33 @@ +import { type Multiaddr } from '@multiformats/multiaddr' +import { Circuit, IP, DNS } from '@multiformats/multiaddr-matcher' +import isPrivate from 'private-ip' +import type { TransportManager } from '@libp2p/interface-internal/src/transport-manager' + +/** + * Returns true if the passed multiaddr is public, not relayed and we have a + * transport that can dial it + */ +export function isPublicAndDialable (ma: Multiaddr, transportManager: TransportManager): boolean { + // ignore circuit relay + if (Circuit.matches(ma)) { + return false + } + + const transport = transportManager.transportForMultiaddr(ma) + + if (transport == null) { + return false + } + + // dns addresses are probably public? + if (DNS.matches(ma)) { + return true + } + + // ensure we have only IPv4/IPv6 addresses + if (!IP.matches(ma)) { + return false + } + + return isPrivate(ma.toOptions().host) === false +} diff --git a/packages/libp2p/src/fetch/index.ts b/packages/libp2p/src/fetch/index.ts index 3523b2b17d..6e345f0d58 100644 --- a/packages/libp2p/src/fetch/index.ts +++ b/packages/libp2p/src/fetch/index.ts @@ -1,5 +1,5 @@ -import { setMaxListeners } from 'events' import { CodeError } from '@libp2p/interface/errors' +import { setMaxListeners } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import first from 'it-first' import * as lp from 'it-length-prefixed' @@ -146,10 +146,7 @@ class DefaultFetchService implements Startable, FetchService { log('using default timeout of %d ms', this.init.timeout) signal = AbortSignal.timeout(this.init.timeout ?? DEFAULT_TIMEOUT) - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, signal) - } catch {} + setMaxListeners(Infinity, signal) } try { diff --git a/packages/libp2p/src/identify/identify.ts b/packages/libp2p/src/identify/identify.ts index 53c75f800f..5b56096f32 100644 --- a/packages/libp2p/src/identify/identify.ts +++ b/packages/libp2p/src/identify/identify.ts @@ -1,5 +1,5 @@ -import { setMaxListeners } from 'events' import { CodeError } from '@libp2p/interface/errors' +import { setMaxListeners } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { peerIdFromKeys } from '@libp2p/peer-id' import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record' @@ -21,7 +21,7 @@ import { Identify } from './pb/message.js' import type { IdentifyService, IdentifyServiceComponents, IdentifyServiceInit } from './index.js' import type { Libp2pEvents, IdentifyResult, SignedPeerRecord, AbortOptions } from '@libp2p/interface' import type { Connection, Stream } from '@libp2p/interface/connection' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { Peer, PeerStore } from '@libp2p/interface/peer-store' import type { Startable } from '@libp2p/interface/startable' @@ -70,7 +70,7 @@ export class DefaultIdentifyService implements Startable, IdentifyService { private readonly maxPushOutgoingStreams: number private readonly maxIdentifyMessageSize: number private readonly maxObservedAddresses: number - private readonly events: EventEmitter + private readonly events: TypedEventTarget private readonly runOnTransientConnection: boolean constructor (components: IdentifyServiceComponents, init: IdentifyServiceInit) { @@ -187,10 +187,7 @@ export class DefaultIdentifyService implements Startable, IdentifyService { const signal = AbortSignal.timeout(this.timeout) - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, signal) - } catch {} + setMaxListeners(Infinity, signal) try { stream = await connection.newStream([this.identifyPushProtocolStr], { @@ -318,22 +315,7 @@ export class DefaultIdentifyService implements Startable, IdentifyService { this.addressManager.addObservedAddr(cleanObservedAddr) } - const signedPeerRecord = await this.#consumeIdentifyMessage(connection.remotePeer, message) - - const result: IdentifyResult = { - peerId: id, - protocolVersion: message.protocolVersion, - agentVersion: message.agentVersion, - publicKey: message.publicKey, - listenAddrs: message.listenAddrs.map(buf => multiaddr(buf)), - observedAddr: message.observedAddr == null ? undefined : multiaddr(message.observedAddr), - protocols: message.protocols, - signedPeerRecord - } - - this.events.safeDispatchEvent('peer:identify', { detail: result }) - - return result + return this.#consumeIdentifyMessage(connection, message) } /** @@ -345,10 +327,7 @@ export class DefaultIdentifyService implements Startable, IdentifyService { const signal = AbortSignal.timeout(this.timeout) - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, signal) - } catch {} + setMaxListeners(Infinity, signal) try { const publicKey = this.peerId.publicKey ?? new Uint8Array(0) @@ -411,7 +390,7 @@ export class DefaultIdentifyService implements Startable, IdentifyService { const message = await pb.read(options) await stream.close(options) - await this.#consumeIdentifyMessage(connection.remotePeer, message) + await this.#consumeIdentifyMessage(connection, message) } catch (err: any) { log.error('received invalid message', err) stream.abort(err) @@ -421,8 +400,8 @@ export class DefaultIdentifyService implements Startable, IdentifyService { log('handled push from %p', connection.remotePeer) } - async #consumeIdentifyMessage (remotePeer: PeerId, message: Identify): Promise { - log('received identify from %p', remotePeer) + async #consumeIdentifyMessage (connection: Connection, message: Identify): Promise { + log('received identify from %p', connection.remotePeer) if (message == null) { throw new Error('Message was null or undefined') @@ -441,7 +420,7 @@ export class DefaultIdentifyService implements Startable, IdentifyService { // if the peer record has been sent, prefer the addresses in the record as they are signed by the remote peer if (message.signedPeerRecord != null) { - log('received signedPeerRecord in push from %p', remotePeer) + log('received signedPeerRecord in push from %p', connection.remotePeer) let peerRecordEnvelope = message.signedPeerRecord const envelope = await RecordEnvelope.openAndCertify(peerRecordEnvelope, PeerRecord.DOMAIN) @@ -453,7 +432,7 @@ export class DefaultIdentifyService implements Startable, IdentifyService { } // Make sure remote peer is the one sending the record - if (!remotePeer.equals(peerRecord.peerId)) { + if (!connection.remotePeer.equals(peerRecord.peerId)) { throw new Error('signing key does not match remote PeerId') } @@ -499,7 +478,7 @@ export class DefaultIdentifyService implements Startable, IdentifyService { addresses: peerRecord.multiaddrs } } else { - log('%p did not send a signed peer record', remotePeer) + log('%p did not send a signed peer record', connection.remotePeer) } if (message.agentVersion != null) { @@ -510,9 +489,23 @@ export class DefaultIdentifyService implements Startable, IdentifyService { peer.metadata.set('ProtocolVersion', uint8ArrayFromString(message.protocolVersion)) } - await this.peerStore.patch(remotePeer, peer) + await this.peerStore.patch(connection.remotePeer, peer) - return output + const result: IdentifyResult = { + peerId: connection.remotePeer, + protocolVersion: message.protocolVersion, + agentVersion: message.agentVersion, + publicKey: message.publicKey, + listenAddrs: message.listenAddrs.map(buf => multiaddr(buf)), + observedAddr: message.observedAddr == null ? undefined : multiaddr(message.observedAddr), + protocols: message.protocols, + signedPeerRecord: output, + connection + } + + this.events.safeDispatchEvent('peer:identify', { detail: result }) + + return result } } diff --git a/packages/libp2p/src/identify/index.ts b/packages/libp2p/src/identify/index.ts index c74238e832..61dc2e3523 100644 --- a/packages/libp2p/src/identify/index.ts +++ b/packages/libp2p/src/identify/index.ts @@ -5,7 +5,7 @@ import { import { DefaultIdentifyService } from './identify.js' import { Identify } from './pb/message.js' import type { AbortOptions, IdentifyResult, Libp2pEvents } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' import type { Connection } from '@libp2p/interface/src/connection/index.js' @@ -58,7 +58,7 @@ export interface IdentifyServiceComponents { connectionManager: ConnectionManager registrar: Registrar addressManager: AddressManager - events: EventEmitter + events: TypedEventTarget } /** diff --git a/packages/libp2p/src/libp2p.ts b/packages/libp2p/src/libp2p.ts index 29c80f0cc7..5708aa59e3 100644 --- a/packages/libp2p/src/libp2p.ts +++ b/packages/libp2p/src/libp2p.ts @@ -1,8 +1,7 @@ -import { setMaxListeners } from 'events' import { unmarshalPublicKey } from '@libp2p/crypto/keys' import { type ContentRouting, contentRouting } from '@libp2p/interface/content-routing' import { CodeError } from '@libp2p/interface/errors' -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent, setMaxListeners } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { type PeerRouting, peerRouting } from '@libp2p/interface/peer-routing' import { DefaultKeyChain } from '@libp2p/keychain' @@ -42,7 +41,7 @@ import type { Datastore } from 'interface-datastore' const log = logger('libp2p') -export class Libp2pNode> extends EventEmitter implements Libp2p { +export class Libp2pNode> extends TypedEventEmitter implements Libp2p { public peerId: PeerId public peerStore: PeerStore public contentRouting: ContentRouting @@ -59,7 +58,7 @@ export class Libp2pNode> extends // event bus - components can listen to this emitter to be notified of system events // and also cause them to be emitted - const events = new EventEmitter() + const events = new TypedEventEmitter() const originalDispatch = events.dispatchEvent.bind(events) events.dispatchEvent = (evt: any) => { const internalResult = originalDispatch(evt) @@ -70,10 +69,8 @@ export class Libp2pNode> extends return internalResult || externalResult } - try { - // This emitter gets listened to a lot - setMaxListeners?.(Infinity, events) - } catch {} + // This emitter gets listened to a lot + setMaxListeners(Infinity, events) this.#started = false this.peerId = init.peerId diff --git a/packages/libp2p/src/pnet/README.md b/packages/libp2p/src/pnet/README.md index 45708eda85..94d03c0362 100644 --- a/packages/libp2p/src/pnet/README.md +++ b/packages/libp2p/src/pnet/README.md @@ -8,7 +8,6 @@ js-libp2p-pnet ## Table of Contents - [Usage](#usage) -- [Examples](#examples) - [Private Shared Keys](#private-shared-keys) - [PSK Generation](#psk-generation) - [From a module using libp2p](#from-a-module-using-libp2p) @@ -32,9 +31,6 @@ const node = await createLibp2p({ }) ``` -## Examples -[Private Networks with IPFS](../../examples/pnet-ipfs) - ## Private Shared Keys Private Shared Keys are expected to be in the following format: diff --git a/packages/libp2p/src/registrar.ts b/packages/libp2p/src/registrar.ts index c679888f4f..c2998583a2 100644 --- a/packages/libp2p/src/registrar.ts +++ b/packages/libp2p/src/registrar.ts @@ -2,8 +2,8 @@ import { CodeError } from '@libp2p/interface/errors' import { logger } from '@libp2p/logger' import merge from 'merge-options' import { codes } from './errors.js' -import type { Libp2pEvents, PeerUpdate } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { IdentifyResult, Libp2pEvents, PeerUpdate } from '@libp2p/interface' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' import type { Topology } from '@libp2p/interface/topology' @@ -19,7 +19,7 @@ export interface RegistrarComponents { peerId: PeerId connectionManager: ConnectionManager peerStore: PeerStore - events: EventEmitter + events: TypedEventTarget } /** @@ -37,11 +37,11 @@ export class DefaultRegistrar implements Registrar { this._onDisconnect = this._onDisconnect.bind(this) this._onPeerUpdate = this._onPeerUpdate.bind(this) - this._onConnect = this._onConnect.bind(this) + this._onPeerIdentify = this._onPeerIdentify.bind(this) this.components.events.addEventListener('peer:disconnect', this._onDisconnect) - this.components.events.addEventListener('peer:connect', this._onConnect) this.components.events.addEventListener('peer:update', this._onPeerUpdate) + this.components.events.addEventListener('peer:identify', this._onPeerIdentify) } getProtocols (): string[] { @@ -183,52 +183,12 @@ export class DefaultRegistrar implements Registrar { } /** - * On peer connected if we already have their protocols. Usually used for reconnects - * as change:protocols event won't be emitted due to identical protocols. - */ - _onConnect (evt: CustomEvent): void { - const remotePeer = evt.detail - - void this.components.peerStore.get(remotePeer) - .then(peer => { - const connection = this.components.connectionManager.getConnections(peer.id)[0] - - if (connection == null) { - log('peer %p connected but the connection manager did not have a connection', peer) - // peer disconnected while we were loading their details from the peer store - return - } - - for (const protocol of peer.protocols) { - const topologies = this.topologies.get(protocol) - - if (topologies == null) { - // no topologies are interested in this protocol - continue - } - - for (const topology of topologies.values()) { - topology.onConnect?.(remotePeer, connection) - } - } - }) - .catch(err => { - if (err.code === codes.ERR_NOT_FOUND) { - // peer has not completed identify so they are not in the peer store - return - } - - log.error('could not inform topologies of connecting peer %p', remotePeer, err) - }) - } - - /** - * Check if a new peer support the multicodecs for this topology + * When a peer is updated, if they have removed supported protocols notify any + * topologies interested in the removed protocols. */ _onPeerUpdate (evt: CustomEvent): void { const { peer, previous } = evt.detail const removed = (previous?.protocols ?? []).filter(protocol => !peer.protocols.includes(protocol)) - const added = peer.protocols.filter(protocol => !(previous?.protocols ?? []).includes(protocol)) for (const protocol of removed) { const topologies = this.topologies.get(protocol) @@ -242,8 +202,18 @@ export class DefaultRegistrar implements Registrar { topology.onDisconnect?.(peer.id) } } + } - for (const protocol of added) { + /** + * After identify has completed and we have received the list of supported + * protocols, notify any topologies interested in those protocols. + */ + _onPeerIdentify (evt: CustomEvent): void { + const protocols = evt.detail.protocols + const connection = evt.detail.connection + const peerId = evt.detail.peerId + + for (const protocol of protocols) { const topologies = this.topologies.get(protocol) if (topologies == null) { @@ -252,12 +222,11 @@ export class DefaultRegistrar implements Registrar { } for (const topology of topologies.values()) { - const connection = this.components.connectionManager.getConnections(peer.id)[0] - - if (connection == null) { + if (connection.transient && topology.notifyOnTransient !== true) { continue } - topology.onConnect?.(peer.id, connection) + + topology.onConnect?.(peerId, connection) } } } diff --git a/packages/libp2p/src/transport-manager.ts b/packages/libp2p/src/transport-manager.ts index 38f5359616..f18ecdcecc 100644 --- a/packages/libp2p/src/transport-manager.ts +++ b/packages/libp2p/src/transport-manager.ts @@ -5,7 +5,7 @@ import { logger } from '@libp2p/logger' import { codes } from './errors.js' import type { Libp2pEvents, AbortOptions } from '@libp2p/interface' import type { Connection } from '@libp2p/interface/connection' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { Metrics } from '@libp2p/interface/metrics' import type { Startable } from '@libp2p/interface/startable' import type { Listener, Transport, Upgrader } from '@libp2p/interface/transport' @@ -23,7 +23,7 @@ export interface DefaultTransportManagerComponents { metrics?: Metrics addressManager: AddressManager upgrader: Upgrader - events: EventEmitter + events: TypedEventTarget } export class DefaultTransportManager implements TransportManager, Startable { diff --git a/packages/libp2p/src/upgrader.ts b/packages/libp2p/src/upgrader.ts index 18934e3ad0..4000cde7a8 100644 --- a/packages/libp2p/src/upgrader.ts +++ b/packages/libp2p/src/upgrader.ts @@ -1,5 +1,5 @@ -import { setMaxListeners } from 'events' import { CodeError } from '@libp2p/interface/errors' +import { setMaxListeners } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import * as mss from '@libp2p/multistream-select' import { peerIdFromString } from '@libp2p/peer-id' @@ -11,7 +11,7 @@ import type { Libp2pEvents, AbortOptions } from '@libp2p/interface' import type { MultiaddrConnection, Connection, Stream, ConnectionProtector, NewStreamOptions } from '@libp2p/interface/connection' import type { ConnectionEncrypter, SecuredConnection } from '@libp2p/interface/connection-encrypter' import type { ConnectionGater } from '@libp2p/interface/connection-gater' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { Metrics } from '@libp2p/interface/metrics' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' @@ -104,7 +104,7 @@ export interface DefaultUpgraderComponents { connectionProtector?: ConnectionProtector registrar: Registrar peerStore: PeerStore - events: EventEmitter + events: TypedEventTarget } type EncryptedConn = Duplex, Source, Promise> @@ -116,7 +116,7 @@ export class DefaultUpgrader implements Upgrader { private readonly connectionEncryption: Map private readonly muxers: Map private readonly inboundUpgradeTimeout: number - private readonly events: EventEmitter + private readonly events: TypedEventTarget constructor (components: DefaultUpgraderComponents, init: UpgraderInit) { this.components = components @@ -170,10 +170,7 @@ export class DefaultUpgrader implements Upgrader { signal.addEventListener('abort', onAbort, { once: true }) - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, signal) - } catch { } + setMaxListeners(Infinity, signal) try { if ((await this.components.connectionGater.denyInboundConnection?.(maConn)) === true) { @@ -444,10 +441,7 @@ export class DefaultUpgrader implements Upgrader { options.signal = AbortSignal.timeout(30000) - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, options.signal) - } catch { } + setMaxListeners(Infinity, options.signal) } const { stream, protocol } = await mss.select(muxedStream, protocols, options) diff --git a/packages/libp2p/test/addresses/address-manager.spec.ts b/packages/libp2p/test/addresses/address-manager.spec.ts index 7f67fa9b07..cb08202392 100644 --- a/packages/libp2p/test/addresses/address-manager.spec.ts +++ b/packages/libp2p/test/addresses/address-manager.spec.ts @@ -1,10 +1,11 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' import delay from 'delay' +import Sinon from 'sinon' import { type StubbedInstance, stubInterface } from 'sinon-ts' import { type AddressFilter, DefaultAddressManager } from '../../src/address-manager/index.js' import type { Libp2pEvents } from '@libp2p/interface' @@ -18,15 +19,14 @@ const announceAddreses = ['/dns4/peer.io'] describe('Address Manager', () => { let peerId: PeerId let peerStore: StubbedInstance - let events: EventEmitter + let events: TypedEventTarget beforeEach(async () => { peerId = await createEd25519PeerId() peerStore = stubInterface({ - // @ts-expect-error incorrect return type - patch: Promise.resolve({}) + patch: Sinon.stub().resolves({}) }) - events = new EventEmitter() + events = new TypedEventEmitter() }) it('should not need any addresses', () => { @@ -147,7 +147,7 @@ describe('Address Manager', () => { const am = new DefaultAddressManager({ peerId, transportManager: stubInterface({ - getAddrs: [] + getAddrs: Sinon.stub().returns([]) }), peerStore, events diff --git a/packages/libp2p/test/circuit-relay/hop.spec.ts b/packages/libp2p/test/circuit-relay/hop.spec.ts index 7c3405197c..b1beb7abb9 100644 --- a/packages/libp2p/test/circuit-relay/hop.spec.ts +++ b/packages/libp2p/test/circuit-relay/hop.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ['error', 5] */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { isStartable } from '@libp2p/interface/startable' import { mockRegistrar, mockUpgrader, mockNetwork, mockConnectionManager, mockConnectionGater } from '@libp2p/interface-compliance-tests/mocks' import { PeerMap } from '@libp2p/peer-collections' @@ -38,7 +38,7 @@ interface Node { connectionManager: ConnectionManager circuitRelayTransport: Transport connectionGater: ConnectionGater - events: EventEmitter + events: TypedEventTarget } let peerIndex = 0 @@ -66,7 +66,7 @@ describe('circuit-relay hop protocol', function () { ]) const peerStore = stubInterface() - const events = new EventEmitter() + const events = new TypedEventEmitter() events.addEventListener('connection:open', (evt) => { const conn = evt.detail connections.set(conn.remotePeer, conn) diff --git a/packages/libp2p/test/circuit-relay/relay.node.ts b/packages/libp2p/test/circuit-relay/relay.node.ts index 936dfbb869..bcf608a10d 100644 --- a/packages/libp2p/test/circuit-relay/relay.node.ts +++ b/packages/libp2p/test/circuit-relay/relay.node.ts @@ -21,7 +21,7 @@ import { HopMessage, Status } from '../../src/circuit-relay/pb/index.js' import { identifyService } from '../../src/identify/index.js' import { createLibp2p, type Libp2pOptions } from '../../src/index.js' import { plaintext } from '../../src/insecure/index.js' -import { discoveredRelayConfig, doesNotHaveRelay, getRelayAddress, hasRelay, usingAsRelay } from './utils.js' +import { discoveredRelayConfig, doesNotHaveRelay, getRelayAddress, hasRelay, notUsingAsRelay, usingAsRelay, usingAsRelayCount } from './utils.js' import type { Components } from '../../src/components.js' import type { Libp2p } from '@libp2p/interface' import type { Connection } from '@libp2p/interface/connection' @@ -354,7 +354,7 @@ describe('circuit-relay', () => { transports: [ tcp(), circuitRelayTransport({ - discoverRelays: 1 + discoverRelays: 3 }) ] }), @@ -603,6 +603,35 @@ describe('circuit-relay', () => { expect(events[1].detail.remotePeer.toString()).to.equal(relay1.peerId.toString()) }) + it('should remove the relay event listener when the relay stops', async () => { + // discover relay and make reservation + await local.dial(relay1.getMultiaddrs()[0]) + await local.dial(relay2.getMultiaddrs()[0]) + + await usingAsRelayCount(local, [relay1, relay2], 2) + + // expect 2 listeners + // @ts-expect-error these are private fields + const listeners = local.components.transportManager.getListeners() + + // @ts-expect-error as a result these will have any types + const circuitListener = listeners.filter(listener => { + // @ts-expect-error as a result these will have any types + const circuitMultiaddrs = listener.getAddrs().filter(ma => Circuit.matches(ma)) + return circuitMultiaddrs.length > 0 + }) + + expect(circuitListener[0].relayStore.listenerCount('relay:removed')).to.equal(2) + + // remove one listener + await local.hangUp(relay1.peerId) + + await notUsingAsRelay(local, relay1) + + // expect 1 listener + expect(circuitListener[0].relayStore.listenerCount('relay:removed')).to.equal(1) + }) + it('should mark a relayed connection as transient', async () => { // discover relay and make reservation const connectionToRelay = await remote.dial(relay1.getMultiaddrs()[0]) diff --git a/packages/libp2p/test/circuit-relay/stop.spec.ts b/packages/libp2p/test/circuit-relay/stop.spec.ts index 872f01d104..f17642b951 100644 --- a/packages/libp2p/test/circuit-relay/stop.spec.ts +++ b/packages/libp2p/test/circuit-relay/stop.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { isStartable } from '@libp2p/interface/startable' import { mockStream } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -43,7 +43,7 @@ describe('circuit-relay stop protocol', function () { transportManager: stubInterface(), upgrader: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() } transport = circuitRelayTransport({ diff --git a/packages/libp2p/test/circuit-relay/utils.ts b/packages/libp2p/test/circuit-relay/utils.ts index e11bd708f6..aa3cde6e15 100644 --- a/packages/libp2p/test/circuit-relay/utils.ts +++ b/packages/libp2p/test/circuit-relay/utils.ts @@ -30,6 +30,23 @@ export async function usingAsRelay (node: Libp2p, relay: Libp2p, opts?: PWaitFor }, opts) } +export async function usingAsRelayCount (node: Libp2p, relays: Libp2p[], count: number): Promise { + // Wait for peer to be used as a relay + await pWaitFor(async () => { + let relayCount = 0 + + for (const relay of relays) { + for (const addr of node.getMultiaddrs()) { + const search = `${relay.peerId.toString()}/p2p-circuit` + if (addr.toString().includes(search)) { + relayCount++ + } + } + } + return relayCount === count + }) +} + export async function notUsingAsRelay (node: Libp2p, relay: Libp2p, opts?: PWaitForOptions): Promise { // Wait for peer to be used as a relay await pWaitFor(() => { diff --git a/packages/libp2p/test/connection-manager/auto-dial.spec.ts b/packages/libp2p/test/connection-manager/auto-dial.spec.ts index 3c5968bdf1..9e45ae8c7b 100644 --- a/packages/libp2p/test/connection-manager/auto-dial.spec.ts +++ b/packages/libp2p/test/connection-manager/auto-dial.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { PeerMap } from '@libp2p/peer-collections' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { PersistentPeerStore } from '@libp2p/peer-store' @@ -23,13 +23,13 @@ import type { ConnectionManager } from '@libp2p/interface-internal/connection-ma describe('auto-dial', () => { let autoDialler: AutoDial - let events: EventEmitter + let events: TypedEventTarget let peerStore: PeerStore let peerId: PeerId beforeEach(async () => { peerId = await createEd25519PeerId() - events = new EventEmitter() + events = new TypedEventEmitter() peerStore = new PersistentPeerStore({ datastore: new MemoryDatastore(), events, @@ -69,8 +69,8 @@ describe('auto-dial', () => { await peerStore.save(peerWithoutAddress.id, peerWithoutAddress) const connectionManager = stubInterface({ - getConnectionsMap: new PeerMap(), - getDialQueue: [] + getConnectionsMap: Sinon.stub().returns(new PeerMap()), + getDialQueue: Sinon.stub().returns([]) }) autoDialler = new AutoDial({ @@ -123,8 +123,8 @@ describe('auto-dial', () => { connectionMap.set(connectedPeer.id, [stubInterface()]) const connectionManager = stubInterface({ - getConnectionsMap: connectionMap, - getDialQueue: [] + getConnectionsMap: Sinon.stub().returns(connectionMap), + getDialQueue: Sinon.stub().returns([]) }) autoDialler = new AutoDial({ @@ -172,13 +172,13 @@ describe('auto-dial', () => { await peerStore.save(peerNotInDialQueue.id, peerNotInDialQueue) const connectionManager = stubInterface({ - getConnectionsMap: new PeerMap(), - getDialQueue: [{ + getConnectionsMap: Sinon.stub().returns(new PeerMap()), + getDialQueue: Sinon.stub().returns([{ id: 'foo', peerId: peerInDialQueue.id, multiaddrs: [], status: 'queued' - }] + }]) }) autoDialler = new AutoDial({ @@ -203,8 +203,8 @@ describe('auto-dial', () => { const peerStoreAllSpy = Sinon.spy(peerStore, 'all') const connectionManager = stubInterface({ - getConnectionsMap: new PeerMap(), - getDialQueue: [] + getConnectionsMap: Sinon.stub().returns(new PeerMap()), + getDialQueue: Sinon.stub().returns([]) }) autoDialler = new AutoDial({ @@ -254,8 +254,8 @@ describe('auto-dial', () => { await peerStore.save(undialablePeer.id, undialablePeer) const connectionManager = stubInterface({ - getConnectionsMap: new PeerMap(), - getDialQueue: [] + getConnectionsMap: Sinon.stub().returns(new PeerMap()), + getDialQueue: Sinon.stub().returns([]) }) autoDialler = new AutoDial({ diff --git a/packages/libp2p/test/connection-manager/direct.node.ts b/packages/libp2p/test/connection-manager/direct.node.ts index 6da375ad6b..72f478d332 100644 --- a/packages/libp2p/test/connection-manager/direct.node.ts +++ b/packages/libp2p/test/connection-manager/direct.node.ts @@ -6,7 +6,7 @@ import path from 'node:path' import { yamux } from '@chainsafe/libp2p-yamux' import { type Connection, type ConnectionProtector, isConnection } from '@libp2p/interface/connection' import { AbortError } from '@libp2p/interface/errors' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockConnection, mockConnectionGater, mockDuplex, mockMultiaddrConnection, mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { mplex } from '@libp2p/mplex' @@ -22,7 +22,7 @@ import { pipe } from 'it-pipe' import { pushable } from 'it-pushable' import pDefer from 'p-defer' import pWaitFor from 'p-wait-for' -import sinon from 'sinon' +import Sinon from 'sinon' import { stubInterface } from 'sinon-ts' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { DefaultAddressManager } from '../../src/address-manager/index.js' @@ -49,16 +49,16 @@ describe('dialing (direct, TCP)', () => { let remoteAddr: Multiaddr let remoteComponents: Components let localComponents: Components - let resolver: sinon.SinonStub<[Multiaddr], Promise> + let resolver: Sinon.SinonStub<[Multiaddr], Promise> beforeEach(async () => { - resolver = sinon.stub<[Multiaddr], Promise>() + resolver = Sinon.stub<[Multiaddr], Promise>() const [localPeerId, remotePeerId] = await Promise.all([ createEd25519PeerId(), createEd25519PeerId() ]) - const remoteEvents = new EventEmitter() + const remoteEvents = new TypedEventEmitter() remoteComponents = defaultComponents({ peerId: remotePeerId, events: remoteEvents, @@ -66,7 +66,7 @@ describe('dialing (direct, TCP)', () => { upgrader: mockUpgrader({ events: remoteEvents }), connectionGater: mockConnectionGater(), transportManager: stubInterface({ - getAddrs: [] + getAddrs: Sinon.stub().returns([]) }) }) remoteComponents.peerStore = new PersistentPeerStore(remoteComponents) @@ -78,7 +78,7 @@ describe('dialing (direct, TCP)', () => { remoteTM = remoteComponents.transportManager = new DefaultTransportManager(remoteComponents) remoteTM.add(tcp()()) - const localEvents = new EventEmitter() + const localEvents = new TypedEventEmitter() localComponents = defaultComponents({ peerId: localPeerId, events: localEvents, @@ -109,7 +109,7 @@ describe('dialing (direct, TCP)', () => { }) afterEach(() => { - sinon.restore() + Sinon.restore() }) it('should be able to connect to a remote node via its multiaddr', async () => { @@ -194,7 +194,7 @@ describe('dialing (direct, TCP)', () => { const dialer = new DialQueue(localComponents) - sinon.spy(localTM, 'dial') + Sinon.spy(localTM, 'dial') const connection = await dialer.dial(peerId) expect(localTM.dial).to.have.property('callCount', remoteAddrs.length) expect(connection).to.exist() @@ -207,7 +207,7 @@ describe('dialing (direct, TCP)', () => { dialTimeout: 50 }) - sinon.stub(localTM, 'dial').callsFake(async (addr, options = {}) => { + Sinon.stub(localTM, 'dial').callsFake(async (addr, options = {}) => { expect(options.signal).to.exist() expect(options.signal?.aborted).to.equal(false) expect(addr.toString()).to.eql(remoteAddr.toString()) @@ -235,7 +235,7 @@ describe('dialing (direct, TCP)', () => { }) const deferredDial = pDefer() - const transportManagerDialStub = sinon.stub(localTM, 'dial') + const transportManagerDialStub = Sinon.stub(localTM, 'dial') transportManagerDialStub.callsFake(async () => deferredDial.promise) // Perform 3 multiaddr dials @@ -273,7 +273,7 @@ describe('dialing (direct, TCP)', () => { maxParallelDialsPerPeer: 10 }) - const transportManagerDialStub = sinon.stub(localTM, 'dial') + const transportManagerDialStub = Sinon.stub(localTM, 'dial') transportManagerDialStub.callsFake(async (ma) => { await delay(10) return mockConnection(mockMultiaddrConnection(mockDuplex(), remoteComponents.peerId)) @@ -340,7 +340,7 @@ describe('libp2p.dialer (direct, TCP)', () => { }) afterEach(async () => { - sinon.restore() + Sinon.restore() if (libp2p != null) { await libp2p.stop() @@ -515,7 +515,7 @@ describe('libp2p.dialer (direct, TCP)', () => { connectionProtector: () => protector }) - const protectorProtectSpy = sinon.spy(protector, 'protect') + const protectorProtectSpy = Sinon.spy(protector, 'protect') remoteLibp2p.components.connectionProtector = preSharedKey({ psk: swarmKeyBuffer })() @@ -589,7 +589,7 @@ describe('libp2p.dialer (direct, TCP)', () => { const dials = 10 const error = new Error('Boom') - sinon.stub(libp2p.components.transportManager, 'dial').callsFake(async () => Promise.reject(error)) + Sinon.stub(libp2p.components.transportManager, 'dial').callsFake(async () => Promise.reject(error)) await libp2p.peerStore.patch(remotePeerId, { multiaddrs: remoteLibp2p.getMultiaddrs() diff --git a/packages/libp2p/test/connection-manager/direct.spec.ts b/packages/libp2p/test/connection-manager/direct.spec.ts index 86bba75ea2..bb90e75d5c 100644 --- a/packages/libp2p/test/connection-manager/direct.spec.ts +++ b/packages/libp2p/test/connection-manager/direct.spec.ts @@ -2,7 +2,7 @@ import { yamux } from '@chainsafe/libp2p-yamux' import { AbortError } from '@libp2p/interface/errors' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockConnectionGater, mockDuplex, mockMultiaddrConnection, mockUpgrader, mockConnection } from '@libp2p/interface-compliance-tests/mocks' import { mplex } from '@libp2p/mplex' import { peerIdFromString } from '@libp2p/peer-id' @@ -45,7 +45,7 @@ describe('dialing (direct, WebSockets)', () => { let connectionManager: DefaultConnectionManager beforeEach(async () => { - const localEvents = new EventEmitter() + const localEvents = new TypedEventEmitter() localComponents = defaultComponents({ peerId: await createEd25519PeerId(), datastore: new MemoryDatastore(), diff --git a/packages/libp2p/test/connection-manager/index.node.ts b/packages/libp2p/test/connection-manager/index.node.ts index add7158a47..cac8b990d3 100644 --- a/packages/libp2p/test/connection-manager/index.node.ts +++ b/packages/libp2p/test/connection-manager/index.node.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start } from '@libp2p/interface/startable' import { mockConnection, mockDuplex, mockMultiaddrConnection } from '@libp2p/interface-compliance-tests/mocks' import { expect } from 'aegir/chai' @@ -53,7 +53,7 @@ describe('Connection Manager', () => { peerStore, transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }) const connectionManager = new DefaultConnectionManager(components, { maxConnections: 1000, @@ -91,7 +91,7 @@ describe('Connection Manager', () => { peerStore, transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }) const connectionManager = new DefaultConnectionManager(components, { maxConnections: 1000, diff --git a/packages/libp2p/test/connection-manager/index.spec.ts b/packages/libp2p/test/connection-manager/index.spec.ts index 699339da03..ee31843332 100644 --- a/packages/libp2p/test/connection-manager/index.spec.ts +++ b/packages/libp2p/test/connection-manager/index.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { KEEP_ALIVE } from '@libp2p/interface/peer-store/tags' import { mockConnection, mockDuplex, mockMultiaddrConnection, mockMetrics } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -365,7 +365,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }, { ...defaultOptions, deny: [ @@ -393,7 +393,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }, { ...defaultOptions, maxConnections: 1 @@ -425,7 +425,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }, { ...defaultOptions, inboundConnectionThreshold: 1 @@ -461,7 +461,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }, { ...defaultOptions, maxConnections: 1, @@ -497,7 +497,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }, { ...defaultOptions, maxIncomingPendingConnections: 1 diff --git a/packages/libp2p/test/connection/index.spec.ts b/packages/libp2p/test/connection/index.spec.ts index 03c21202be..d249731f55 100644 --- a/packages/libp2p/test/connection/index.spec.ts +++ b/packages/libp2p/test/connection/index.spec.ts @@ -1,86 +1,59 @@ -import * as PeerIdFactory from '@libp2p/peer-id-factory' +import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' +import { expect } from 'aegir/chai' +import Sinon from 'sinon' import { createConnection } from '../../src/connection/index.js' -import { pair } from './fixtures/pair.js' -import type { Stream } from '@libp2p/interface/connection' -const peers = [{ - id: 'QmNMMAqSxPetRS1cVMmutW5BCN1qQQyEr4u98kUvZjcfEw', - privKey: 'CAASpQkwggShAgEAAoIBAQDPek2aeHMa0blL42RTKd6xgtkk4Zkldvq4LHxzcag5uXepiQzWANEUvoD3KcUTmMRmx14PvsxdLCNst7S2JSa0R2n5wSRs14zGy6892lx4H4tLBD1KSpQlJ6vabYM1CJhIQRG90BtzDPrJ/X1iJ2HA0PPDz0Mflam2QUMDDrU0IuV2m7gSCJ5r4EmMs3U0xnH/1gShkVx4ir0WUdoWf5KQUJOmLn1clTRHYPv4KL9A/E38+imNAXfkH3c2T7DrCcYRkZSpK+WecjMsH1dCX15hhhggNqfp3iulO1tGPxHjm7PDGTPUjpCWKpD5e50sLqsUwexac1ja6ktMfszIR+FPAgMBAAECggEAB2H2uPRoRCAKU+T3gO4QeoiJaYKNjIO7UCplE0aMEeHDnEjAKC1HQ1G0DRdzZ8sb0fxuIGlNpFMZv5iZ2ZFg2zFfV//DaAwTek9tIOpQOAYHUtgHxkj5FIlg2BjlflGb+ZY3J2XsVB+2HNHkUEXOeKn2wpTxcoJE07NmywkO8Zfr1OL5oPxOPlRN1gI4ffYH2LbfaQVtRhwONR2+fs5ISfubk5iKso6BX4moMYkxubYwZbpucvKKi/rIjUA3SK86wdCUnno1KbDfdXSgCiUlvxt/IbRFXFURQoTV6BOi3sP5crBLw8OiVubMr9/8WE6KzJ0R7hPd5+eeWvYiYnWj4QKBgQD6jRlAFo/MgPO5NZ/HRAk6LUG+fdEWexA+GGV7CwJI61W/Dpbn9ZswPDhRJKo3rquyDFVZPdd7+RlXYg1wpmp1k54z++L1srsgj72vlg4I8wkZ4YLBg0+zVgHlQ0kxnp16DvQdOgiRFvMUUMEgetsoIx1CQWTd67hTExGsW+WAZQKBgQDT/WaHWvwyq9oaZ8G7F/tfeuXvNTk3HIJdfbWGgRXB7lJ7Gf6FsX4x7PeERfL5a67JLV6JdiLLVuYC2CBhipqLqC2DB962aKMvxobQpSljBBZvZyqP1IGPoKskrSo+2mqpYkeCLbDMuJ1nujgMP7gqVjabs2zj6ACKmmpYH/oNowJ/T0ZVtvFsjkg+1VsiMupUARRQuPUWMwa9HOibM1NIZcoQV2NGXB5Z++kR6JqxQO0DZlKArrviclderUdY+UuuY4VRiSEprpPeoW7ZlbTku/Ap8QZpWNEzZorQDro7bnfBW91fX9/81ets/gCPGrfEn+58U3pdb9oleCOQc/ifpQKBgBTYGbi9bYbd9vgZs6bd2M2um+VFanbMytS+g5bSIn2LHXkVOT2UEkB+eGf9KML1n54QY/dIMmukA8HL1oNAyalpw+/aWj+9Ui5kauUhGEywHjSeBEVYM9UXizxz+m9rsoktLLLUI0o97NxCJzitG0Kub3gn0FEogsUeIc7AdinZAoGBANnM1vcteSQDs7x94TDEnvvqwSkA2UWyLidD2jXgE0PG4V6tTkK//QPBmC9eq6TIqXkzYlsErSw4XeKO91knFofmdBzzVh/ddgx/NufJV4tXF+a2iTpqYBUJiz9wpIKgf43/Ob+P1EA99GAhSdxz1ess9O2aTqf3ANzn6v6g62Pv', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPek2aeHMa0blL42RTKd6xgtkk4Zkldvq4LHxzcag5uXepiQzWANEUvoD3KcUTmMRmx14PvsxdLCNst7S2JSa0R2n5wSRs14zGy6892lx4H4tLBD1KSpQlJ6vabYM1CJhIQRG90BtzDPrJ/X1iJ2HA0PPDz0Mflam2QUMDDrU0IuV2m7gSCJ5r4EmMs3U0xnH/1gShkVx4ir0WUdoWf5KQUJOmLn1clTRHYPv4KL9A/E38+imNAXfkH3c2T7DrCcYRkZSpK+WecjMsH1dCX15hhhggNqfp3iulO1tGPxHjm7PDGTPUjpCWKpD5e50sLqsUwexac1ja6ktMfszIR+FPAgMBAAE=' -}, { - id: 'QmW8rAgaaA6sRydK1k6vonShQME47aDxaFidbtMevWs73t', - privKey: 'CAASpwkwggSjAgEAAoIBAQCTU3gVDv3SRXLOsFln9GEf1nJ/uCEDhOG10eC0H9l9IPpVxjuPT1ep+ykFUdvefq3D3q+W3hbmiHm81o8dYv26RxZIEioToUWp7Ec5M2B/niYoE93za9/ZDwJdl7eh2hNKwAdxTmdbXUPjkIU4vLyHKRFbJIn9X8w9djldz8hoUvC1BK4L1XrT6F2l0ruJXErH2ZwI1youfSzo87TdXIoFKdrQLuW6hOtDCGKTiS+ab/DkMODc6zl8N47Oczv7vjzoWOJMUJs1Pg0ZsD1zmISY38P0y/QyEhatZn0B8BmSWxlLQuukatzOepQI6k+HtfyAAjn4UEqnMaXTP1uwLldVAgMBAAECggEAHq2f8MqpYjLiAFZKl9IUs3uFZkEiZsgx9BmbMAb91Aec+WWJG4OLHrNVTG1KWp+IcaQablEa9bBvoToQnS7y5OpOon1d066egg7Ymfmv24NEMM5KRpktCNcOSA0CySpPIB6yrg6EiUr3ixiaFUGABKkxmwgVz/Q15IqM0ZMmCUsC174PMAz1COFZxD0ZX0zgHblOJQW3dc0X3XSzhht8vU02SMoVObQHQfeXEHv3K/RiVj/Ax0bTc5JVkT8dm8xksTtsFCNOzRBqFS6MYqX6U/u0Onz3Jm5Jt7fLWb5n97gZR4SleyGrqxYNb46d9X7mP0ie7E6bzFW0DsWBIeAqVQKBgQDW0We2L1n44yOvJaMs3evpj0nps13jWidt2I3RlZXjWzWHiYQfvhWUWqps/xZBnAYgnN/38xbKzHZeRNhrqOo+VB0WK1IYl0lZVE4l6TNKCsLsUfQzsb1pePkd1eRZA+TSqsi+I/IOQlQU7HA0bMrah/5FYyUBP0jYvCOvYTlZuwKBgQCvkcVRydVlzjUgv7lY5lYvT8IHV5iYO4Qkk2q6Wjv9VUKAJZauurMdiy05PboWfs5kbETdwFybXMBcknIvZO4ihxmwL8mcoNwDVZHI4bXapIKMTCyHgUKvJ9SeTcKGC7ZuQJ8mslRmYox/HloTOXEJgQgPRxXcwa3amzvdZI+6LwKBgQCLsnQqgxKUi0m6bdR2qf7vzTH4258z6X34rjpT0F5AEyF1edVFOz0XU/q+lQhpNEi7zqjLuvbYfSyA026WXKuwSsz7jMJ/oWqev/duKgAjp2npesY/E9gkjfobD+zGgoS9BzkyhXe1FCdP0A6L2S/1+zg88WOwMvJxl6/xLl24XwKBgCm60xSajX8yIQyUpWBM9yUtpueJ2Xotgz4ST+bVNbcEAddll8gWFiaqgug9FLLuFu5lkYTHiPtgc1RNdphvO+62/9MRuLDixwh/2TPO+iNqwKDKJjda8Nei9vVddCPaOtU/xNQ0xLzFJbG9LBmvqH9izOCcu8SJwGHaTcNUeJj/AoGADCJ26cY30c13F/8awAAmFYpZWCuTP5ppTsRmjd63ixlrqgkeLGpJ7kYb5fXkcTycRGYgP0e1kssBGcmE7DuG955fx3ZJESX3GQZ+XfMHvYGONwF1EiK1f0p6+GReC2VlQ7PIkoD9o0hojM6SnWvv9EXNjCPALEbfPFFvcniKVsE=', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCTU3gVDv3SRXLOsFln9GEf1nJ/uCEDhOG10eC0H9l9IPpVxjuPT1ep+ykFUdvefq3D3q+W3hbmiHm81o8dYv26RxZIEioToUWp7Ec5M2B/niYoE93za9/ZDwJdl7eh2hNKwAdxTmdbXUPjkIU4vLyHKRFbJIn9X8w9djldz8hoUvC1BK4L1XrT6F2l0ruJXErH2ZwI1youfSzo87TdXIoFKdrQLuW6hOtDCGKTiS+ab/DkMODc6zl8N47Oczv7vjzoWOJMUJs1Pg0ZsD1zmISY38P0y/QyEhatZn0B8BmSWxlLQuukatzOepQI6k+HtfyAAjn4UEqnMaXTP1uwLldVAgMBAAE=' -}, { - id: 'QmZqCdSzgpsmB3Qweb9s4fojAoqELWzqku21UVrqtVSKi4', - privKey: 'CAASpgkwggSiAgEAAoIBAQCdbSEsTmw7lp5HagRcx57DaLiSUEkh4iBcKc7Y+jHICEIA8NIVi9FlfGEZj9G21FpiTR4Cy+BLVEuf8Nm90bym4iV+cSumeS21fvD8xGTEbeKGljs6OYHy3M45JhWF85gqHQJOqZufI2NRDuRgMZEO2+qGEXmSlv9mMXba/+9ecze8nSpB7bG2Z2pnKDeYwhF9Cz+ElMyn7TBWDjJERGVgFbTpdM3rBnbhB/TGpvs732QqZmIBlxnDb/Jn0l1gNZCgkEDcJ/0NDMBJTQ8vbvcdmaw3eaMPLkn1ix4wdu9QWCA0IBtuY1R7vSUtf4irnLJG7DnAw2GfM5QrF3xF1GLXAgMBAAECggEAQ1N0qHoxl5pmvqv8iaFlqLSUmx5y6GbI6CGJMQpvV9kQQU68yjItr3VuIXx8d/CBZyEMAK4oko7OeOyMcr3MLKLy3gyQWnXgsopDjhZ/8fH8uwps8g2+IZuFJrO+6LaxEPGvFu06fOiphPUVfn40R2KN/iBjGeox+AaXijmCqaV2vEdNJJPpMfz6VKZBDLTrbiqvo/3GN1U99PUqfPWpOWR29oAhh/Au6blSqvqTUPXB2+D/X6e1JXv31mxMPK68atDHSUjZWKB9lE4FMK1bkSKJRbyXmNIlbZ9V8X4/0r8/6T7JnW7ZT8ugRkquohmwgG7KkDXB1YsOCKXYUqzVYQKBgQDtnopFXWYl7XUyePJ/2MA5i7eoko9jmF44L31irqmHc5unNf6JlNBjlxTNx3WyfzhUzrn3c18psnGkqtow0tkBj5hmqn8/WaPbc5UA/5R1FNaNf8W5khn7MDm6KtYRPjN9djqTDiVHyC6ljONYd+5S+MqyKVWZ3t/xvG60sw85qwKBgQCpmpDtL+2JBwkfeUr3LyDcQxvbfzcv8lXj2otopWxWiLiZF1HzcqgAa2CIwu9kCGEt9Zr+9E4uINbe1To0b01/FhvR6xKO/ukceGA/mBB3vsKDcRmvpBUp+3SmnhY0nOk+ArQl4DhJ34k8pDM3EDPrixPf8SfVdU/8IM32lsdHhQKBgHLgpvCKCwxjFLnmBzcPzz8C8TOqR3BbBZIcQ34l+wflOGdKj1hsfaLoM8KYn6pAHzfBCd88A9Hg11hI0VuxVACRL5jS7NnvuGwsIOluppNEE8Ys86aXn7/0vLPoab3EWJhbRE48FIHzobmft3nZ4XpzlWs02JGfUp1IAC2UM9QpAoGAeWy3pZhSr2/iEC5+hUmwdQF2yEbj8+fDpkWo2VrVnX506uXPPkQwE1zM2Bz31t5I9OaJ+U5fSpcoPpDaAwBMs1fYwwlRWB8YNdHY1q6/23svN3uZsC4BGPV2JnO34iMUudilsRg+NGVdk5TbNejbwx7nM8Urh59djFzQGGMKeSECgYA0QMCARPpdMY50Mf2xQaCP7HfMJhESSPaBq9V3xY6ToEOEnXgAR5pNjnU85wnspHp+82r5XrKfEQlFxGpj2YA4DRRmn239sjDa29qP42UNAFg1+C3OvXTht1d5oOabaGhU0udwKmkEKUbb0bG5xPQJ5qeSJ5T1gLzLk3SIP0GlSw==', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCdbSEsTmw7lp5HagRcx57DaLiSUEkh4iBcKc7Y+jHICEIA8NIVi9FlfGEZj9G21FpiTR4Cy+BLVEuf8Nm90bym4iV+cSumeS21fvD8xGTEbeKGljs6OYHy3M45JhWF85gqHQJOqZufI2NRDuRgMZEO2+qGEXmSlv9mMXba/+9ecze8nSpB7bG2Z2pnKDeYwhF9Cz+ElMyn7TBWDjJERGVgFbTpdM3rBnbhB/TGpvs732QqZmIBlxnDb/Jn0l1gNZCgkEDcJ/0NDMBJTQ8vbvcdmaw3eaMPLkn1ix4wdu9QWCA0IBtuY1R7vSUtf4irnLJG7DnAw2GfM5QrF3xF1GLXAgMBAAE=' -}, { - id: 'QmR5VwgsL7jyfZHAGyp66tguVrQhCRQuRc3NokocsCZ3fA', - privKey: 'CAASpwkwggSjAgEAAoIBAQCGXYU+uc2nn1zuJhfdFOl34upztnrD1gpHu58ousgHdGlGgYgbqLBAvIAauXdEL0+e30HofjA634SQxE+9nV+0FQBam1DDzHQlXsuwHV+2SKvSDkk4bVllMFpu2SJtts6VH+OXC/2ANJOm+eTALykQPYXgLIBxrhp/eD+Jz5r6wW2nq3k6OmYyK/4pgGzFjo5UyX+fa/171AJ68UPboFpDy6BZCcUjS0ondxPvD7cv5jMNqqMKIB/7rpi8n+Q3oeccRqVL56wH+FE3/QLjwYHwY6ILNRyvNXRqHjwBEXB2R5moXN0AFUWTw9rt3KhFiEjR1U81BTw5/xS7W2Iu0FgZAgMBAAECggEAS64HK8JZfE09eYGJNWPe8ECmD1C7quw21BpwVe+GVPSTizvQHswPohbKDMNj0srXDMPxCnNw1OgqcaOwyjsGuZaOoXoTroTM8nOHRIX27+PUqzaStS6aCG2IsiCozKUHjGTuupftS7XRaF4eIsUtWtFcQ1ytZ9pJYHypRQTi5NMSrTze5ThjnWxtHilK7gnBXik+aR0mYEVfSn13czQEC4rMOs+b9RAc/iibDNoLopfIdvmCCvfxzmySnR7Cu1iSUAONkir7PB+2Mt/qRFCH6P+jMamtCgQ8AmifXgVmDUlun+4MnKg3KrPd6ZjOEKhVe9mCHtGozk65RDREShfDdQKBgQDi+x2MuRa9peEMOHnOyXTS+v+MFcfmG0InsO08rFNBKZChLB+c9UHBdIvexpfBHigSyERfuDye4z6lxi8ZnierWMYJP30nxmrnxwTGTk1MQquhfs1A0kpmDnPsjlOS/drEIEIssNx2WbfJ7YtMxLWBtp+BJzGpQmr0LKC+NHRSrwKBgQCXiy2kJESIUkIs2ihV55hhT6/bZo1B1O5DPA2nkjOBXqXF6fvijzMDX82JjLd07lQZlI0n1Q/Hw0p4iYi9YVd2bLkLXF5UIb2qOeHj76enVFOrPHUSkC9Y2g/0Xs+60Ths2xRd8RrrfQU3kl5iVpBywkCIrb2M5+wRnNTk1W3TtwKBgQCvplyrteAfSurpJhs9JzE8w/hWU9SqAZYkWQp91W1oE95Um2yrbjBAoQxMjaqKS+f/APPIjy56Vqj4aHGyhW11b/Fw3qzfxvCcBKtxOs8eoMlo5FO6QgJJEA4tlcafDcvp0nzjUMqK28safLU7503+33B35fjMXxWdd5u9FaKfCQKBgC4W6j6tuRosymuRvgrCcRnHfpify/5loEFallyMnpWOD6Tt0OnK25z/GifnYDRz96gAAh5HMpFy18dpLOlMHamqz2yhHx8/U8vd5tHIJZlCkF/X91M5/uxrBccwvsT2tM6Got8fYSyVzWxlW8dUxIHiinYHQUsFjkqdBDLEpq5pAoGASoTw5RBEWFM0GuAZdXsyNyxU+4S+grkTS7WdW/Ymkukh+bJZbnvF9a6MkSehqXnknthmufonds2AFNS//63gixENsoOhzT5+2cdfc6tJECvJ9xXVXkf85AoQ6T/RrXF0W4m9yQyCngNJUrKUOIH3oDIfdZITlYzOC3u1ojj7VuQ=', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCGXYU+uc2nn1zuJhfdFOl34upztnrD1gpHu58ousgHdGlGgYgbqLBAvIAauXdEL0+e30HofjA634SQxE+9nV+0FQBam1DDzHQlXsuwHV+2SKvSDkk4bVllMFpu2SJtts6VH+OXC/2ANJOm+eTALykQPYXgLIBxrhp/eD+Jz5r6wW2nq3k6OmYyK/4pgGzFjo5UyX+fa/171AJ68UPboFpDy6BZCcUjS0ondxPvD7cv5jMNqqMKIB/7rpi8n+Q3oeccRqVL56wH+FE3/QLjwYHwY6ILNRyvNXRqHjwBEXB2R5moXN0AFUWTw9rt3KhFiEjR1U81BTw5/xS7W2Iu0FgZAgMBAAE=' -}, { - id: 'QmScLDqRg7H6ipCYxm9fVk152UWavQFKscTdoT4YNHxgqp', - privKey: 'CAASpwkwggSjAgEAAoIBAQCWEHaTZ6LBLFP5OPrUqjDM/cF4b2zrfh1Zm3kd02ZtgQB3iYtZqRPJT5ctT3A7WdVF/7dCxPGOCkJlLekTx4Y4gD8JtjA+EfN9fR/2RBKbti2N3CD4vkGp9ss4hbBFcXIhl8zuD/ELHutbV6b8b4QXJGnxfp/B+1kNPnyd7SJznS0QyvI8OLI1nAkVKdYLDRW8kPKeHyx1xhdNDuTQVTFyAjRGQ4e3UYFB7bYIHW3E6kCtCoJDlj+JPC02Yt1LHzIzZVLvPvNFnYY2mag6OiGFuh/oMBIqvnPc1zRZ3eLUqeGZjQVaoR0kdgZUKz7Q2TBeNldxK/s6XO0DnkQTlelNAgMBAAECggEAdmt1dyswR2p4tdIeNpY7Pnj9JNIhTNDPznefI0dArCdBvBMhkVaYk6MoNIxcj6l7YOrDroAF8sXr0TZimMY6B/pERKCt/z1hPWTxRQBBAvnHhwvwRPq2jK6BfhAZoyM8IoBNKowP9mum5QUNdGV4Al8s73KyFX0IsCfgZSvNpRdlt+DzPh+hu/CyoZaMpRchJc1UmK8Fyk3KfO+m0DZNfHP5P08lXNfM6MZLgTJVVgERHyG+vBOzTd2RElMe19nVCzHwb3dPPRZSQ7Fnz3rA+GeLqsM2Zi4HNhfbD1OcD9C4wDj5tYL6hWTkdz4IlfVcjCeUHxgIOhdDV2K+OwbuAQKBgQD0FjUZ09UW2FQ/fitbvIB5f1SkXWPxTF9l6mAeuXhoGv2EtQUO4vq/PK6N08RjrZdWQy6UsqHgffi7lVQ8o3hvCKdbtf4sP+cM92OrY0WZV89os79ndj4tyvmnP8WojwRjt/2XEfgdoWcgWxW9DiYINTOQVimZX+X/3on4s8hEgQKBgQCdY3kOMbyQeLTRkqHXjVTY4ddO+v4S4wOUa1l4rTqAbq1W3JYWwoDQgFuIu3limIHmjnSJpCD4EioXFsM7p6csenoc20sHxsaHnJ6Mn5Te41UYmY9EW0otkQ0C3KbXM0hwQkjyplnEmZawGKmjEHW8DJ3vRYTv9TUCgYKxDHgOzQKBgB4A/NYH7BG61eBYKgxEx6YnuMfbkwV+Vdu5S8d7FQn3B2LgvZZu4FPRqcNVXLbEB+5ao8czjiKCWaj1Wj15+rvrXGcxn+Tglg5J+r5+nXeUC7LbJZQaPNp0MOwWMr3dlrSLUWjYlJ9Pz9VyXOG4c4Rexc/gR4zK9QLW4C7qKpwBAoGAZzyUb0cYlPtYQA+asTU3bnvVKy1f8yuNcZFowst+EDiI4u0WVh+HNzy6zdmLKa03p+/RaWeLaK0hhrubnEnAUmCUMNF3ScaM+u804LDcicc8TkKLwx7ObU0z56isl4RAA8K27tNHFrpYKXJD834cfBkaj5ReOrfw6Y/iFhhDuBECgYEA8gbC76uz7LSHhW30DSRTcqOzTyoe2oYKQaxuxYNp7vSSOkcdRen+mrdflDvud2q/zN2QdL4pgqdldHlR35M/lJ0f0B6zp74jlzbO9700wzsOqreezGc5eWiroDL100U9uIZ50BKb8CKtixIHpinUSPIUcVDkSAZ2y7mbfCxQwqQ=', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCWEHaTZ6LBLFP5OPrUqjDM/cF4b2zrfh1Zm3kd02ZtgQB3iYtZqRPJT5ctT3A7WdVF/7dCxPGOCkJlLekTx4Y4gD8JtjA+EfN9fR/2RBKbti2N3CD4vkGp9ss4hbBFcXIhl8zuD/ELHutbV6b8b4QXJGnxfp/B+1kNPnyd7SJznS0QyvI8OLI1nAkVKdYLDRW8kPKeHyx1xhdNDuTQVTFyAjRGQ4e3UYFB7bYIHW3E6kCtCoJDlj+JPC02Yt1LHzIzZVLvPvNFnYY2mag6OiGFuh/oMBIqvnPc1zRZ3eLUqeGZjQVaoR0kdgZUKz7Q2TBeNldxK/s6XO0DnkQTlelNAgMBAAE=' -}, { - id: 'QmckxVrJw1Yo8LqvmDJNUmdAsKtSbiKWmrXJFyKmUraBoN', - privKey: 'CAASpwkwggSjAgEAAoIBAQC1/GFud/7xutux7qRfMj1sIdMRh99/chR6HqVj6LQqrgk4jil0mdN/LCk/tqPqmDtObHdmEhCoybzuhLbCKgUqryKDwO6yBJHSKWY9QqrKZtLJ37SgKwGjE3+NUD4r1dJHhtQrICFdOdSCBzs/v8gi+J+KZLHo7+Nms4z09ysy7qZh94Pd7cW4gmSMergqUeANLD9C0ERw1NXolswOW7Bi7UGr7yuBxejICLO3nkxe0OtpQBrYrqdCD9vs3t/HQZbPWVoiRj4VO7fxkAPKLl30HzcIfxj/ayg8NHcH59d08D+N2v5Sdh28gsiYKIPE9CXvuw//HUY2WVRY5fDC5JglAgMBAAECggEBAKb5aN/1w3pBqz/HqRMbQpYLNuD33M3PexBNPAy+P0iFpDo63bh5Rz+A4lvuFNmzUX70MFz7qENlzi6+n/zolxMB29YtWBUH8k904rTEjXXl//NviQgITZk106tx+4k2x5gPEm57LYGfBOdFAUzNhzDnE2LkXwRNzkS161f7zKwOEsaGWRscj6UvhO4MIFxjb32CVwt5eK4yOVqtyMs9u30K4Og+AZYTlhtm+bHg6ndCCBO6CQurCQ3jD6YOkT+L3MotKqt1kORpvzIB0ujZRf49Um8wlcjC5G9aexBeGriXaVdPF62zm7GA7RMsbQM/6aRbA1fEQXvJhHUNF9UFeaECgYEA8wCjKqQA7UQnHjRwTsktdwG6szfxd7z+5MTqHHTWhWzgcQLgdh5/dO/zanEoOThadMk5C1Bqjq96gH2xim8dg5XQofSVtV3Ui0dDa+XRB3E3fyY4D3RF5hHv85O0GcvQc6DIb+Ja1oOhvHowFB1C+CT3yEgwzX/EK9xpe+KtYAkCgYEAv7hCnj/DcZFU3fAfS+unBLuVoVJT/drxv66P686s7J8UM6tW+39yDBZ1IcwY9vHFepBvxY2fFfEeLI02QFM+lZXVhNGzFkP90agNHK01psGgrmIufl9zAo8WOKgkLgbYbSHzkkDeqyjEPU+B0QSsZOCE+qLCHSdsnTmo/TjQhj0CgYAz1+j3yfGgrS+jVBC53lXi0+2fGspbf2jqKdDArXSvFqFzuudki/EpY6AND4NDYfB6hguzjD6PnoSGMUrVfAtR7X6LbwEZpqEX7eZGeMt1yQPMDr1bHrVi9mS5FMQR1NfuM1lP9Xzn00GIUpE7WVrWUhzDEBPJY/7YVLf0hFH08QKBgDWBRQZJIVBmkNrHktRrVddaSq4U/d/Q5LrsCrpymYwH8WliHgpeTQPWmKXwAd+ZJdXIzYjCt202N4eTeVqGYOb6Q/anV2WVYBbM4avpIxoA28kPGY6nML+8EyWIt2ApBOmgGgvtEreNzwaVU9NzjHEyv6n7FlVwlT1jxCe3XWq5AoGASYPKQoPeDlW+NmRG7z9EJXJRPVtmLL40fmGgtju9QIjLnjuK8XaczjAWT+ySI93Whu+Eujf2Uj7Q+NfUjvAEzJgwzuOd3jlQvoALq11kuaxlNQTn7rx0A1QhBgUJE8AkvShPC9FEnA4j/CLJU0re9H/8VvyN6qE0Mho0+YbjpP8=', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC1/GFud/7xutux7qRfMj1sIdMRh99/chR6HqVj6LQqrgk4jil0mdN/LCk/tqPqmDtObHdmEhCoybzuhLbCKgUqryKDwO6yBJHSKWY9QqrKZtLJ37SgKwGjE3+NUD4r1dJHhtQrICFdOdSCBzs/v8gi+J+KZLHo7+Nms4z09ysy7qZh94Pd7cW4gmSMergqUeANLD9C0ERw1NXolswOW7Bi7UGr7yuBxejICLO3nkxe0OtpQBrYrqdCD9vs3t/HQZbPWVoiRj4VO7fxkAPKLl30HzcIfxj/ayg8NHcH59d08D+N2v5Sdh28gsiYKIPE9CXvuw//HUY2WVRY5fDC5JglAgMBAAE=' -}] +function defaultConnectionInit (): any { + return { + timeline: { + open: Date.now() - 10, + upgraded: Date.now() + }, + direction: 'outbound', + encryption: '/secio/1.0.0', + multiplexer: '/mplex/6.7.0', + status: 'open', + newStream: Sinon.stub(), + close: Sinon.stub(), + abort: Sinon.stub(), + getStreams: Sinon.stub() + } +} describe('connection', () => { it('should not require local or remote addrs', async () => { - const remotePeer = await PeerIdFactory.createFromJSON(peers[1]) - - let openStreams: any[] = [] - let streamId = 0 + const remotePeer = await createEd25519PeerId() return createConnection({ remotePeer, remoteAddr: multiaddr('/ip4/127.0.0.1/tcp/4002'), - timeline: { - open: Date.now() - 10, - upgraded: Date.now() - }, - direction: 'outbound', - encryption: '/secio/1.0.0', - multiplexer: '/mplex/6.7.0', - status: 'open', - newStream: async (protocols) => { - const id = `${streamId++}` - const stream: Stream = { - ...pair(), - close: async () => { - await stream.sink(async function * () {}()) + ...defaultConnectionInit() + }) + }) - openStreams = openStreams.filter(s => s.id !== id) - }, - closeRead: async () => {}, - closeWrite: async () => { - await stream.sink(async function * () {}()) - }, - id, - abort: () => {}, - direction: 'outbound', - protocol: protocols[0], - timeline: { - open: 0 - }, - metadata: {}, - status: 'open', - writeStatus: 'ready', - readStatus: 'ready' - } + it('should append remote peer id to address if not already present', async () => { + const remotePeer = await createEd25519PeerId() - openStreams.push(stream) + const conn = createConnection({ + remotePeer, + remoteAddr: multiaddr('/ip4/127.0.0.1/tcp/4002'), + ...defaultConnectionInit() + }) - return stream - }, - close: async () => {}, - abort: () => {}, - getStreams: () => openStreams + expect(conn.remoteAddr.getPeerId()).to.equal(remotePeer.toString()) + }) + + it('should not append remote peer id to address if present', async () => { + const remotePeer = await createEd25519PeerId() + const otherPeer = await createEd25519PeerId() + + const conn = createConnection({ + remotePeer, + remoteAddr: multiaddr(`/ip4/127.0.0.1/tcp/4002/p2p/${otherPeer}`), + ...defaultConnectionInit() }) + + expect(conn.remoteAddr.getPeerId()).to.equal(otherPeer.toString()) }) }) diff --git a/packages/libp2p/test/dcutr/utils.spec.ts b/packages/libp2p/test/dcutr/utils.spec.ts new file mode 100644 index 0000000000..f5ed2b5fcb --- /dev/null +++ b/packages/libp2p/test/dcutr/utils.spec.ts @@ -0,0 +1,40 @@ +/* eslint-env mocha */ + +import { multiaddr } from '@multiformats/multiaddr' +import { expect } from 'aegir/chai' +import Sinon from 'sinon' +import { stubInterface } from 'sinon-ts' +import { isPublicAndDialable } from '../../src/dcutr/utils.js' +import type { Transport } from '@libp2p/interface/transport' +import type { TransportManager } from '@libp2p/interface-internal/transport-manager' + +describe('dcutr utils', () => { + describe('isPublicAndDialable', () => { + const testCases = { + // good addresses + '/ip4/123.123.123.123/tcp/80/p2p/12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa': true, + '/dnsaddr/example.com/p2p/12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa': true, + '/ip4/123.123.123.123/tcp/80/p2p/12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa/p2p-circuit/webrtc/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN': true, + + // bad addresses + '/dnsaddr/example.com/p2p/12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa/p2p-circuit/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN': false, + '/ip4/10.0.0.1/tcp/123/p2p/12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa': false + } + + for (const [key, value] of Object.entries(testCases)) { + it(`should ${value ? '' : 'not '}allow ${key}`, () => { + const transportManager = stubInterface({ + transportForMultiaddr: Sinon.stub().returns(stubInterface()) + }) + + expect(isPublicAndDialable(multiaddr(key), transportManager)).to.equal(value) + }) + } + + it('should not allow addresses for which there is no transport', () => { + const transportManager = stubInterface() + + expect(isPublicAndDialable(multiaddr('/ip4/123.123.123.123/p2p/12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa'), transportManager)).to.be.false() + }) + }) +}) diff --git a/packages/libp2p/test/fetch/index.spec.ts b/packages/libp2p/test/fetch/index.spec.ts index 9ef87c88e5..7b90a0f7db 100644 --- a/packages/libp2p/test/fetch/index.spec.ts +++ b/packages/libp2p/test/fetch/index.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -27,7 +27,7 @@ const defaultInit: FetchServiceInit = { async function createComponents (index: number): Promise { const peerId = await createEd25519PeerId() - const events = new EventEmitter() + const events = new TypedEventEmitter() const components = defaultComponents({ peerId, registrar: mockRegistrar(), diff --git a/packages/libp2p/test/identify/index.spec.ts b/packages/libp2p/test/identify/index.spec.ts index 46525769ba..4531641437 100644 --- a/packages/libp2p/test/identify/index.spec.ts +++ b/packages/libp2p/test/identify/index.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockConnectionGater, mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -51,7 +51,7 @@ const protocols = [MULTICODEC_IDENTIFY, MULTICODEC_IDENTIFY_PUSH] async function createComponents (index: number): Promise { const peerId = await createEd25519PeerId() - const events = new EventEmitter() + const events = new TypedEventEmitter() const components = defaultComponents({ peerId, datastore: new MemoryDatastore(), diff --git a/packages/libp2p/test/identify/push.spec.ts b/packages/libp2p/test/identify/push.spec.ts index 2916a8e1c4..a73bdc3655 100644 --- a/packages/libp2p/test/identify/push.spec.ts +++ b/packages/libp2p/test/identify/push.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockConnectionGater, mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -42,7 +42,7 @@ const protocols = [MULTICODEC_IDENTIFY, MULTICODEC_IDENTIFY_PUSH] async function createComponents (index: number): Promise { const peerId = await createEd25519PeerId() - const events = new EventEmitter() + const events = new TypedEventEmitter() const components = defaultComponents({ peerId, datastore: new MemoryDatastore(), diff --git a/packages/libp2p/test/identify/service.node.ts b/packages/libp2p/test/identify/service.node.ts index e7ce86b685..bae39bc2d6 100644 --- a/packages/libp2p/test/identify/service.node.ts +++ b/packages/libp2p/test/identify/service.node.ts @@ -65,13 +65,15 @@ describe('identify', () => { expect(connection).to.exist() // wait for identify to run on the new connection - await eventPromise + const identifyResult = await eventPromise + + // should have run on the new connection + expect(identifyResult).to.have.nested.property('detail.connection', connection) // assert we have received certified announce addresses - const peer = await libp2p.peerStore.get(remoteLibp2p.peerId) - expect(peer.addresses).to.have.lengthOf(1) - expect(peer.addresses[0].isCertified).to.be.true('did not receive certified address via identify') - expect(peer.addresses[0].multiaddr.toString()).to.startWith('/dns4/localhost/', 'did not receive announce address via identify') + expect(identifyResult).to.have.deep.nested.property('detail.signedPeerRecord.addresses', [ + multiaddr(`/dns4/localhost/tcp/${REMOTE_PORT}`) + ], 'did not receive announce address via identify') }) it('should run identify automatically for inbound connections', async () => { @@ -88,14 +90,16 @@ describe('identify', () => { const connection = await remoteLibp2p.dial(multiaddr(`/ip4/127.0.0.1/tcp/${LOCAL_PORT}/p2p/${libp2p.peerId.toString()}`)) expect(connection).to.exist() - // wait for identify to run on the new connection - await eventPromise + // wait for identify to run + const identifyResult = await eventPromise + + // should have run on the new connection + expect(identifyResult).to.have.nested.property('detail.connection', connection) // assert we have received certified announce addresses - const peer = await libp2p.peerStore.get(remoteLibp2p.peerId) - expect(peer.addresses).to.have.lengthOf(1) - expect(peer.addresses[0].isCertified).to.be.true('did not receive certified address via identify') - expect(peer.addresses[0].multiaddr.toString()).to.startWith('/dns4/localhost/', 'did not receive announce address via identify') + expect(identifyResult).to.have.deep.nested.property('detail.signedPeerRecord.addresses', [ + multiaddr(`/dns4/localhost/tcp/${LOCAL_PORT}`) + ], 'did not receive announce address via identify') }) it('should identify connection on dial and get proper announce addresses', async () => { diff --git a/packages/libp2p/test/interop.ts b/packages/libp2p/test/interop.ts index 871b47b3c9..5e34db58e6 100644 --- a/packages/libp2p/test/interop.ts +++ b/packages/libp2p/test/interop.ts @@ -129,7 +129,10 @@ async function createJsPeer (options: SpawnOptions): Promise { }, transports: [tcp(), circuitRelayTransport()], streamMuxers: [], - connectionEncryption: [noise()] + connectionEncryption: [noise()], + connectionManager: { + minConnections: 0 + } } const services: ServiceFactoryMap = { diff --git a/packages/libp2p/test/peer-discovery/index.node.ts b/packages/libp2p/test/peer-discovery/index.node.ts index 7adfb0c867..d3d6bd0939 100644 --- a/packages/libp2p/test/peer-discovery/index.node.ts +++ b/packages/libp2p/test/peer-discovery/index.node.ts @@ -2,7 +2,7 @@ import { bootstrap } from '@libp2p/bootstrap' import { randomBytes } from '@libp2p/crypto' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { kadDHT } from '@libp2p/kad-dht' import { mdns } from '@libp2p/mdns' @@ -22,7 +22,7 @@ import type { KadDHT } from '@libp2p/kad-dht' const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0') -class TestPeerDiscovery extends EventEmitter implements PeerDiscovery { +class TestPeerDiscovery extends TypedEventEmitter implements PeerDiscovery { get [peerDiscovery] (): PeerDiscovery { return this } diff --git a/packages/libp2p/test/ping/index.spec.ts b/packages/libp2p/test/ping/index.spec.ts index c37d5d0ebe..9b6aef1385 100644 --- a/packages/libp2p/test/ping/index.spec.ts +++ b/packages/libp2p/test/ping/index.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -28,7 +28,7 @@ const defaultInit: PingServiceInit = { async function createComponents (index: number): Promise { const peerId = await createEd25519PeerId() - const events = new EventEmitter() + const events = new TypedEventEmitter() const components = defaultComponents({ peerId, registrar: mockRegistrar(), diff --git a/packages/libp2p/test/registrar/registrar.spec.ts b/packages/libp2p/test/registrar/registrar.spec.ts index 0e5b585acf..302e773121 100644 --- a/packages/libp2p/test/registrar/registrar.spec.ts +++ b/packages/libp2p/test/registrar/registrar.spec.ts @@ -1,8 +1,7 @@ /* eslint-env mocha */ import { yamux } from '@chainsafe/libp2p-yamux' -import { CodeError } from '@libp2p/interface/errors' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { mockDuplex, mockMultiaddrConnection, mockUpgrader, mockConnection } from '@libp2p/interface-compliance-tests/mocks' import { mplex } from '@libp2p/mplex' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -14,7 +13,6 @@ import pDefer from 'p-defer' import { type StubbedInstance, stubInterface } from 'sinon-ts' import { type Components, defaultComponents } from '../../src/components.js' import { DefaultConnectionManager } from '../../src/connection-manager/index.js' -import { codes } from '../../src/errors.js' import { plaintext } from '../../src/insecure/index.js' import { createLibp2pNode, type Libp2pNode } from '../../src/libp2p.js' import { DefaultRegistrar } from '../../src/registrar.js' @@ -43,7 +41,7 @@ describe('registrar', () => { describe('errors', () => { beforeEach(() => { - const events = new EventEmitter() + const events = new TypedEventEmitter() components = defaultComponents({ peerId, events, @@ -81,13 +79,13 @@ describe('registrar', () => { let peerId: PeerId let connectionManager: StubbedInstance let peerStore: StubbedInstance - let events: EventEmitter + let events: TypedEventTarget beforeEach(async () => { peerId = await createEd25519PeerId() connectionManager = stubInterface() peerStore = stubInterface() - events = new EventEmitter() + events = new TypedEventEmitter() registrar = new DefaultRegistrar({ peerId, @@ -141,7 +139,7 @@ describe('registrar', () => { const conn = mockConnection(mockMultiaddrConnection(mockDuplex(), remotePeerId)) // return connection from connection manager - connectionManager.getConnections.withArgs(matchPeerId(remotePeerId)).returns([conn]) + connectionManager.getConnections.withArgs(remotePeerId).returns([conn]) const topology: Topology = { onConnect: (peerId, connection) => { @@ -170,8 +168,12 @@ describe('registrar', () => { }) // remote peer connects - events.safeDispatchEvent('peer:connect', { - detail: remotePeerId + events.safeDispatchEvent('peer:identify', { + detail: { + peerId: remotePeerId, + protocols: [protocol], + connection: conn + } }) await onConnectDefer.promise @@ -206,12 +208,13 @@ describe('registrar', () => { // Register protocol await registrar.register(protocol, topology) - // No details before identify - peerStore.get.withArgs(matchPeerId(conn.remotePeer)).rejects(new CodeError('Not found', codes.ERR_NOT_FOUND)) - // remote peer connects - events.safeDispatchEvent('peer:connect', { - detail: remotePeerId + events.safeDispatchEvent('peer:identify', { + detail: { + peerId: remotePeerId, + protocols: [protocol], + connection: conn + } }) // Can get details after identify @@ -261,6 +264,140 @@ describe('registrar', () => { await onDisconnectDefer.promise }) + it('should not call topology handlers for transient connection', async () => { + const onConnectDefer = pDefer() + const onDisconnectDefer = pDefer() + + // Setup connections before registrar + const remotePeerId = await createEd25519PeerId() + const conn = mockConnection(mockMultiaddrConnection(mockDuplex(), remotePeerId)) + + // connection is transient + conn.transient = true + + // return connection from connection manager + connectionManager.getConnections.withArgs(matchPeerId(remotePeerId)).returns([conn]) + + const topology: Topology = { + onConnect: () => { + onConnectDefer.reject(new Error('Topolgy onConnect called for transient connection')) + }, + onDisconnect: () => { + onDisconnectDefer.reject(new Error('Topolgy onDisconnect called for transient connection')) + } + } + + // Register topology for protocol + await registrar.register(protocol, topology) + + // remote peer connects + events.safeDispatchEvent('peer:identify', { + detail: { + peerId: remotePeerId, + protocols: [protocol], + connection: conn + } + }) + + await expect(Promise.any([ + onConnectDefer.promise, + onDisconnectDefer.promise, + new Promise((resolve) => { + setTimeout(() => { + resolve() + }, 1000) + }) + ])).to.eventually.not.be.rejected() + }) + + it('should call topology onConnect handler for transient connection when explicitly requested', async () => { + const onConnectDefer = pDefer() + + // Setup connections before registrar + const remotePeerId = await createEd25519PeerId() + const conn = mockConnection(mockMultiaddrConnection(mockDuplex(), remotePeerId)) + + // connection is transient + conn.transient = true + + // return connection from connection manager + connectionManager.getConnections.withArgs(matchPeerId(remotePeerId)).returns([conn]) + + const topology: Topology = { + notifyOnTransient: true, + onConnect: () => { + onConnectDefer.resolve() + } + } + + // Register topology for protocol + await registrar.register(protocol, topology) + + // remote peer connects + events.safeDispatchEvent('peer:identify', { + detail: { + peerId: remotePeerId, + protocols: [protocol], + connection: conn + } + }) + + await expect(onConnectDefer.promise).to.eventually.be.undefined() + }) + + it('should call topology handlers for non-transient connection opened after transient connection', async () => { + const onConnectDefer = pDefer() + let callCount = 0 + + const topology: Topology = { + notifyOnTransient: true, + onConnect: () => { + callCount++ + + if (callCount === 2) { + onConnectDefer.resolve() + } + } + } + + // Register topology for protocol + await registrar.register(protocol, topology) + + // Setup connections before registrar + const remotePeerId = await createEd25519PeerId() + const transientConnection = mockConnection(mockMultiaddrConnection(mockDuplex(), remotePeerId)) + transientConnection.transient = true + + const nonTransientConnection = mockConnection(mockMultiaddrConnection(mockDuplex(), remotePeerId)) + nonTransientConnection.transient = false + + // return connection from connection manager + connectionManager.getConnections.withArgs(matchPeerId(remotePeerId)).returns([ + transientConnection, + nonTransientConnection + ]) + + // remote peer connects over transient connection + events.safeDispatchEvent('peer:identify', { + detail: { + peerId: remotePeerId, + protocols: [protocol], + connection: transientConnection + } + }) + + // remote peer opens non-transient connection + events.safeDispatchEvent('peer:identify', { + detail: { + peerId: remotePeerId, + protocols: [protocol], + connection: nonTransientConnection + } + }) + + await expect(onConnectDefer.promise).to.eventually.be.undefined() + }) + it('should be able to register and unregister a handler', async () => { const deferred = pDefer() diff --git a/packages/libp2p/test/transports/transport-manager.node.ts b/packages/libp2p/test/transports/transport-manager.node.ts index 7404e88bbe..290414e618 100644 --- a/packages/libp2p/test/transports/transport-manager.node.ts +++ b/packages/libp2p/test/transports/transport-manager.node.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { FaultTolerance } from '@libp2p/interface/transport' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' @@ -33,7 +33,7 @@ describe('Transport Manager (TCP)', () => { }) beforeEach(async () => { - const events = new EventEmitter() + const events = new TypedEventEmitter() components = defaultComponents({ peerId: localPeer, events, diff --git a/packages/libp2p/test/transports/transport-manager.spec.ts b/packages/libp2p/test/transports/transport-manager.spec.ts index 89024dd8bc..c71a124a92 100644 --- a/packages/libp2p/test/transports/transport-manager.spec.ts +++ b/packages/libp2p/test/transports/transport-manager.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { FaultTolerance } from '@libp2p/interface/transport' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' @@ -26,7 +26,7 @@ describe('Transport Manager (WebSockets)', () => { let components: Components beforeEach(async () => { - const events = new EventEmitter() + const events = new TypedEventEmitter() components = { peerId: await createEd25519PeerId(), events, diff --git a/packages/libp2p/test/upgrading/upgrader.spec.ts b/packages/libp2p/test/upgrading/upgrader.spec.ts index f1343f128e..6f83c08ecd 100644 --- a/packages/libp2p/test/upgrading/upgrader.spec.ts +++ b/packages/libp2p/test/upgrading/upgrader.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ import { yamux } from '@chainsafe/libp2p-yamux' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockConnectionGater, mockConnectionManager, mockMultiaddrConnPair, mockRegistrar, mockStream, mockMuxer } from '@libp2p/interface-compliance-tests/mocks' import { mplex } from '@libp2p/mplex' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -76,7 +76,7 @@ describe('Upgrader', () => { registrar: mockRegistrar(), datastore: new MemoryDatastore(), connectionProtector: localConnectionProtector, - events: new EventEmitter() + events: new TypedEventEmitter() }) localComponents.peerStore = new PersistentPeerStore(localComponents) localComponents.connectionManager = mockConnectionManager(localComponents) @@ -103,7 +103,7 @@ describe('Upgrader', () => { registrar: mockRegistrar(), datastore: new MemoryDatastore(), connectionProtector: remoteConnectionProtector, - events: new EventEmitter() + events: new TypedEventEmitter() }) remoteComponents.peerStore = new PersistentPeerStore(remoteComponents) remoteComponents.connectionManager = mockConnectionManager(remoteComponents) diff --git a/packages/libp2p/test/upnp-nat/upnp-nat.node.ts b/packages/libp2p/test/upnp-nat/upnp-nat.node.ts index 42d6cc6407..8e39909147 100644 --- a/packages/libp2p/test/upnp-nat/upnp-nat.node.ts +++ b/packages/libp2p/test/upnp-nat/upnp-nat.node.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { FaultTolerance } from '@libp2p/interface/transport' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' @@ -31,7 +31,7 @@ describe('UPnP NAT (TCP)', () => { let client: StubbedInstance async function createNatManager (addrs = DEFAULT_ADDRESSES, natManagerOptions = {}): Promise<{ natManager: any, components: Components }> { - const events = new EventEmitter() + const events = new TypedEventEmitter() const components: any = defaultComponents({ peerId: await createEd25519PeerId(), upgrader: mockUpgrader({ events }), diff --git a/packages/logger/CHANGELOG.md b/packages/logger/CHANGELOG.md index fbe63635f4..6fe40ded69 100644 --- a/packages/logger/CHANGELOG.md +++ b/packages/logger/CHANGELOG.md @@ -5,6 +5,17 @@ * specify updated formatter for multiaddrs ([#36](https://github.com/libp2p/js-libp2p-logger/issues/36)) ([abaefb4](https://github.com/libp2p/js-libp2p-logger/commit/abaefb490a0d9464a23b422d9fc5b80051532d10)) +### [3.0.4](https://www.github.com/libp2p/js-libp2p/compare/logger-v3.0.3...logger-v3.0.4) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * devDependencies + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + ### [3.0.3](https://www.github.com/libp2p/js-libp2p/compare/logger-v3.0.2...logger-v3.0.3) (2023-10-06) diff --git a/packages/logger/README.md b/packages/logger/README.md index def89c67a1..ce77232376 100644 --- a/packages/logger/README.md +++ b/packages/logger/README.md @@ -1,5 +1,3 @@ -# @libp2p/logger - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,31 +5,7 @@ > A logging component for use in js-libp2p modules -## Table of contents - -- [Install](#install) - - [Browser ` -``` - -## Description +# About A map that reports it's size to the libp2p [Metrics](https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/metrics#readme) system. @@ -61,17 +35,31 @@ with this base58btc: Qmfoo with this base32: bafyfoo ``` -## API Docs +# Install + +```console +$ npm i @libp2p/logger +``` + +## Browser ` +``` + +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/logger/package.json b/packages/logger/package.json index 38babeb080..a7bca3d05f 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/logger", - "version": "3.0.3", + "version": "3.0.4", "description": "A logging component for use in js-libp2p modules", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/logger#readme", @@ -49,17 +49,17 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", + "@libp2p/interface": "^0.1.4", "@multiformats/multiaddr": "^12.1.5", "debug": "^4.3.4", "interface-datastore": "^8.2.0", "multiformats": "^12.0.1" }, "devDependencies": { - "@libp2p/peer-id": "^3.0.3", + "@libp2p/peer-id": "^3.0.4", "@types/debug": "^4.1.7", "aegir": "^41.0.2", - "sinon": "^16.0.0", + "sinon": "^17.0.0", "uint8arrays": "^4.0.4" } } diff --git a/packages/logger/src/index.ts b/packages/logger/src/index.ts index 87f1354d50..1bb24ea8dc 100644 --- a/packages/logger/src/index.ts +++ b/packages/logger/src/index.ts @@ -1,3 +1,34 @@ +/** + * @packageDocumentation + * + * A map that reports it's size to the libp2p [Metrics](https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/metrics#readme) system. + * + * If metrics are disabled a regular map is used. + * + * @example + * + * ```JavaScript + * import { logger } from '@libp2p/logger' + * + * const log = logger('libp2p:my:component:name') + * + * log('something happened: %s', 'it was ok') + * log.error('something bad happened: %o', err) + * + * log('with this peer: %p', aPeerId) + * log('and this base58btc: %b', aUint8Array) + * log('and this base32: %t', aUint8Array) + * ``` + * ```console + * $ DEBUG=libp2p:* node index.js + * something happened: it was ok + * something bad happened: + * with this peer: 12D3Foo + * with this base58btc: Qmfoo + * with this base32: bafyfoo + * ``` + */ + import debug from 'debug' import { base32 } from 'multiformats/bases/base32' import { base58btc } from 'multiformats/bases/base58' diff --git a/packages/metrics-prometheus/CHANGELOG.md b/packages/metrics-prometheus/CHANGELOG.md index f8ec58da18..d3bf87e9a2 100644 --- a/packages/metrics-prometheus/CHANGELOG.md +++ b/packages/metrics-prometheus/CHANGELOG.md @@ -5,6 +5,19 @@ * move prom-client to deps ([#32](https://github.com/libp2p/js-libp2p-prometheus-metrics/issues/32)) ([73acad0](https://github.com/libp2p/js-libp2p-prometheus-metrics/commit/73acad0a20a9a0ad024cd47a53f154668dbae77b)) +### [2.0.9](https://www.github.com/libp2p/js-libp2p/compare/prometheus-metrics-v2.0.8...prometheus-metrics-v2.0.9) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + ### [2.0.8](https://www.github.com/libp2p/js-libp2p/compare/prometheus-metrics-v2.0.7...prometheus-metrics-v2.0.8) (2023-10-06) diff --git a/packages/metrics-prometheus/README.md b/packages/metrics-prometheus/README.md index 6dadf9e4e2..42bb982e6f 100644 --- a/packages/metrics-prometheus/README.md +++ b/packages/metrics-prometheus/README.md @@ -1,5 +1,3 @@ -# @libp2p/prometheus-metrics - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,27 +5,7 @@ > Collect libp2p metrics for scraping by Prometheus or Graphana -## Table of contents - -- [Install](#install) -- [Usage](#usage) - - [Queries](#queries) - - [Data sent/received](#data-sentreceived) - - [CPU usage](#cpu-usage) - - [Memory usage](#memory-usage) - - [DHT query time](#dht-query-time) - - [TCP transport dialer errors](#tcp-transport-dialer-errors) -- [API Docs](#api-docs) -- [License](#license) -- [Contribution](#contribution) - -## Install - -```console -$ npm i @libp2p/prometheus-metrics -``` - -## Usage +# About Configure your libp2p node with Prometheus metrics: @@ -93,17 +71,112 @@ libp2p_kad_dht_lan_query_time_seconds rate(libp2p_tcp_dialer_errors_total[30s]) ``` -## API Docs +## Example + +```typescript +import { prometheusMetrics } from '@libp2p/prometheus-metrics' + +const metrics = prometheusMetrics()() +const myMetric = metrics.registerMetric({ + name: 'my_metric', + label: 'my_label', + help: 'my help text' +}) + +myMetric.update(1) +``` + +## Example + +A metric that is expensive to calculate can be created by passing a `calculate` function that will only be invoked when metrics are being scraped: + +```typescript +import { prometheusMetrics } from '@libp2p/prometheus-metrics' + +const metrics = prometheusMetrics()() +const myMetric = metrics.registerMetric({ + name: 'my_metric', + label: 'my_label', + help: 'my help text', + calculate: async () => { + // do something expensive + return 1 + } +}) +``` + +## Example + +If several metrics should be grouped together (e.g. for graphing purposes) `registerMetricGroup` can be used instead: + +```typescript +import { prometheusMetrics } from '@libp2p/prometheus-metrics' + +const metrics = prometheusMetrics()() +const myMetricGroup = metrics.registerMetricGroup({ + name: 'my_metric_group', + label: 'my_label', + help: 'my help text' +}) + +myMetricGroup.increment({ my_label: 'my_value' }) +``` + +There are specific metric groups for tracking libp2p connections and streams: + +## Example + +Track a newly opened multiaddr connection: + +```typescript +import { prometheusMetrics } from '@libp2p/prometheus-metrics' +import { createLibp2p } from 'libp2p' + +const metrics = prometheusMetrics()() + +const libp2p = await createLibp2p({ + metrics: metrics, + }) +// set up a multiaddr connection +const connection = await libp2p.dial('multiaddr') +const connections = metrics.trackMultiaddrConnection(connection) +``` + +## Example + +Track a newly opened stream: + +```typescript +import { prometheusMetrics } from '@libp2p/prometheus-metrics' +import { createLibp2p } from 'libp2p' + +const metrics = prometheusMetrics()() + +const libp2p = await createLibp2p({ + metrics: metrics, +}) + +const stream = await connection.newStream('/my/protocol') +const streams = metrics.trackProtocolStream(stream) +``` + +# Install + +```console +$ npm i @libp2p/prometheus-metrics +``` + +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/metrics-prometheus/package.json b/packages/metrics-prometheus/package.json index 87fd6acc4a..5e1d62f67b 100644 --- a/packages/metrics-prometheus/package.json +++ b/packages/metrics-prometheus/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/prometheus-metrics", - "version": "2.0.8", + "version": "2.0.9", "description": "Collect libp2p metrics for scraping by Prometheus or Graphana", "author": "", "license": "Apache-2.0 OR MIT", @@ -43,15 +43,15 @@ "test:electron-main": "aegir test -t electron-main --cov" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", "it-foreach": "^2.0.3", "it-stream-types": "^2.0.1", - "prom-client": "^14.2.0" + "prom-client": "^15.0.0" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^4.1.1", - "@libp2p/peer-id-factory": "^3.0.5", + "@libp2p/interface-compliance-tests": "^4.1.2", + "@libp2p/peer-id-factory": "^3.0.6", "@multiformats/multiaddr": "^12.1.3", "aegir": "^41.0.2", "it-drain": "^3.0.2", diff --git a/packages/metrics-prometheus/src/index.ts b/packages/metrics-prometheus/src/index.ts index 3e6accc57c..ebc0b83d2e 100644 --- a/packages/metrics-prometheus/src/index.ts +++ b/packages/metrics-prometheus/src/index.ts @@ -1,10 +1,69 @@ /** * @packageDocumentation * - * Collect libp2p metrics for scraping by Prometheus or Graphana. - * @module libp2p-prometheus-metrics + * Configure your libp2p node with Prometheus metrics: * - * A tracked metric can be created by calling either `registerMetric` on the metrics object + * ```js + * import { createLibp2p } from 'libp2p' + * import { prometheusMetrics } from '@libp2p/prometheus-metrics' + * + * const node = await createLibp2p({ + * metrics: prometheusMetrics() + * }) + * ``` + * + * Then use the `prom-client` module to supply metrics to the Prometheus/Graphana client using your http framework: + * + * ```js + * import client from 'prom-client' + * + * async handler (request, h) { + * return h.response(await client.register.metrics()) + * .type(client.register.contentType) + * } + * ``` + * + * All Prometheus metrics are global so there's no other work required to extract them. + * + * ### Queries + * + * Some useful queries are: + * + * #### Data sent/received + * + * ``` + * rate(libp2p_data_transfer_bytes_total[30s]) + * ``` + * + * #### CPU usage + * + * ``` + * rate(process_cpu_user_seconds_total[30s]) * 100 + * ``` + * + * #### Memory usage + * + * ``` + * nodejs_memory_usage_bytes + * ``` + * + * #### DHT query time + * + * ``` + * libp2p_kad_dht_wan_query_time_seconds + * ``` + * + * or + * + * ``` + * libp2p_kad_dht_lan_query_time_seconds + * ``` + * + * #### TCP transport dialer errors + * + * ``` + * rate(libp2p_tcp_dialer_errors_total[30s]) + * ``` * * @example * @@ -20,10 +79,11 @@ * * myMetric.update(1) * ``` - * A metric that is expensive to calculate can be created by passing a `calculate` function that will only be invoked when metrics are being scraped: * * @example * + * A metric that is expensive to calculate can be created by passing a `calculate` function that will only be invoked when metrics are being scraped: + * * ```typescript * import { prometheusMetrics } from '@libp2p/prometheus-metrics' * @@ -39,10 +99,10 @@ * }) * ``` * - * If several metrics should be grouped together (e.g. for graphing purposes) `registerMetricGroup` can be used instead: - * * @example * + * If several metrics should be grouped together (e.g. for graphing purposes) `registerMetricGroup` can be used instead: + * * ```typescript * import { prometheusMetrics } from '@libp2p/prometheus-metrics' * @@ -58,14 +118,14 @@ * * There are specific metric groups for tracking libp2p connections and streams: * - * Track a newly opened multiaddr connection: * @example * + * Track a newly opened multiaddr connection: + * * ```typescript * import { prometheusMetrics } from '@libp2p/prometheus-metrics' * import { createLibp2p } from 'libp2p' * - * * const metrics = prometheusMetrics()() * * const libp2p = await createLibp2p({ @@ -76,9 +136,10 @@ * const connections = metrics.trackMultiaddrConnection(connection) * ``` * - * Track a newly opened stream: * @example * + * Track a newly opened stream: + * * ```typescript * import { prometheusMetrics } from '@libp2p/prometheus-metrics' * import { createLibp2p } from 'libp2p' @@ -96,7 +157,7 @@ import { logger } from '@libp2p/logger' import each from 'it-foreach' -import { collectDefaultMetrics, type DefaultMetricsCollectorConfiguration, register, type Registry } from 'prom-client' +import { collectDefaultMetrics, type DefaultMetricsCollectorConfiguration, register, type Registry, type RegistryContentType } from 'prom-client' import { PrometheusCounterGroup } from './counter-group.js' import { PrometheusCounter } from './counter.js' import { PrometheusMetricGroup } from './metric-group.js' @@ -126,7 +187,7 @@ export interface PrometheusMetricsInit { /** * prom-client options to pass to the `collectDefaultMetrics` function */ - defaultMetrics?: DefaultMetricsCollectorConfiguration + defaultMetrics?: DefaultMetricsCollectorConfiguration /** * All metrics in prometheus are global so to prevent clashes in naming diff --git a/packages/multistream-select/CHANGELOG.md b/packages/multistream-select/CHANGELOG.md index b15826cbc0..27a09be593 100644 --- a/packages/multistream-select/CHANGELOG.md +++ b/packages/multistream-select/CHANGELOG.md @@ -11,6 +11,16 @@ * **dev:** bump aegir from 38.1.8 to 39.0.10 ([#70](https://github.com/libp2p/js-libp2p-multistream-select/issues/70)) ([f87b1c3](https://github.com/libp2p/js-libp2p-multistream-select/commit/f87b1c3505934ebeed6eff018af8d3042e7e6e06)) +### [4.0.4](https://www.github.com/libp2p/js-libp2p/compare/multistream-select-v4.0.3...multistream-select-v4.0.4) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + ### [4.0.3](https://www.github.com/libp2p/js-libp2p/compare/multistream-select-v4.0.2...multistream-select-v4.0.3) (2023-10-06) diff --git a/packages/multistream-select/README.md b/packages/multistream-select/README.md index ecb617ad0b..4412a86756 100644 --- a/packages/multistream-select/README.md +++ b/packages/multistream-select/README.md @@ -1,5 +1,3 @@ -# @libp2p/multistream-select - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,38 +5,11 @@ > JavaScript implementation of multistream-select -## Table of contents - -- [Install](#install) - - [Browser ` -``` - -## Background - -### What is `multistream-select`? +# About -TLDR; multistream-select is protocol multiplexing per connection/stream. [Full spec here](https://github.com/multiformats/multistream-select) +multistream-select is protocol multiplexing per connection/stream. [Full spec here](https://github.com/multiformats/multistream-select) -### Select a protocol flow +## Select a protocol flow The caller will send "interactive" messages, expecting for some acknowledgement from the callee, which will "select" the handler for the desired and supported protocol: @@ -54,17 +25,31 @@ The caller will send "interactive" messages, expecting for some acknowledgement > ``` -## API Docs +# Install + +```console +$ npm i @libp2p/multistream-select +``` + +## Browser ` +``` + +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/multistream-select/package.json b/packages/multistream-select/package.json index 0d095536ad..6671553658 100644 --- a/packages/multistream-select/package.json +++ b/packages/multistream-select/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/multistream-select", - "version": "4.0.3", + "version": "4.0.4", "description": "JavaScript implementation of multistream-select", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/multistream-select#readme", @@ -53,8 +53,8 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", "abortable-iterator": "^5.0.1", "it-first": "^3.0.1", "it-handshake": "^4.1.3", diff --git a/packages/multistream-select/src/index.ts b/packages/multistream-select/src/index.ts index efe37ef346..84968842b0 100644 --- a/packages/multistream-select/src/index.ts +++ b/packages/multistream-select/src/index.ts @@ -1,3 +1,25 @@ +/** + * @packageDocumentation + * + * multistream-select is protocol multiplexing per connection/stream. [Full spec here](https://github.com/multiformats/multistream-select) + * + * ## Select a protocol flow + * + * The caller will send "interactive" messages, expecting for some acknowledgement from the callee, which will "select" the handler for the desired and supported protocol: + * + * ``` + * < /multistream-select/0.3.0 # i speak multistream-select/0.3.0 + * > /multistream-select/0.3.0 # ok, let's speak multistream-select/0.3.0 + * > /ipfs-dht/0.2.3 # i want to speak ipfs-dht/0.2.3 + * < na # ipfs-dht/0.2.3 is not available + * > /ipfs-dht/0.1.9 # What about ipfs-dht/0.1.9 ? + * < /ipfs-dht/0.1.9 # ok let's speak ipfs-dht/0.1.9 -- in a sense acts as an ACK + * > + * > + * > + * ``` + */ + import { PROTOCOL_ID } from './constants.js' import type { AbortOptions } from '@libp2p/interface' import type { Duplex, Source } from 'it-stream-types' diff --git a/packages/peer-collections/CHANGELOG.md b/packages/peer-collections/CHANGELOG.md index 43cda9ddb9..59391d3e53 100644 --- a/packages/peer-collections/CHANGELOG.md +++ b/packages/peer-collections/CHANGELOG.md @@ -11,6 +11,18 @@ * **dev:** bump aegir from 38.1.8 to 39.0.10 ([#36](https://github.com/libp2p/js-libp2p-peer-collections/issues/36)) ([9fa3de6](https://github.com/libp2p/js-libp2p-peer-collections/commit/9fa3de6d85dbe1ade54fda86b597ed9ffe6d71d5)) +### [4.0.6](https://www.github.com/libp2p/js-libp2p/compare/peer-collections-v4.0.5...peer-collections-v4.0.6) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * devDependencies + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + ### [4.0.5](https://www.github.com/libp2p/js-libp2p/compare/peer-collections-v4.0.4...peer-collections-v4.0.5) (2023-10-06) diff --git a/packages/peer-collections/README.md b/packages/peer-collections/README.md index 9292ed7402..3112e317a7 100644 --- a/packages/peer-collections/README.md +++ b/packages/peer-collections/README.md @@ -1,5 +1,3 @@ -# @libp2p/peer-collections - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,22 +5,19 @@ > Stores values against a peer id -## Table of contents +# About -- [Install](#install) - - [Browser ` ``` -## Description - -We can't use PeerIds as collection keys because collection keys are compared using same-value-zero equality, so this is just a group of collections that stringifies PeerIds before storing them. - -PeerIds cache stringified versions of themselves so this should be a cheap operation. - -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/peer-collections/package.json b/packages/peer-collections/package.json index 615fd30416..f799605a16 100644 --- a/packages/peer-collections/package.json +++ b/packages/peer-collections/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/peer-collections", - "version": "4.0.5", + "version": "4.0.6", "description": "Stores values against a peer id", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/peer-collections#readme", @@ -49,11 +49,11 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/peer-id": "^3.0.3" + "@libp2p/interface": "^0.1.4", + "@libp2p/peer-id": "^3.0.4" }, "devDependencies": { - "@libp2p/peer-id-factory": "^3.0.5", + "@libp2p/peer-id-factory": "^3.0.6", "aegir": "^41.0.2" } } diff --git a/packages/peer-collections/src/index.ts b/packages/peer-collections/src/index.ts index db2767e619..39bd9479d3 100644 --- a/packages/peer-collections/src/index.ts +++ b/packages/peer-collections/src/index.ts @@ -1,3 +1,11 @@ +/** + * @packageDocumentation + * + * We can't use PeerIds as collection keys because collection keys are compared using same-value-zero equality, so this is just a group of collections that stringifies PeerIds before storing them. + * + * PeerIds cache stringified versions of themselves so this should be a cheap operation. + */ + export { PeerMap } from './map.js' export { PeerSet } from './set.js' export { PeerList } from './list.js' diff --git a/packages/peer-discovery-bootstrap/CHANGELOG.md b/packages/peer-discovery-bootstrap/CHANGELOG.md index b2a127a3ef..8f408ea357 100644 --- a/packages/peer-discovery-bootstrap/CHANGELOG.md +++ b/packages/peer-discovery-bootstrap/CHANGELOG.md @@ -9,6 +9,25 @@ * update @libp2p/interface-peer-discovery to 2.0.0 ([#176](https://github.com/libp2p/js-libp2p-bootstrap/issues/176)) ([1954e75](https://github.com/libp2p/js-libp2p-bootstrap/commit/1954e75fa4b1e6b3b42f885f663f989fd0e422ab)) +### [9.0.9](https://www.github.com/libp2p/js-libp2p/compare/bootstrap-v9.0.8...bootstrap-v9.0.9) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + ### [9.0.8](https://www.github.com/libp2p/js-libp2p/compare/bootstrap-v9.0.7...bootstrap-v9.0.8) (2023-10-06) @@ -591,4 +610,4 @@ Co-authored-by: Alan Shaw -## [0.4.2](https://github.com/libp2p/js-ipfs-railing/compare/v0.4.1...v0.4.2) (2017-03-21) +## [0.4.2](https://github.com/libp2p/js-ipfs-railing/compare/v0.4.1...v0.4.2) (2017-03-21) \ No newline at end of file diff --git a/packages/peer-discovery-bootstrap/README.md b/packages/peer-discovery-bootstrap/README.md index c48965d55c..9176c04857 100644 --- a/packages/peer-discovery-bootstrap/README.md +++ b/packages/peer-discovery-bootstrap/README.md @@ -1,5 +1,3 @@ -# @libp2p/bootstrap - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,37 +5,11 @@ > Peer discovery via a list of bootstrap peers -## Table of contents - -- [Install](#install) - - [Browser ` -``` +The configured bootstrap peers will be discovered after the configured timeout. This will ensure there are some peers in the peer store for the node to use to discover other peers. -## Usage - -The configured bootstrap peers will be discovered after the configured timeout. This will ensure -there are some peers in the peer store for the node to use to discover other peers. - -They will be tagged with a tag with the name `'bootstrap'` tag, the value `50` and it will expire -after two minutes which means the nodes connections may be closed if the maximum number of -connections is reached. +They will be tagged with a tag with the name `'bootstrap'` tag, the value `50` and it will expire after two minutes which means the nodes connections may be closed if the maximum number of connections is reached. Clients that need constant connections to bootstrap nodes (e.g. browsers) can set the TTL to `Infinity`. @@ -73,31 +45,38 @@ let options = { ] } -async function start () { - let libp2p = await createLibp2p(options) +const libp2p = await createLibp2p(options) - libp2p.on('peer:discovery', function (peerId) { - console.log('found peer: ', peerId.toB58String()) - }) +libp2p.on('peer:discovery', function (peerId) { + console.log('found peer: ', peerId.toB58String()) +}) +``` - await libp2p.start() +# Install -} +```console +$ npm i @libp2p/bootstrap +``` + +## Browser ` ``` -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/peer-discovery-bootstrap/package.json b/packages/peer-discovery-bootstrap/package.json index 7961f87940..b41498deb6 100644 --- a/packages/peer-discovery-bootstrap/package.json +++ b/packages/peer-discovery-bootstrap/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/bootstrap", - "version": "9.0.8", + "version": "9.0.9", "description": "Peer discovery via a list of bootstrap peers", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/peer-discovery-bootstrap#readme", @@ -49,15 +49,15 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", - "@libp2p/peer-id": "^3.0.3", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", + "@libp2p/peer-id": "^3.0.4", "@multiformats/mafmt": "^12.1.2", "@multiformats/multiaddr": "^12.1.5" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^4.1.1", + "@libp2p/interface-compliance-tests": "^4.1.2", "aegir": "^41.0.2", - "sinon-ts": "^1.0.0" + "sinon-ts": "^2.0.0" } } diff --git a/packages/peer-discovery-bootstrap/src/index.ts b/packages/peer-discovery-bootstrap/src/index.ts index 1debb10fc6..999b14f5e0 100644 --- a/packages/peer-discovery-bootstrap/src/index.ts +++ b/packages/peer-discovery-bootstrap/src/index.ts @@ -1,4 +1,53 @@ -import { EventEmitter } from '@libp2p/interface/events' +/** + * @packageDocumentation + * + * The configured bootstrap peers will be discovered after the configured timeout. This will ensure there are some peers in the peer store for the node to use to discover other peers. + * + * They will be tagged with a tag with the name `'bootstrap'` tag, the value `50` and it will expire after two minutes which means the nodes connections may be closed if the maximum number of connections is reached. + * + * Clients that need constant connections to bootstrap nodes (e.g. browsers) can set the TTL to `Infinity`. + * + * ```JavaScript + * import { createLibp2p } from 'libp2p' + * import { bootstrap } from '@libp2p/bootstrap' + * import { tcp } from 'libp2p/tcp' + * import { noise } from '@libp2p/noise' + * import { mplex } from '@libp2p/mplex' + * + * let options = { + * transports: [ + * tcp() + * ], + * streamMuxers: [ + * mplex() + * ], + * connectionEncryption: [ + * noise() + * ], + * peerDiscovery: [ + * bootstrap({ + * list: [ // a list of bootstrap peer multiaddrs to connect to on node startup + * "/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", + * "/dnsaddr/bootstrap.libp2p.io/ipfs/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN", + * "/dnsaddr/bootstrap.libp2p.io/ipfs/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa" + * ], + * timeout: 1000, // in ms, + * tagName: 'bootstrap', + * tagValue: 50, + * tagTTL: 120000 // in ms + * }) + * ] + * } + * + * const libp2p = await createLibp2p(options) + * + * libp2p.on('peer:discovery', function (peerId) { + * console.log('found peer: ', peerId.toB58String()) + * }) + * ``` + */ + +import { TypedEventEmitter } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { logger } from '@libp2p/logger' import { peerIdFromString } from '@libp2p/peer-id' @@ -50,7 +99,7 @@ export interface BootstrapComponents { /** * Emits 'peer' events on a regular interval for each peer in the provided list. */ -class Bootstrap extends EventEmitter implements PeerDiscovery, Startable { +class Bootstrap extends TypedEventEmitter implements PeerDiscovery, Startable { static tag = 'bootstrap' private timer?: ReturnType diff --git a/packages/peer-discovery-mdns/CHANGELOG.md b/packages/peer-discovery-mdns/CHANGELOG.md index 3eb7ebe38b..f13ffb2473 100644 --- a/packages/peer-discovery-mdns/CHANGELOG.md +++ b/packages/peer-discovery-mdns/CHANGELOG.md @@ -9,6 +9,28 @@ * update @libp2p/interface-peer-discovery to 2.0.0 ([#197](https://github.com/libp2p/js-libp2p-mdns/issues/197)) ([e8172af](https://github.com/libp2p/js-libp2p-mdns/commit/e8172af8b9856a934327195238b00e5fbba436a4)) +### [9.0.11](https://www.github.com/libp2p/js-libp2p/compare/mdns-v9.0.10...mdns-v9.0.11) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * @libp2p/utils bumped from ^4.0.4 to ^4.0.5 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + * @libp2p/interface-internal bumped from ^0.1.6 to ^0.1.7 + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + ### [9.0.10](https://www.github.com/libp2p/js-libp2p/compare/mdns-v9.0.9...mdns-v9.0.10) (2023-10-06) @@ -645,4 +667,4 @@ Co-authored-by: Jacob Heun -## [0.6.2](https://github.com/libp2p/js-libp2p-mdns/compare/v0.6.1...v0.6.2) (2017-03-21) +## [0.6.2](https://github.com/libp2p/js-libp2p-mdns/compare/v0.6.1...v0.6.2) (2017-03-21) \ No newline at end of file diff --git a/packages/peer-discovery-mdns/README.md b/packages/peer-discovery-mdns/README.md index be587d8220..11ebefd4f3 100644 --- a/packages/peer-discovery-mdns/README.md +++ b/packages/peer-discovery-mdns/README.md @@ -1,5 +1,3 @@ -# @libp2p/mdns - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,24 +5,13 @@ > Node.js libp2p mDNS discovery implementation for peer discovery -## Table of contents +# About -- [Install](#install) -- [Usage](#usage) -- [MDNS messages](#mdns-messages) -- [API Docs](#api-docs) -- [License](#license) -- [Contribution](#contribution) +A peer discover mechanism that uses [mDNS](https://datatracker.ietf.org/doc/html/rfc6762) to discover peers on the local network. -## Install +## Example -```console -$ npm i @libp2p/mdns -``` - -## Usage - -```Typescript +```ts import { mdns } from '@libp2p/mdns' const options = { @@ -33,81 +20,84 @@ const options = { ] } -async function start () { - const libp2p = await createLibp2p(options) - - libp2p.on('peer:discovery', function (peerId) { - console.log('found peer: ', peerId.toB58String()) - }) +const libp2p = await createLibp2p(options) - await libp2p.start() -} +libp2p.on('peer:discovery', function (peerId) { + console.log('found peer: ', peerId.toB58String()) +}) +await libp2p.start() ``` -- options - - `peerName` - Peer name to announce (should not be peeer id), default random string - - `multiaddrs` - multiaddrs to announce - - `broadcast` - (true/false) announce our presence through mDNS, default `true` - - `interval` - query interval, default 10 \* 1000 (10 seconds) - - `serviceTag` - name of the service announce , default '_p2p._udp.local\` - ## MDNS messages A query is sent to discover the libp2p nodes on the local network ```js { - type: 'query', - questions: [ { name: '_p2p._udp.local', type: 'PTR' } ] + type: 'query', + questions: [ { name: '_p2p._udp.local', type: 'PTR' } ] } ``` When a query is detected, each libp2p node sends an answer about itself ```js - [ { name: '_p2p._udp.local', - type: 'PTR', - class: 'IN', - ttl: 120, - data: 'QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK._p2p._udp.local' }, - { name: 'QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK._p2p._udp.local', - type: 'SRV', - class: 'IN', - ttl: 120, - data: - { priority: 10, - weight: 1, - port: '20002', - target: 'LAPTOP-G5LJ7VN9' } }, - { name: 'QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK._p2p._udp.local', - type: 'TXT', - class: 'IN', - ttl: 120, - data: ['QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK'] }, - { name: 'LAPTOP-G5LJ7VN9', - type: 'A', - class: 'IN', - ttl: 120, - data: '127.0.0.1' }, - { name: 'LAPTOP-G5LJ7VN9', - type: 'AAAA', - class: 'IN', - ttl: 120, - data: '::1' } ] +[{ + name: '_p2p._udp.local', + type: 'PTR', + class: 'IN', + ttl: 120, + data: 'QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK._p2p._udp.local' +}, { + name: 'QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK._p2p._udp.local', + type: 'SRV', + class: 'IN', + ttl: 120, + data: { + priority: 10, + weight: 1, + port: '20002', + target: 'LAPTOP-G5LJ7VN9' + } +}, { + name: 'QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK._p2p._udp.local', + type: 'TXT', + class: 'IN', + ttl: 120, + data: ['QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK'] +}, { + name: 'LAPTOP-G5LJ7VN9', + type: 'A', + class: 'IN', + ttl: 120, + data: '127.0.0.1' +}, { + name: 'LAPTOP-G5LJ7VN9', + type: 'AAAA', + class: 'IN', + ttl: 120, + data: '::1' +}] +``` + +# Install + +```console +$ npm i @libp2p/mdns ``` -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/peer-discovery-mdns/package.json b/packages/peer-discovery-mdns/package.json index f362c70f69..2d618de54f 100644 --- a/packages/peer-discovery-mdns/package.json +++ b/packages/peer-discovery-mdns/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/mdns", - "version": "9.0.10", + "version": "9.0.11", "description": "Node.js libp2p mDNS discovery implementation for peer discovery", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/peer-discovery-mdns#readme", @@ -45,19 +45,19 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", - "@libp2p/peer-id": "^3.0.3", - "@libp2p/utils": "^4.0.4", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", + "@libp2p/peer-id": "^3.0.4", + "@libp2p/utils": "^4.0.5", "@multiformats/multiaddr": "^12.1.5", "@types/multicast-dns": "^7.2.1", "dns-packet": "^5.4.0", "multicast-dns": "^7.2.5" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^4.1.1", - "@libp2p/interface-internal": "^0.1.6", - "@libp2p/peer-id-factory": "^3.0.5", + "@libp2p/interface-compliance-tests": "^4.1.2", + "@libp2p/interface-internal": "^0.1.7", + "@libp2p/peer-id-factory": "^3.0.6", "aegir": "^41.0.2", "p-wait-for": "^5.0.2", "ts-sinon": "^2.0.2" diff --git a/packages/peer-discovery-mdns/src/index.ts b/packages/peer-discovery-mdns/src/index.ts index 7424131c06..ed37439b57 100644 --- a/packages/peer-discovery-mdns/src/index.ts +++ b/packages/peer-discovery-mdns/src/index.ts @@ -1,4 +1,82 @@ -import { CustomEvent, EventEmitter } from '@libp2p/interface/events' +/** + * @packageDocumentation + * + * A peer discover mechanism that uses [mDNS](https://datatracker.ietf.org/doc/html/rfc6762) to discover peers on the local network. + * + * @example + * + * ```ts + * import { mdns } from '@libp2p/mdns' + * + * const options = { + * peerDiscovery: [ + * mdns() + * ] + * } + * + * const libp2p = await createLibp2p(options) + * + * libp2p.on('peer:discovery', function (peerId) { + * console.log('found peer: ', peerId.toB58String()) + * }) + * + * await libp2p.start() + * ``` + * + * ## MDNS messages + * + * A query is sent to discover the libp2p nodes on the local network + * + * ```js + * { + * type: 'query', + * questions: [ { name: '_p2p._udp.local', type: 'PTR' } ] + * } + * ``` + * + * When a query is detected, each libp2p node sends an answer about itself + * + * ```js + * [{ + * name: '_p2p._udp.local', + * type: 'PTR', + * class: 'IN', + * ttl: 120, + * data: 'QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK._p2p._udp.local' + * }, { + * name: 'QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK._p2p._udp.local', + * type: 'SRV', + * class: 'IN', + * ttl: 120, + * data: { + * priority: 10, + * weight: 1, + * port: '20002', + * target: 'LAPTOP-G5LJ7VN9' + * } + * }, { + * name: 'QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK._p2p._udp.local', + * type: 'TXT', + * class: 'IN', + * ttl: 120, + * data: ['QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK'] + * }, { + * name: 'LAPTOP-G5LJ7VN9', + * type: 'A', + * class: 'IN', + * ttl: 120, + * data: '127.0.0.1' + * }, { + * name: 'LAPTOP-G5LJ7VN9', + * type: 'AAAA', + * class: 'IN', + * ttl: 120, + * data: '::1' + * }] + * ``` + */ + +import { CustomEvent, TypedEventEmitter } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { logger } from '@libp2p/logger' import multicastDNS from 'multicast-dns' @@ -12,11 +90,33 @@ import type { AddressManager } from '@libp2p/interface-internal/address-manager' const log = logger('libp2p:mdns') export interface MulticastDNSInit { + /** + * (true/false) announce our presence through mDNS, default `true` + */ broadcast?: boolean + + /** + * query interval, default 10 \* 1000 (10 seconds) + */ interval?: number + + /** + * name of the service announce , default '_p2p._udp.local\` + */ serviceTag?: string + /** + * Peer name to announce (should not be peeer id), default random string + */ peerName?: string + + /** + * UDP port to broadcast to + */ port?: number + + /** + * UDP IP to broadcast to + */ ip?: string } @@ -24,7 +124,7 @@ export interface MulticastDNSComponents { addressManager: AddressManager } -class MulticastDNS extends EventEmitter implements PeerDiscovery, Startable { +class MulticastDNS extends TypedEventEmitter implements PeerDiscovery, Startable { public mdns?: multicastDNS.MulticastDNS private readonly broadcast: boolean diff --git a/packages/peer-id-factory/CHANGELOG.md b/packages/peer-id-factory/CHANGELOG.md index dba517b519..491b844b2f 100644 --- a/packages/peer-id-factory/CHANGELOG.md +++ b/packages/peer-id-factory/CHANGELOG.md @@ -5,6 +5,17 @@ * update README.md ([#59](https://github.com/libp2p/js-libp2p-peer-id/issues/59)) ([aba6483](https://github.com/libp2p/js-libp2p-peer-id/commit/aba6483dad028ee5c24bfc01135b77568666cfd3)) +### [3.0.6](https://www.github.com/libp2p/js-libp2p/compare/peer-id-factory-v3.0.5...peer-id-factory-v3.0.6) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^2.0.5 to ^2.0.6 + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + ### [3.0.5](https://www.github.com/libp2p/js-libp2p/compare/peer-id-factory-v3.0.4...peer-id-factory-v3.0.5) (2023-10-06) diff --git a/packages/peer-id-factory/README.md b/packages/peer-id-factory/README.md index 7c353cd96b..b430276ed2 100644 --- a/packages/peer-id-factory/README.md +++ b/packages/peer-id-factory/README.md @@ -1,5 +1,3 @@ -# @libp2p/peer-id-factory - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,31 +5,7 @@ > Create PeerId instances -## Table of contents - -- [Install](#install) - - [Browser ` -``` - -## Description +# About Generate, import, and export PeerIDs, for use with [IPFS](https://github.com/ipfs/ipfs). @@ -52,17 +26,31 @@ console.log(id.toString()) 12D3KooWRm8J3iL796zPFi2EtGGtUJn58AG67gcqzMFHZnnsTzqD ``` -## API Docs +# Install + +```console +$ npm i @libp2p/peer-id-factory +``` + +## Browser ` +``` + +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/peer-id-factory/package.json b/packages/peer-id-factory/package.json index d2ca5bdb2f..6b4416994c 100644 --- a/packages/peer-id-factory/package.json +++ b/packages/peer-id-factory/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/peer-id-factory", - "version": "3.0.5", + "version": "3.0.6", "description": "Create PeerId instances", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/peer-id-factory#readme", @@ -53,9 +53,9 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/crypto": "^2.0.5", - "@libp2p/interface": "^0.1.3", - "@libp2p/peer-id": "^3.0.3", + "@libp2p/crypto": "^2.0.6", + "@libp2p/interface": "^0.1.4", + "@libp2p/peer-id": "^3.0.4", "multiformats": "^12.0.1", "protons-runtime": "^5.0.0", "uint8arraylist": "^2.4.3", diff --git a/packages/peer-id-factory/src/index.ts b/packages/peer-id-factory/src/index.ts index 626f01eec3..f40646befe 100644 --- a/packages/peer-id-factory/src/index.ts +++ b/packages/peer-id-factory/src/index.ts @@ -1,3 +1,26 @@ +/** + * @packageDocumentation + * + * Generate, import, and export PeerIDs, for use with [IPFS](https://github.com/ipfs/ipfs). + * + * A Peer ID is the SHA-256 [multihash](https://github.com/multiformats/multihash) of a public key. + * + * The public key is a base64 encoded string of a protobuf containing an RSA DER buffer. This uses a node buffer to pass the base64 encoded public key protobuf to the multihash for ID generation. + * + * @example + * + * ```JavaScript + * import { createEd25519PeerId } from '@libp2p/peer-id-factory' + * + * const peerId = await createEd25519PeerId() + * console.log(id.toString()) + * ``` + * + * ```bash + * 12D3KooWRm8J3iL796zPFi2EtGGtUJn58AG67gcqzMFHZnnsTzqD + * ``` + */ + import { generateKeyPair, marshalPrivateKey, unmarshalPrivateKey, marshalPublicKey, unmarshalPublicKey } from '@libp2p/crypto/keys' import { peerIdFromKeys, peerIdFromBytes } from '@libp2p/peer-id' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' diff --git a/packages/peer-id/CHANGELOG.md b/packages/peer-id/CHANGELOG.md index 986cefe7ae..3bf6b46c8a 100644 --- a/packages/peer-id/CHANGELOG.md +++ b/packages/peer-id/CHANGELOG.md @@ -5,6 +5,15 @@ * update README.md ([#59](https://github.com/libp2p/js-libp2p-peer-id/issues/59)) ([aba6483](https://github.com/libp2p/js-libp2p-peer-id/commit/aba6483dad028ee5c24bfc01135b77568666cfd3)) +### [3.0.4](https://www.github.com/libp2p/js-libp2p/compare/peer-id-v3.0.3...peer-id-v3.0.4) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + ### [3.0.3](https://www.github.com/libp2p/js-libp2p/compare/peer-id-v3.0.2...peer-id-v3.0.3) (2023-10-06) diff --git a/packages/peer-id/README.md b/packages/peer-id/README.md index 7c2c8c23bc..aafa9396d7 100644 --- a/packages/peer-id/README.md +++ b/packages/peer-id/README.md @@ -1,29 +1,15 @@ -# @libp2p/peer-id - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) [![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) -> Implementation of @libp2p/interface-peer-id - -## Table of contents - -- [Install](#install) - - [Browser ` ``` -## Description - -A basic implementation of a peer id - -## Example - -```JavaScript -import { peerIdFromString } from '@libp2p/peer-id' - -const peer = peerIdFromString('k51qzi5uqu5dkwkqm42v9j9kqcam2jiuvloi16g72i4i4amoo2m8u3ol3mqu6s') - -console.log(peer.toCid()) // CID(bafzaa...) -console.log(peer.toString()) // "12D3K..." -``` - -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/peer-id/package.json b/packages/peer-id/package.json index bb910d9888..bc2fa6aea1 100644 --- a/packages/peer-id/package.json +++ b/packages/peer-id/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/peer-id", - "version": "3.0.3", + "version": "3.0.4", "description": "Implementation of @libp2p/interface-peer-id", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/peer-id#readme", @@ -49,7 +49,7 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", + "@libp2p/interface": "^0.1.4", "multiformats": "^12.0.1", "uint8arrays": "^4.0.6" }, diff --git a/packages/peer-id/src/index.ts b/packages/peer-id/src/index.ts index b1dfd2fabe..db722aa171 100644 --- a/packages/peer-id/src/index.ts +++ b/packages/peer-id/src/index.ts @@ -1,3 +1,19 @@ +/** + * @packageDocumentation + * + * An implementation of a peer id + * + * @example + * + * ```JavaScript + * import { peerIdFromString } from '@libp2p/peer-id' + * const peer = peerIdFromString('k51qzi5uqu5dkwkqm42v9j9kqcam2jiuvloi16g72i4i4amoo2m8u3ol3mqu6s') + * + * console.log(peer.toCid()) // CID(bafzaa...) + * console.log(peer.toString()) // "12D3K..." + * ``` + */ + import { CodeError } from '@libp2p/interface/errors' import { type Ed25519PeerId, type PeerIdType, type RSAPeerId, type Secp256k1PeerId, symbol, type PeerId } from '@libp2p/interface/peer-id' import { base58btc } from 'multiformats/bases/base58' diff --git a/packages/peer-record/CHANGELOG.md b/packages/peer-record/CHANGELOG.md index 69281e709b..cd7020862b 100644 --- a/packages/peer-record/CHANGELOG.md +++ b/packages/peer-record/CHANGELOG.md @@ -11,6 +11,20 @@ * **dev:** bump aegir from 38.1.8 to 39.0.10 ([#64](https://github.com/libp2p/js-libp2p-peer-record/issues/64)) ([ba3ac38](https://github.com/libp2p/js-libp2p-peer-record/commit/ba3ac38c79e9449a75c0a54fefe289ee9e2c78fb)) +### [6.0.7](https://www.github.com/libp2p/js-libp2p/compare/peer-record-v6.0.6...peer-record-v6.0.7) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^2.0.5 to ^2.0.6 + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * @libp2p/utils bumped from ^4.0.4 to ^4.0.5 + * devDependencies + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + ### [6.0.6](https://www.github.com/libp2p/js-libp2p/compare/peer-record-v6.0.5...peer-record-v6.0.6) (2023-10-06) diff --git a/packages/peer-record/README.md b/packages/peer-record/README.md index 358efe226b..ae3adc5144 100644 --- a/packages/peer-record/README.md +++ b/packages/peer-record/README.md @@ -1,5 +1,3 @@ -# @libp2p/peer-record - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,44 +5,11 @@ > Used to transfer signed peer data across the network -## Table of contents - -- [Install](#install) - - [Browser ` -``` - -## Description +# About Libp2p nodes need to store data in a public location (e.g. a DHT), or rely on potentially untrustworthy intermediaries to relay information over its lifetime. Accordingly, libp2p nodes need to be able to verify that the data came from a specific peer and that it hasn't been tampered with. -### Envelope +## Envelope Libp2p provides an all-purpose data container called **envelope**. It was created to enable the distribution of verifiable records, which we can prove originated from the addressed peer itself. The envelope includes a signature of the data, so that its authenticity is verified. @@ -52,9 +17,9 @@ This envelope stores a marshaled record implementing the [interface-record](http You can read further about the envelope in [libp2p/specs#217](https://github.com/libp2p/specs/pull/217). -## Usage +## Example -- create an envelope with an instance of an [interface-record](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/record) implementation and prepare it for being exchanged: +Create an envelope with an instance of an [interface-record](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/record) implementation and prepare it for being exchanged: ```js // interface-record implementation example with the "libp2p-example" namespace @@ -83,7 +48,9 @@ const e = await PeerEnvelope.seal(rec, peerId) const wireData = e.marshal() ``` -- consume a received envelope (`wireData`) and transform it back to a record: +## Example + +Consume a received envelope (`wireData`) and transform it back to a record: ```js import { PeerEnvelope } from '@libp2p/peer-record' @@ -109,9 +76,9 @@ A peer record contains the peers' publicly reachable listen addresses, and may b You can read further about the Peer Record in [libp2p/specs#217](https://github.com/libp2p/specs/pull/217). -### Usage +## Example -- create a new Peer Record +Create a new Peer Record ```js import { PeerRecord } from '@libp2p/peer-record' @@ -122,7 +89,9 @@ const pr = new PeerRecord({ }) ``` -- create a Peer Record from a protobuf +## Example + +Create a Peer Record from a protobuf ```js import { PeerRecord } from '@libp2p/peer-record' @@ -130,23 +99,21 @@ import { PeerRecord } from '@libp2p/peer-record' const pr = PeerRecord.createFromProtobuf(data) ``` -### Libp2p Flows +## Libp2p Flows -#### Self Record +### Self Record Once a libp2p node has started and is listening on a set of multiaddrs, its own peer record can be created. The identify service is responsible for creating the self record when the identify protocol kicks in for the first time. This record will be stored for future needs of the identify protocol when connecting with other peers. -#### Self record Updates - -***NOT\_YET\_IMPLEMENTED*** +### Self record Updates While creating peer records is fairly trivial, addresses are not static and might be modified at arbitrary times. This can happen via an Address Manager API, or even through AutoRelay/AutoNAT. When a libp2p node changes its listen addresses, the identify service will be informed. Once that happens, the identify service creates a new self record and stores it. With the new record, the identify push/delta protocol will be used to communicate this change to the connected peers. -#### Subsystem receiving a record +### Subsystem receiving a record Considering that a node can discover other peers' addresses from a variety of sources, Libp2p Peerstore can differentiate the addresses that were obtained through a signed peer record. @@ -154,34 +121,48 @@ Once a record is received and its signature properly validated, its envelope is The AddressBook Addresses will be updated with the content of the envelope with a certified property. This allows other subsystems to identify the known certified addresses of a peer. -#### Subsystem providing a record +### Subsystem providing a record Libp2p subsystems that exchange other peers information will provide the envelope that they received by those peers. As a result, other peers can verify if the envelope was really created by the addressed peer. When a subsystem wants to provide a record, it will get it from the AddressBook, if it exists. Other subsystems are also able to provide the self record, since it is also stored in the AddressBook. -### Future Work +## Future Work - Persistence only considering certified addresses? - Peers may not know their own addresses. It's often impossible to automatically infer one's own public address, and peers may need to rely on third party peers to inform them of their observed public addresses. - A peer may inadvertently or maliciously sign an address that they do not control. In other words, a signature isn't a guarantee that a given address is valid. - Some addresses may be ambiguous. For example, addresses on a private subnet are valid within that subnet but are useless on the public internet. - Once all these pieces are in place, we will also need a way to prioritize addresses based on their authenticity, that is, the dialer can prioritize self-certified addresses over addresses from an unknown origin. - - Modular dialer? (taken from go PR notes) - - With the modular dialer, users should easily be able to configure precedence. With dialer v1, anything we do to prioritise dials is gonna be spaghetti and adhoc. With the modular dialer, you’d be able to specify the order of dials when instantiating the pipeline. - - Multiple parallel dials. We already have the issue where new addresses aren't added to existing dials. +- Modular dialer? (taken from go PR notes) + - With the modular dialer, users should easily be able to configure precedence. With dialer v1, anything we do to prioritise dials is gonna be spaghetti and adhoc. With the modular dialer, you’d be able to specify the order of dials when instantiating the pipeline. + - Multiple parallel dials. We already have the issue where new addresses aren't added to existing dials. + +# Install + +```console +$ npm i @libp2p/peer-record +``` + +## Browser ` +``` -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/peer-record/package.json b/packages/peer-record/package.json index a7110a82b4..d0e6c0ccbc 100644 --- a/packages/peer-record/package.json +++ b/packages/peer-record/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/peer-record", - "version": "6.0.6", + "version": "6.0.7", "description": "Used to transfer signed peer data across the network", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/peer-record#readme", @@ -56,10 +56,10 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/crypto": "^2.0.5", - "@libp2p/interface": "^0.1.3", - "@libp2p/peer-id": "^3.0.3", - "@libp2p/utils": "^4.0.4", + "@libp2p/crypto": "^2.0.6", + "@libp2p/interface": "^0.1.4", + "@libp2p/peer-id": "^3.0.4", + "@libp2p/utils": "^4.0.5", "@multiformats/multiaddr": "^12.1.5", "protons-runtime": "^5.0.0", "uint8-varint": "^2.0.0", @@ -67,7 +67,7 @@ "uint8arrays": "^4.0.6" }, "devDependencies": { - "@libp2p/peer-id-factory": "^3.0.5", + "@libp2p/peer-id-factory": "^3.0.6", "aegir": "^41.0.2", "protons": "^7.0.2" } diff --git a/packages/peer-record/src/index.ts b/packages/peer-record/src/index.ts index 51238b79ac..c3207bac39 100644 --- a/packages/peer-record/src/index.ts +++ b/packages/peer-record/src/index.ts @@ -1,3 +1,138 @@ +/** + * @packageDocumentation + * + * Libp2p nodes need to store data in a public location (e.g. a DHT), or rely on potentially untrustworthy intermediaries to relay information over its lifetime. Accordingly, libp2p nodes need to be able to verify that the data came from a specific peer and that it hasn't been tampered with. + * + * ## Envelope + * + * Libp2p provides an all-purpose data container called **envelope**. It was created to enable the distribution of verifiable records, which we can prove originated from the addressed peer itself. The envelope includes a signature of the data, so that its authenticity is verified. + * + * This envelope stores a marshaled record implementing the [interface-record](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/record). These Records are designed to be serialized to bytes and placed inside of the envelopes before being shared with other peers. + * + * You can read further about the envelope in [libp2p/specs#217](https://github.com/libp2p/specs/pull/217). + * + * @example + * + * Create an envelope with an instance of an [interface-record](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/record) implementation and prepare it for being exchanged: + * + * ```js + * // interface-record implementation example with the "libp2p-example" namespace + * import { PeerRecord } from '@libp2p/peer-record' + * import { fromString } from 'uint8arrays/from-string' + * + * class ExampleRecord extends PeerRecord { + * constructor () { + * super ('libp2p-example', fromString('0302', 'hex')) + * } + * + * marshal () {} + * + * equals (other) {} + * } + * + * ExampleRecord.createFromProtobuf = () => {} + * ``` + * + * ```js + * import { PeerEnvelope } from '@libp2p/peer-record' + * import { ExampleRecord } from './example-record.js' + * + * const rec = new ExampleRecord() + * const e = await PeerEnvelope.seal(rec, peerId) + * const wireData = e.marshal() + * ``` + * + * @example + * + * Consume a received envelope (`wireData`) and transform it back to a record: + * + * ```js + * import { PeerEnvelope } from '@libp2p/peer-record' + * import { ExampleRecord } from './example-record.js' + * + * const domain = 'libp2p-example' + * let e + * + * try { + * e = await PeerEnvelope.openAndCertify(wireData, domain) + * } catch (err) {} + * + * const rec = ExampleRecord.createFromProtobuf(e.payload) + * ``` + * + * ## Peer Record + * + * All libp2p nodes keep a `PeerStore`, that among other information stores a set of known addresses for each peer, which can come from a variety of sources. + * + * Libp2p peer records were created to enable the distribution of verifiable address records, which we can prove originated from the addressed peer itself. With such guarantees, libp2p is able to prioritize addresses based on their authenticity, with the most strict strategy being to only dial certified addresses (no strategies have been implemented at the time of writing). + * + * A peer record contains the peers' publicly reachable listen addresses, and may be extended in the future to contain additional metadata relevant to routing. It also contains a `seqNumber` field, a timestamp per the spec, so that we can verify the most recent record. + * + * You can read further about the Peer Record in [libp2p/specs#217](https://github.com/libp2p/specs/pull/217). + * + * @example + * + * Create a new Peer Record + * + * ```js + * import { PeerRecord } from '@libp2p/peer-record' + * + * const pr = new PeerRecord({ + * peerId: node.peerId, + * multiaddrs: node.multiaddrs + * }) + * ``` + * + * @example + * + * Create a Peer Record from a protobuf + * + * ```js + * import { PeerRecord } from '@libp2p/peer-record' + * + * const pr = PeerRecord.createFromProtobuf(data) + * ``` + * + * ## Libp2p Flows + * + * ### Self Record + * + * Once a libp2p node has started and is listening on a set of multiaddrs, its own peer record can be created. + * + * The identify service is responsible for creating the self record when the identify protocol kicks in for the first time. This record will be stored for future needs of the identify protocol when connecting with other peers. + * + * ### Self record Updates + * + * While creating peer records is fairly trivial, addresses are not static and might be modified at arbitrary times. This can happen via an Address Manager API, or even through AutoRelay/AutoNAT. + * + * When a libp2p node changes its listen addresses, the identify service will be informed. Once that happens, the identify service creates a new self record and stores it. With the new record, the identify push/delta protocol will be used to communicate this change to the connected peers. + * + * ### Subsystem receiving a record + * + * Considering that a node can discover other peers' addresses from a variety of sources, Libp2p Peerstore can differentiate the addresses that were obtained through a signed peer record. + * + * Once a record is received and its signature properly validated, its envelope is stored in the AddressBook in its byte representation. The `seqNumber` remains unmarshalled so that we can quickly compare it against incoming records to determine the most recent record. + * + * The AddressBook Addresses will be updated with the content of the envelope with a certified property. This allows other subsystems to identify the known certified addresses of a peer. + * + * ### Subsystem providing a record + * + * Libp2p subsystems that exchange other peers information will provide the envelope that they received by those peers. As a result, other peers can verify if the envelope was really created by the addressed peer. + * + * When a subsystem wants to provide a record, it will get it from the AddressBook, if it exists. Other subsystems are also able to provide the self record, since it is also stored in the AddressBook. + * + * ## Future Work + * + * - Persistence only considering certified addresses? + * - Peers may not know their own addresses. It's often impossible to automatically infer one's own public address, and peers may need to rely on third party peers to inform them of their observed public addresses. + * - A peer may inadvertently or maliciously sign an address that they do not control. In other words, a signature isn't a guarantee that a given address is valid. + * - Some addresses may be ambiguous. For example, addresses on a private subnet are valid within that subnet but are useless on the public internet. + * - Once all these pieces are in place, we will also need a way to prioritize addresses based on their authenticity, that is, the dialer can prioritize self-certified addresses over addresses from an unknown origin. + * - Modular dialer? (taken from go PR notes) + * - With the modular dialer, users should easily be able to configure precedence. With dialer v1, anything we do to prioritise dials is gonna be spaghetti and adhoc. With the modular dialer, you’d be able to specify the order of dials when instantiating the pipeline. + * - Multiple parallel dials. We already have the issue where new addresses aren't added to existing dials. + */ + export { RecordEnvelope } from './envelope/index.js' export type { RecordEnvelopeInit } from './envelope/index.js' export { PeerRecord } from './peer-record/index.js' diff --git a/packages/peer-store/CHANGELOG.md b/packages/peer-store/CHANGELOG.md index 0996044df8..12927a0bc2 100644 --- a/packages/peer-store/CHANGELOG.md +++ b/packages/peer-store/CHANGELOG.md @@ -11,6 +11,26 @@ * **dev:** bump p-event from 5.0.1 to 6.0.0 ([#89](https://github.com/libp2p/js-libp2p-peer-store/issues/89)) ([9d96700](https://github.com/libp2p/js-libp2p-peer-store/commit/9d9670048b5e8feeac656cba92cb2e513e4a77be)) +### [9.0.7](https://www.github.com/libp2p/js-libp2p/compare/peer-store-v9.0.6...peer-store-v9.0.7) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-collections bumped from ^4.0.5 to ^4.0.6 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + * @libp2p/peer-record bumped from ^6.0.6 to ^6.0.7 + ### [9.0.6](https://www.github.com/libp2p/js-libp2p/compare/peer-store-v9.0.5...peer-store-v9.0.6) (2023-10-06) @@ -498,4 +518,4 @@ Co-authored-by: Alex Potsides ### Features -* add peer store/records, and streams are just streams ([#160](https://github.com/libp2p/js-libp2p-interfaces/issues/160)) ([8860a0c](https://github.com/libp2p/js-libp2p-interfaces/commit/8860a0cd46b359a5648402d83870f7ff957222fe)) +* add peer store/records, and streams are just streams ([#160](https://github.com/libp2p/js-libp2p-interfaces/issues/160)) ([8860a0c](https://github.com/libp2p/js-libp2p-interfaces/commit/8860a0cd46b359a5648402d83870f7ff957222fe)) \ No newline at end of file diff --git a/packages/peer-store/README.md b/packages/peer-store/README.md index 41a310aad6..7b7d85b490 100644 --- a/packages/peer-store/README.md +++ b/packages/peer-store/README.md @@ -1,5 +1,3 @@ -# @libp2p/peer-store - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,21 +5,13 @@ > Stores information about peers libp2p knows on the network -## Table of contents - -- [Install](#install) - - [Browser ` ``` -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. - -[peer-id]: https://github.com/libp2p/js-peer-id - -[peer-store-events]: [https://github.com/libp2p/js-libp2p/blob/master/doc/API.md#libp2ppeerStore] diff --git a/packages/peer-store/package.json b/packages/peer-store/package.json index 74350542c4..a2896c2f05 100644 --- a/packages/peer-store/package.json +++ b/packages/peer-store/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/peer-store", - "version": "9.0.6", + "version": "9.0.7", "description": "Stores information about peers libp2p knows on the network", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/peer-store#readme", @@ -54,12 +54,12 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", - "@libp2p/peer-collections": "^4.0.5", - "@libp2p/peer-id": "^3.0.3", - "@libp2p/peer-id-factory": "^3.0.5", - "@libp2p/peer-record": "^6.0.6", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", + "@libp2p/peer-collections": "^4.0.6", + "@libp2p/peer-id": "^3.0.4", + "@libp2p/peer-id-factory": "^3.0.6", + "@libp2p/peer-record": "^6.0.7", "@multiformats/multiaddr": "^12.1.5", "interface-datastore": "^8.2.0", "it-all": "^3.0.2", @@ -77,6 +77,6 @@ "p-defer": "^4.0.0", "p-event": "^6.0.0", "protons": "^7.0.2", - "sinon": "^16.0.0" + "sinon": "^17.0.0" } } diff --git a/packages/peer-store/src/index.ts b/packages/peer-store/src/index.ts index d130a8a7c3..ec9b4632bf 100644 --- a/packages/peer-store/src/index.ts +++ b/packages/peer-store/src/index.ts @@ -3,7 +3,7 @@ import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record' import all from 'it-all' import { PersistentStore, type PeerUpdate } from './store.js' import type { Libp2pEvents } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore, Peer, PeerData, PeerQuery } from '@libp2p/interface/peer-store' import type { Multiaddr } from '@multiformats/multiaddr' @@ -14,7 +14,7 @@ const log = logger('libp2p:peer-store') export interface PersistentPeerStoreComponents { peerId: PeerId datastore: Datastore - events: EventEmitter + events: TypedEventTarget } /** @@ -33,7 +33,7 @@ export interface PersistentPeerStoreInit { */ export class PersistentPeerStore implements PeerStore { private readonly store: PersistentStore - private readonly events: EventEmitter + private readonly events: TypedEventTarget private readonly peerId: PeerId constructor (components: PersistentPeerStoreComponents, init: PersistentPeerStoreInit = {}) { diff --git a/packages/peer-store/test/index.spec.ts b/packages/peer-store/test/index.spec.ts index 868d811c72..e5fd106beb 100644 --- a/packages/peer-store/test/index.spec.ts +++ b/packages/peer-store/test/index.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record' import { multiaddr } from '@multiformats/multiaddr' @@ -18,12 +18,12 @@ describe('PersistentPeerStore', () => { let peerId: PeerId let otherPeerId: PeerId let peerStore: PersistentPeerStore - let events: EventEmitter + let events: TypedEventTarget beforeEach(async () => { peerId = await createEd25519PeerId() otherPeerId = await createEd25519PeerId() - events = new EventEmitter() + events = new TypedEventEmitter() peerStore = new PersistentPeerStore({ peerId, events, datastore: new MemoryDatastore() }) }) diff --git a/packages/peer-store/test/merge.spec.ts b/packages/peer-store/test/merge.spec.ts index 8a0f6e8475..cb615b0acb 100644 --- a/packages/peer-store/test/merge.spec.ts +++ b/packages/peer-store/test/merge.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -20,12 +20,12 @@ describe('merge', () => { let peerId: PeerId let otherPeerId: PeerId let peerStore: PersistentPeerStore - let events: EventEmitter + let events: TypedEventTarget beforeEach(async () => { peerId = await createEd25519PeerId() otherPeerId = await createEd25519PeerId() - events = new EventEmitter() + events = new TypedEventEmitter() peerStore = new PersistentPeerStore({ peerId, events, datastore: new MemoryDatastore() }) }) diff --git a/packages/peer-store/test/patch.spec.ts b/packages/peer-store/test/patch.spec.ts index 2800fc71fb..938bfffbfd 100644 --- a/packages/peer-store/test/patch.spec.ts +++ b/packages/peer-store/test/patch.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -20,12 +20,12 @@ describe('patch', () => { let peerId: PeerId let otherPeerId: PeerId let peerStore: PersistentPeerStore - let events: EventEmitter + let events: TypedEventTarget beforeEach(async () => { peerId = await createEd25519PeerId() otherPeerId = await createEd25519PeerId() - events = new EventEmitter() + events = new TypedEventEmitter() peerStore = new PersistentPeerStore({ peerId, events, datastore: new MemoryDatastore() }) }) diff --git a/packages/peer-store/test/save.spec.ts b/packages/peer-store/test/save.spec.ts index dde76aa979..160018c9b9 100644 --- a/packages/peer-store/test/save.spec.ts +++ b/packages/peer-store/test/save.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { createEd25519PeerId, createRSAPeerId, createSecp256k1PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -23,12 +23,12 @@ describe('save', () => { let peerId: PeerId let otherPeerId: PeerId let peerStore: PersistentPeerStore - let events: EventEmitter + let events: TypedEventTarget beforeEach(async () => { peerId = await createEd25519PeerId() otherPeerId = await createEd25519PeerId() - events = new EventEmitter() + events = new TypedEventEmitter() peerStore = new PersistentPeerStore({ peerId, events, datastore: new MemoryDatastore() }) }) diff --git a/packages/protocol-perf/CHANGELOG.md b/packages/protocol-perf/CHANGELOG.md index edfb9ed294..e745f44df3 100644 --- a/packages/protocol-perf/CHANGELOG.md +++ b/packages/protocol-perf/CHANGELOG.md @@ -1,5 +1,36 @@ # Changelog +### [1.1.13](https://www.github.com/libp2p/js-libp2p/compare/perf-v1.1.12...perf-v1.1.13) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^2.0.5 to ^2.0.6 + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + * @libp2p/interface-internal bumped from ^0.1.6 to ^0.1.7 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + * @libp2p/tcp bumped from ^8.0.9 to ^8.0.10 + * libp2p bumped from ^0.46.15 to ^0.46.16 + +### [1.1.12](https://www.github.com/libp2p/js-libp2p/compare/perf-v1.1.11...perf-v1.1.12) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * libp2p bumped from ^0.46.14 to ^0.46.15 + ### [1.1.11](https://www.github.com/libp2p/js-libp2p/compare/perf-v1.1.10...perf-v1.1.11) (2023-10-10) @@ -147,4 +178,4 @@ * @libp2p/logger bumped from ^3.0.0 to ^3.0.2 * @libp2p/peer-id-factory bumped from 3.0.0 to ^3.0.3 * @libp2p/tcp bumped from ^8.0.0 to ^8.0.3 - * libp2p bumped from ^0.46.3 to ^0.46.4 + * libp2p bumped from ^0.46.3 to ^0.46.4 \ No newline at end of file diff --git a/packages/protocol-perf/README.md b/packages/protocol-perf/README.md index 15ca3f4ada..915e7420ea 100644 --- a/packages/protocol-perf/README.md +++ b/packages/protocol-perf/README.md @@ -1,5 +1,3 @@ -# @libp2p/perf - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,39 +5,58 @@ > Implementation of Perf Protocol -## Table of contents +# About + +The `performanceService` implements the [perf protocol](https://github.com/libp2p/specs/blob/master/perf/perf.md), which is used to measure performance within and across libp2p implementations +addresses. -- [Install](#install) - - [Browser ` ``` -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/protocol-perf/package.json b/packages/protocol-perf/package.json index 6902f8d8f0..b9dd5e2c01 100644 --- a/packages/protocol-perf/package.json +++ b/packages/protocol-perf/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/perf", - "version": "1.1.11", + "version": "1.1.13", "description": "Implementation of Perf Protocol", "author": "@maschad / @marcopolo", "license": "Apache-2.0 OR MIT", @@ -50,16 +50,16 @@ "dependencies": { "@chainsafe/libp2p-noise": "^13.0.0", "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/crypto": "^2.0.5", - "@libp2p/interface": "^0.1.3", - "@libp2p/interface-compliance-tests": "^4.1.1", - "@libp2p/interface-internal": "^0.1.6", + "@libp2p/crypto": "^2.0.6", + "@libp2p/interface": "^0.1.4", + "@libp2p/interface-compliance-tests": "^4.1.2", + "@libp2p/interface-internal": "^0.1.7", "@libp2p/interfaces": "3.3.2", - "@libp2p/logger": "^3.0.3", - "@libp2p/peer-id-factory": "^3.0.5", - "@libp2p/tcp": "^8.0.9", + "@libp2p/logger": "^3.0.4", + "@libp2p/peer-id-factory": "^3.0.6", + "@libp2p/tcp": "^8.0.10", "@multiformats/multiaddr": "^12.1.5", - "libp2p": "^0.46.14", + "libp2p": "^0.46.16", "uint8arrays": "^4.0.6", "yargs": "^17.7.2" }, diff --git a/packages/protocol-perf/test/index.spec.ts b/packages/protocol-perf/test/index.spec.ts index 83fd6c310f..fc8299ed10 100644 --- a/packages/protocol-perf/test/index.spec.ts +++ b/packages/protocol-perf/test/index.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { connectionPair, mockRegistrar, type MockNetworkComponents, mockConnectionManager } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -11,7 +11,7 @@ export async function createComponents (): Promise { const components: any = { peerId: await createEd25519PeerId(), registrar: mockRegistrar(), - events: new EventEmitter() + events: new TypedEventEmitter() } components.connectionManager = mockConnectionManager(components) diff --git a/packages/pubsub-floodsub/CHANGELOG.md b/packages/pubsub-floodsub/CHANGELOG.md index 178ead29e1..f5f91fb1e5 100644 --- a/packages/pubsub-floodsub/CHANGELOG.md +++ b/packages/pubsub-floodsub/CHANGELOG.md @@ -11,6 +11,21 @@ * **dev:** bump aegir from 38.1.8 to 39.0.10 ([#233](https://github.com/libp2p/js-libp2p-floodsub/issues/233)) ([e073298](https://github.com/libp2p/js-libp2p-floodsub/commit/e073298f324a89656b0ca6d9a629e60eaedc7873)) +### [8.0.10](https://www.github.com/libp2p/js-libp2p/compare/floodsub-v8.0.9...floodsub-v8.0.10) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/pubsub bumped from ^8.0.7 to ^8.0.8 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + * @libp2p/peer-collections bumped from ^4.0.5 to ^4.0.6 + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + ### [8.0.9](https://www.github.com/libp2p/js-libp2p/compare/floodsub-v8.0.8...floodsub-v8.0.9) (2023-10-06) diff --git a/packages/pubsub-floodsub/README.md b/packages/pubsub-floodsub/README.md index 9fadcbc2ca..a1b7c91b9b 100644 --- a/packages/pubsub-floodsub/README.md +++ b/packages/pubsub-floodsub/README.md @@ -1,5 +1,3 @@ -# @libp2p/floodsub - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,31 +5,9 @@ > libp2p-floodsub, also known as pubsub-flood or just dumbsub, this implementation of pubsub focused on delivering an API for Publish/Subscribe, but with no CastTree Forming (it just floods the network). -## Table of contents - -- [Install](#install) - - [Browser ` -``` +# About -## Don't use this module +> Don't use this module This module is a naive implementation of pubsub. It broadcasts all messages to all network peers, cannot provide older messages and has no protection against bad actors. @@ -39,7 +15,7 @@ It exists for academic purposes only, you should not use it in production. Instead please use [gossipsub](https://www.npmjs.com/package/@chainsafe/libp2p-gossipsub) - a more complete implementation which is also compatible with floodsub. -## Usage +## Example ```JavaScript import { createLibp2pNode } from 'libp2p' @@ -59,17 +35,31 @@ node.pubsub.addEventListener('message', (evt) => { node.pubsub.publish('fruit', new TextEncoder().encode('banana')) ``` -## API Docs +# Install + +```console +$ npm i @libp2p/floodsub +``` + +## Browser ` +``` + +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/pubsub-floodsub/package.json b/packages/pubsub-floodsub/package.json index 0099535d9b..f00f74f793 100644 --- a/packages/pubsub-floodsub/package.json +++ b/packages/pubsub-floodsub/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/floodsub", - "version": "8.0.9", + "version": "8.0.10", "description": "libp2p-floodsub, also known as pubsub-flood or just dumbsub, this implementation of pubsub focused on delivering an API for Publish/Subscribe, but with no CastTree Forming (it just floods the network).", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/pubsub-floodsub#readme", @@ -55,23 +55,23 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", - "@libp2p/pubsub": "^8.0.7", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", + "@libp2p/pubsub": "^8.0.8", "protons-runtime": "^5.0.0", "uint8arraylist": "^2.4.3", "uint8arrays": "^4.0.6" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^4.1.1", - "@libp2p/peer-collections": "^4.0.5", - "@libp2p/peer-id-factory": "^3.0.5", + "@libp2p/interface-compliance-tests": "^4.1.2", + "@libp2p/peer-collections": "^4.0.6", + "@libp2p/peer-id-factory": "^3.0.6", "@multiformats/multiaddr": "^12.1.3", "@types/sinon": "^10.0.15", "aegir": "^41.0.2", "multiformats": "^12.0.1", "p-wait-for": "^5.0.2", "protons": "^7.0.2", - "sinon": "^16.0.0" + "sinon": "^17.0.0" } } diff --git a/packages/pubsub-floodsub/src/index.ts b/packages/pubsub-floodsub/src/index.ts index 4d50605173..53a0e41677 100644 --- a/packages/pubsub-floodsub/src/index.ts +++ b/packages/pubsub-floodsub/src/index.ts @@ -1,3 +1,35 @@ +/** + * @packageDocumentation + * + * > Don't use this module + * + * This module is a naive implementation of pubsub. It broadcasts all messages to all network peers, cannot provide older messages and has no protection against bad actors. + * + * It exists for academic purposes only, you should not use it in production. + * + * Instead please use [gossipsub](https://www.npmjs.com/package/@chainsafe/libp2p-gossipsub) - a more complete implementation which is also compatible with floodsub. + * + * @example + * + * ```JavaScript + * import { createLibp2pNode } from 'libp2p' + * import { floodsub } from '@libp2p/floodsub' + * + * const node = await createLibp2pNode({ + * pubsub: floodsub() + * //... other options + * }) + * await node.start() + * + * node.pubsub.subscribe('fruit') + * node.pubsub.addEventListener('message', (evt) => { + * console.log(evt) + * }) + * + * node.pubsub.publish('fruit', new TextEncoder().encode('banana')) + * ``` + */ + import { logger } from '@libp2p/logger' import { PubSubBaseProtocol, type PubSubComponents } from '@libp2p/pubsub' import { toString } from 'uint8arrays/to-string' diff --git a/packages/pubsub/CHANGELOG.md b/packages/pubsub/CHANGELOG.md index b4847adc19..c155018d78 100644 --- a/packages/pubsub/CHANGELOG.md +++ b/packages/pubsub/CHANGELOG.md @@ -5,6 +5,28 @@ * **dev:** bump delay from 5.0.0 to 6.0.0 ([#144](https://github.com/libp2p/js-libp2p-pubsub/issues/144)) ([1364ce4](https://github.com/libp2p/js-libp2p-pubsub/commit/1364ce41815d3392cfca61169e113cc5414ac2d9)) +### [8.0.8](https://www.github.com/libp2p/js-libp2p/compare/pubsub-v8.0.7...pubsub-v8.0.8) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^2.0.5 to ^2.0.6 + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/interface-internal bumped from ^0.1.6 to ^0.1.7 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-collections bumped from ^4.0.5 to ^4.0.6 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * devDependencies + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + ### [8.0.7](https://www.github.com/libp2p/js-libp2p/compare/pubsub-v8.0.6...pubsub-v8.0.7) (2023-10-06) @@ -642,4 +664,4 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline ### BREAKING CHANGES -* not all fields from concrete classes have been added to the interfaces, some adjustment may be necessary as this gets rolled out +* not all fields from concrete classes have been added to the interfaces, some adjustment may be necessary as this gets rolled out \ No newline at end of file diff --git a/packages/pubsub/README.md b/packages/pubsub/README.md index a985a40c40..7962231142 100644 --- a/packages/pubsub/README.md +++ b/packages/pubsub/README.md @@ -1,5 +1,3 @@ -# @libp2p/pubsub - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,22 +5,13 @@ > libp2p pubsub base class -## Table of contents - -- [Install](#install) - - [Browser ` ``` -## Usage - -```console -npm i @libp2p/pubsub -``` - -```javascript -import { PubSubBaseProtocol } from '@libp2p/pubsub' - -class MyPubsubImplementation extends PubSubBaseProtocol { - // .. extra methods here -} -``` - -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/pubsub/package.json b/packages/pubsub/package.json index baf14e94f9..4aef70e43c 100644 --- a/packages/pubsub/package.json +++ b/packages/pubsub/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/pubsub", - "version": "8.0.7", + "version": "8.0.8", "description": "libp2p pubsub base class", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/pubsub#readme", @@ -79,12 +79,12 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/crypto": "^2.0.5", - "@libp2p/interface": "^0.1.3", - "@libp2p/interface-internal": "^0.1.6", - "@libp2p/logger": "^3.0.3", - "@libp2p/peer-collections": "^4.0.5", - "@libp2p/peer-id": "^3.0.3", + "@libp2p/crypto": "^2.0.6", + "@libp2p/interface": "^0.1.4", + "@libp2p/interface-internal": "^0.1.7", + "@libp2p/logger": "^3.0.4", + "@libp2p/peer-collections": "^4.0.6", + "@libp2p/peer-id": "^3.0.4", "abortable-iterator": "^5.0.1", "it-length-prefixed": "^9.0.1", "it-pipe": "^3.0.1", @@ -95,7 +95,7 @@ "uint8arrays": "^4.0.6" }, "devDependencies": { - "@libp2p/peer-id-factory": "^3.0.5", + "@libp2p/peer-id-factory": "^3.0.6", "@types/sinon": "^10.0.15", "aegir": "^41.0.2", "delay": "^6.0.0", @@ -104,6 +104,6 @@ "p-wait-for": "^5.0.2", "protons": "^7.0.2", "protons-runtime": "^5.0.0", - "sinon": "^16.0.0" + "sinon": "^17.0.0" } } diff --git a/packages/pubsub/src/index.ts b/packages/pubsub/src/index.ts index b8760e3a4f..dc78665470 100644 --- a/packages/pubsub/src/index.ts +++ b/packages/pubsub/src/index.ts @@ -1,5 +1,20 @@ +/** + * @packageDocumentation + * + * A set of components to be extended in order to create a pubsub implementation. + * + * @example + * ```javascript + * import { PubSubBaseProtocol } from '@libp2p/pubsub' + * + * class MyPubsubImplementation extends PubSubBaseProtocol { + * // .. extra methods here + * } + * ``` + */ + import { CodeError } from '@libp2p/interface/errors' -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { type PubSub, type Message, type StrictNoSign, type StrictSign, type PubSubInit, type PubSubEvents, type PeerStreams, type PubSubRPCMessage, type PubSubRPC, type PubSubRPCSubscription, type SubscriptionChangeData, type PublishResult, type TopicValidatorFn, TopicValidatorResult } from '@libp2p/interface/pubsub' import { logger } from '@libp2p/logger' import { PeerMap, PeerSet } from '@libp2p/peer-collections' @@ -28,7 +43,7 @@ export interface PubSubComponents { * PubSubBaseProtocol handles the peers and connections logic for pubsub routers * and specifies the API that pubsub routers should have. */ -export abstract class PubSubBaseProtocol = PubSubEvents> extends EventEmitter implements PubSub { +export abstract class PubSubBaseProtocol = PubSubEvents> extends TypedEventEmitter implements PubSub { public started: boolean /** * Map of topics to which peers are subscribed to @@ -198,6 +213,12 @@ export abstract class PubSubBaseProtocol = Pu protected _onPeerConnected (peerId: PeerId, conn: Connection): void { log('connected %p', peerId) + // if this connection is already in use for pubsub, ignore it + if (conn.streams.find(stream => stream.direction === 'outbound' && stream.protocol != null && this.multicodecs.includes(stream.protocol)) != null) { + log('outbound pubsub streams already present on connection from %p', peerId) + return + } + void Promise.resolve().then(async () => { try { const stream = await conn.newStream(this.multicodecs) @@ -513,8 +534,14 @@ export abstract class PubSubBaseProtocol = Pu sendRpc (peer: PeerId, rpc: PubSubRPC): void { const peerStreams = this.peers.get(peer) - if (peerStreams == null || !peerStreams.isWritable) { - log.error('Cannot send RPC to %p as there is no open stream to it available', peer) + if (peerStreams == null) { + log.error('Cannot send RPC to %p as there are no streams to it available', peer) + + return + } + + if (!peerStreams.isWritable) { + log.error('Cannot send RPC to %p as there is no outbound stream to it available', peer) return } diff --git a/packages/pubsub/src/peer-streams.ts b/packages/pubsub/src/peer-streams.ts index c4a13387a5..8e1646907a 100644 --- a/packages/pubsub/src/peer-streams.ts +++ b/packages/pubsub/src/peer-streams.ts @@ -1,4 +1,4 @@ -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { abortableSource } from 'abortable-iterator' import * as lp from 'it-length-prefixed' @@ -20,7 +20,7 @@ export interface PeerStreamsInit { /** * Thin wrapper around a peer's inbound / outbound pubsub streams */ -export class PeerStreams extends EventEmitter { +export class PeerStreams extends TypedEventEmitter { public readonly id: PeerId public readonly protocol: string /** diff --git a/packages/pubsub/test/utils/index.ts b/packages/pubsub/test/utils/index.ts index b98c78b76f..fdd7e5b535 100644 --- a/packages/pubsub/test/utils/index.ts +++ b/packages/pubsub/test/utils/index.ts @@ -136,7 +136,8 @@ export const ConnectionPair = (): [Connection, Connection] => { ...d0, protocol: protocol[0], closeWrite: async () => {} - }) + }), + streams: [] }, { // @ts-expect-error incomplete implementation @@ -144,7 +145,8 @@ export const ConnectionPair = (): [Connection, Connection] => { ...d1, protocol: protocol[0], closeWrite: async () => {} - }) + }), + streams: [] } ] } diff --git a/packages/stream-multiplexer-mplex/CHANGELOG.md b/packages/stream-multiplexer-mplex/CHANGELOG.md index 5f4a08412a..9b0f54c66b 100644 --- a/packages/stream-multiplexer-mplex/CHANGELOG.md +++ b/packages/stream-multiplexer-mplex/CHANGELOG.md @@ -12,6 +12,18 @@ * **dev:** bump cborg from 1.10.2 to 2.0.1 ([#282](https://github.com/libp2p/js-libp2p-mplex/issues/282)) ([4dbc590](https://github.com/libp2p/js-libp2p-mplex/commit/4dbc590d1ac92581fe2e937757567eef3854acf4)) * **dev:** bump delay from 5.0.0 to 6.0.0 ([#281](https://github.com/libp2p/js-libp2p-mplex/issues/281)) ([1e03e75](https://github.com/libp2p/js-libp2p-mplex/commit/1e03e75369722be9872f747cd83f555bc08d49fe)) +### [9.0.9](https://www.github.com/libp2p/js-libp2p/compare/mplex-v9.0.8...mplex-v9.0.9) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + ### [9.0.8](https://www.github.com/libp2p/js-libp2p/compare/mplex-v9.0.7...mplex-v9.0.8) (2023-10-06) diff --git a/packages/stream-multiplexer-mplex/README.md b/packages/stream-multiplexer-mplex/README.md index ee8b856784..dc8954f6c2 100644 --- a/packages/stream-multiplexer-mplex/README.md +++ b/packages/stream-multiplexer-mplex/README.md @@ -1,5 +1,3 @@ -# @libp2p/mplex - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,22 +5,13 @@ > JavaScript implementation of -## Table of contents - -- [Install](#install) - - [Browser ` ``` -[![](https://github.com/libp2p/interface-stream-muxer/raw/master/img/badge.png)](https://github.com/libp2p/interface-stream-muxer) - -## Usage - -```js -import { mplex } from '@libp2p/mplex' -import { pipe } from 'it-pipe' - -const factory = mplex() - -const muxer = factory.createStreamMuxer(components, { - onStream: stream => { // Receive a duplex stream from the remote - // ...receive data from the remote and optionally send data back - }, - onStreamEnd: stream => { - // ...handle any tracking you may need of stream closures - } -}) - -pipe(conn, muxer, conn) // conn is duplex connection to another peer - -const stream = muxer.newStream() // Create a new duplex stream to the remote - -// Use the duplex stream to send some data to the remote... -pipe([1, 2, 3], stream) -``` - ## API Docs - diff --git a/packages/stream-multiplexer-mplex/examples/dialer.js b/packages/stream-multiplexer-mplex/examples/dialer.js deleted file mode 100644 index 9c33ba34ba..0000000000 --- a/packages/stream-multiplexer-mplex/examples/dialer.js +++ /dev/null @@ -1,45 +0,0 @@ -/* eslint-disable no-console */ -'use strict' - -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import tcp from 'net' -import { pipe } from 'it-pipe' -import { toIterable } from './util.js' -import { Mplex } from '../dist/src/index.js' - -const socket = toIterable(tcp.connect(9999)) -console.log('[dialer] socket stream opened') - -const controller = new AbortController() - -const factory = new Mplex({ signal: controller.signal }) -const muxer = factory.createStreamMuxer() - -const pipeMuxerToSocket = async () => { - await pipe(muxer, socket, muxer) - console.log('[dialer] socket stream closed') -} - -const sendAndReceive = async () => { - const muxedStream = muxer.newStream('hello') - console.log('[dialer] muxed stream opened') - - await pipe( - [uint8ArrayFromString('hey, how is it going. I am the dialer')], - muxedStream, - async source => { - for await (const chunk of source) { - console.log('[dialer] received:') - console.log(uint8ArrayToString(chunk.slice())) - } - } - ) - console.log('[dialer] muxed stream closed') - - // Close the socket stream after 1s - setTimeout(() => controller.abort(), 1000) -} - -pipeMuxerToSocket() -sendAndReceive() diff --git a/packages/stream-multiplexer-mplex/examples/listener.js b/packages/stream-multiplexer-mplex/examples/listener.js deleted file mode 100644 index 189c945531..0000000000 --- a/packages/stream-multiplexer-mplex/examples/listener.js +++ /dev/null @@ -1,37 +0,0 @@ -/* eslint-disable no-console */ -'use strict' - -import tcp from 'net' -import { pipe } from 'it-pipe' -import { toIterable } from './util.js' -import { Mplex } from '../dist/src/index.js' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const listener = tcp.createServer(async socket => { - console.log('[listener] Got connection!') - - const factory = new Mplex() - socket = toIterable(socket) - const muxer = factory.createStreamMuxer({ - onIncomingStream: async (stream) => { - console.log('[listener] muxed stream opened, id:', stream.id) - await pipe( - stream, - source => (async function * () { - for await (const chunk of source) { - console.log('[listener] received:') - console.log(uint8ArrayToString(chunk.slice())) - yield uint8ArrayFromString('thanks for the message, I am the listener') - } - })(), - stream - ) - console.log('[listener] muxed stream closed') - } - }) - await pipe(socket, muxer, socket) - console.log('[listener] socket stream closed') -}) - -listener.listen(9999, () => console.log('[listener] listening on 9999')) diff --git a/packages/stream-multiplexer-mplex/examples/util.js b/packages/stream-multiplexer-mplex/examples/util.js deleted file mode 100644 index 057c0c6787..0000000000 --- a/packages/stream-multiplexer-mplex/examples/util.js +++ /dev/null @@ -1,17 +0,0 @@ -// Simple convertion of Node.js duplex to iterable duplex (no backpressure) -export const toIterable = socket => { - return { - sink: async source => { - try { - for await (const chunk of source) { - socket.write(chunk) - } - } catch (err) { - // If not an abort then destroy the socket with an error - return socket.destroy(err.code === 'ABORT_ERR' ? null : err) - } - socket.end() - }, - source: socket - } -} diff --git a/packages/stream-multiplexer-mplex/package.json b/packages/stream-multiplexer-mplex/package.json index 67a1db3952..750f082c29 100644 --- a/packages/stream-multiplexer-mplex/package.json +++ b/packages/stream-multiplexer-mplex/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/mplex", - "version": "9.0.8", + "version": "9.0.9", "description": "JavaScript implementation of https://github.com/libp2p/mplex", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/stream-multiplexer-mplex#readme", @@ -57,8 +57,8 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", "abortable-iterator": "^5.0.1", "benchmark": "^2.1.4", "it-batched-bytes": "^2.0.2", @@ -70,7 +70,7 @@ "uint8arrays": "^4.0.6" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^4.1.1", + "@libp2p/interface-compliance-tests": "^4.1.2", "aegir": "^41.0.2", "cborg": "^4.0.3", "delay": "^6.0.0", diff --git a/packages/stream-multiplexer-mplex/src/index.ts b/packages/stream-multiplexer-mplex/src/index.ts index c7ef9549df..75913bb7b5 100644 --- a/packages/stream-multiplexer-mplex/src/index.ts +++ b/packages/stream-multiplexer-mplex/src/index.ts @@ -1,3 +1,36 @@ +/** + * @packageDocumentation + * + * This is a [simple stream multiplexer(https://docs.libp2p.io/concepts/multiplex/mplex/) that has been deprecated. + * + * Please use [@chainsafe/libp2p-yamux](https://www.npmjs.com/package/@chainsafe/libp2p-yamux) instead. + * + * @example + * + * ```js + * import { mplex } from '@libp2p/mplex' + * import { pipe } from 'it-pipe' + * + * const factory = mplex() + * + * const muxer = factory.createStreamMuxer(components, { + * onStream: stream => { // Receive a duplex stream from the remote + * // ...receive data from the remote and optionally send data back + * }, + * onStreamEnd: stream => { + * // ...handle any tracking you may need of stream closures + * } + * }) + * + * pipe(conn, muxer, conn) // conn is duplex connection to another peer + * + * const stream = muxer.newStream() // Create a new duplex stream to the remote + * + * // Use the duplex stream to send some data to the remote... + * pipe([1, 2, 3], stream) + * ``` + */ + import { MplexStreamMuxer } from './mplex.js' import type { StreamMuxer, StreamMuxerFactory, StreamMuxerInit } from '@libp2p/interface/stream-muxer' diff --git a/packages/transport-tcp/CHANGELOG.md b/packages/transport-tcp/CHANGELOG.md index 58cedcc115..b9860cbed6 100644 --- a/packages/transport-tcp/CHANGELOG.md +++ b/packages/transport-tcp/CHANGELOG.md @@ -5,6 +5,25 @@ * **dev:** bump aegir from 38.1.8 to 39.0.10 ([#279](https://github.com/libp2p/js-libp2p-tcp/issues/279)) ([3ed1235](https://github.com/libp2p/js-libp2p-tcp/commit/3ed12353aa48b5a933f80042846a8f1c2337fa47)) +### [8.0.10](https://www.github.com/libp2p/js-libp2p/compare/tcp-v8.0.9...tcp-v8.0.10) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/utils bumped from ^4.0.4 to ^4.0.5 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + ### [8.0.9](https://www.github.com/libp2p/js-libp2p/compare/tcp-v8.0.8...tcp-v8.0.9) (2023-10-06) @@ -1038,4 +1057,4 @@ -# 0.1.0 (2015-09-16) +# 0.1.0 (2015-09-16) \ No newline at end of file diff --git a/packages/transport-tcp/README.md b/packages/transport-tcp/README.md index 83fe40f6fc..a914a9db81 100644 --- a/packages/transport-tcp/README.md +++ b/packages/transport-tcp/README.md @@ -1,5 +1,3 @@ -# @libp2p/tcp - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,21 +5,11 @@ > A TCP transport for libp2p -## Table of contents - -- [Install](#install) -- [Usage](#usage) -- [API Docs](#api-docs) -- [License](#license) -- [Contribution](#contribution) - -## Install +# About -```console -$ npm i @libp2p/tcp -``` +A [libp2p transport](https://docs.libp2p.io/concepts/transports/overview/) based on the TCP networking stack. -## Usage +## Example ```js import { tcp } from '@libp2p/tcp' @@ -71,17 +59,23 @@ new connection opened Value: hello World! ``` -## API Docs +# Install + +```console +$ npm i @libp2p/tcp +``` + +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/transport-tcp/package.json b/packages/transport-tcp/package.json index 7633c493bb..140df64288 100644 --- a/packages/transport-tcp/package.json +++ b/packages/transport-tcp/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/tcp", - "version": "8.0.9", + "version": "8.0.10", "description": "A TCP transport for libp2p", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/transport-tcp#readme", @@ -51,21 +51,21 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", - "@libp2p/utils": "^4.0.4", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", + "@libp2p/utils": "^4.0.5", "@multiformats/mafmt": "^12.1.2", "@multiformats/multiaddr": "^12.1.5", "@types/sinon": "^10.0.15", "stream-to-it": "^0.2.2" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^4.1.1", + "@libp2p/interface-compliance-tests": "^4.1.2", "aegir": "^41.0.2", "it-all": "^3.0.1", "it-pipe": "^3.0.1", "p-defer": "^4.0.0", - "sinon": "^16.0.0", + "sinon": "^17.0.0", "uint8arrays": "^4.0.4" } } diff --git a/packages/transport-tcp/src/index.ts b/packages/transport-tcp/src/index.ts index ed526a2182..bf67f831bb 100644 --- a/packages/transport-tcp/src/index.ts +++ b/packages/transport-tcp/src/index.ts @@ -1,3 +1,59 @@ +/** + * @packageDocumentation + * + * A [libp2p transport](https://docs.libp2p.io/concepts/transports/overview/) based on the TCP networking stack. + * + * @example + * + * ```js + * import { tcp } from '@libp2p/tcp' + * import { multiaddr } from '@multiformats/multiaddr' + * import { pipe } from 'it-pipe' + * import all from 'it-all' + * + * // A simple upgrader that just returns the MultiaddrConnection + * const upgrader = { + * upgradeInbound: async maConn => maConn, + * upgradeOutbound: async maConn => maConn + * } + * + * const transport = tcp()() + * + * const listener = transport.createListener({ + * upgrader, + * handler: (socket) => { + * console.log('new connection opened') + * pipe( + * ['hello', ' ', 'World!'], + * socket + * ) + * } + * }) + * + * const addr = multiaddr('/ip4/127.0.0.1/tcp/9090') + * await listener.listen(addr) + * console.log('listening') + * + * const socket = await transport.dial(addr, { upgrader }) + * const values = await pipe( + * socket, + * all + * ) + * console.log(`Value: ${values.toString()}`) + * + * // Close connection after reading + * await listener.close() + * ``` + * + * Outputs: + * + * ```sh + * listening + * new connection opened + * Value: hello World! + * ``` + */ + import net from 'net' import { AbortError, CodeError } from '@libp2p/interface/errors' import { type CreateListenerOptions, type DialOptions, symbol, type Transport, type Listener } from '@libp2p/interface/transport' diff --git a/packages/transport-tcp/src/listener.ts b/packages/transport-tcp/src/listener.ts index 95792ed137..ee2d1a20f9 100644 --- a/packages/transport-tcp/src/listener.ts +++ b/packages/transport-tcp/src/listener.ts @@ -1,6 +1,6 @@ import net from 'net' import { CodeError } from '@libp2p/interface/errors' -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { CODE_P2P } from './constants.js' import { toMultiaddrConnection } from './socket-to-conn.js' @@ -71,7 +71,7 @@ type Status = { code: TCPListenerStatusCode.INACTIVE } | { netConfig: NetConfig } -export class TCPListener extends EventEmitter implements Listener { +export class TCPListener extends TypedEventEmitter implements Listener { private readonly server: net.Server /** Keep track of open connections to destroy in case of timeout */ private readonly connections = new Set() diff --git a/packages/transport-tcp/test/connection-limits.spec.ts b/packages/transport-tcp/test/connection-limits.spec.ts index 30aea96ac7..67a47c23e7 100644 --- a/packages/transport-tcp/test/connection-limits.spec.ts +++ b/packages/transport-tcp/test/connection-limits.spec.ts @@ -1,6 +1,6 @@ import net from 'node:net' import { promisify } from 'util' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -88,7 +88,7 @@ describe('closeAbove/listenBelow', () => { const trasnport = tcp({ closeServerOnMaxConnections: { listenBelow, closeAbove } })() const upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) const listener = trasnport.createListener({ upgrader }) as TCPListener // eslint-disable-next-line @typescript-eslint/promise-function-async @@ -115,7 +115,7 @@ describe('closeAbove/listenBelow', () => { const trasnport = tcp({ closeServerOnMaxConnections: { listenBelow, closeAbove } })() const upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) const listener = trasnport.createListener({ upgrader }) as TCPListener // eslint-disable-next-line @typescript-eslint/promise-function-async @@ -150,7 +150,7 @@ describe('closeAbove/listenBelow', () => { const trasnport = tcp({ closeServerOnMaxConnections: { listenBelow, closeAbove } })() const upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) const listener = trasnport.createListener({ upgrader }) as TCPListener // eslint-disable-next-line @typescript-eslint/promise-function-async @@ -181,7 +181,7 @@ describe('closeAbove/listenBelow', () => { const trasnport = tcp({ closeServerOnMaxConnections: { listenBelow, closeAbove } })() const upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) const listener = trasnport.createListener({ upgrader }) as TCPListener // eslint-disable-next-line @typescript-eslint/promise-function-async diff --git a/packages/transport-tcp/test/connection.spec.ts b/packages/transport-tcp/test/connection.spec.ts index 0308d61708..a8cb893edb 100644 --- a/packages/transport-tcp/test/connection.spec.ts +++ b/packages/transport-tcp/test/connection.spec.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -13,7 +13,7 @@ describe('valid localAddr and remoteAddr', () => { beforeEach(() => { transport = tcp()() upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) }) diff --git a/packages/transport-tcp/test/listen-dial.spec.ts b/packages/transport-tcp/test/listen-dial.spec.ts index a2988bce77..4c7f608350 100644 --- a/packages/transport-tcp/test/listen-dial.spec.ts +++ b/packages/transport-tcp/test/listen-dial.spec.ts @@ -1,6 +1,6 @@ import os from 'os' import path from 'path' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockRegistrar, mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -22,7 +22,7 @@ describe('listen', () => { beforeEach(() => { transport = tcp()() upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) }) @@ -175,7 +175,7 @@ describe('dial', () => { }) upgrader = mockUpgrader({ registrar, - events: new EventEmitter() + events: new TypedEventEmitter() }) transport = tcp()() diff --git a/packages/transport-tcp/test/max-connections.spec.ts b/packages/transport-tcp/test/max-connections.spec.ts index 13d18d0c14..495a23e991 100644 --- a/packages/transport-tcp/test/max-connections.spec.ts +++ b/packages/transport-tcp/test/max-connections.spec.ts @@ -1,6 +1,6 @@ import net from 'node:net' import { promisify } from 'node:util' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -22,7 +22,7 @@ describe('maxConnections', () => { const transport = tcp({ maxConnections })() const upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) const listener = transport.createListener({ upgrader }) // eslint-disable-next-line @typescript-eslint/promise-function-async diff --git a/packages/transport-webrtc/CHANGELOG.md b/packages/transport-webrtc/CHANGELOG.md index ca190b424c..bfd78218c6 100644 --- a/packages/transport-webrtc/CHANGELOG.md +++ b/packages/transport-webrtc/CHANGELOG.md @@ -5,6 +5,38 @@ * add browser-to-browser test for bi-directional communication ([#172](https://github.com/libp2p/js-libp2p-webrtc/issues/172)) ([1ec3d8a](https://github.com/libp2p/js-libp2p-webrtc/commit/1ec3d8a8b611d5227f430037e2547fd86d115eaa)) +### [3.2.5](https://www.github.com/libp2p/js-libp2p/compare/webrtc-v3.2.4...webrtc-v3.2.5) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/interface-internal bumped from ^0.1.6 to ^0.1.7 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + * @libp2p/websockets bumped from ^7.0.9 to ^7.0.10 + * libp2p bumped from ^0.46.15 to ^0.46.16 + +### [3.2.4](https://www.github.com/libp2p/js-libp2p/compare/webrtc-v3.2.3...webrtc-v3.2.4) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * libp2p bumped from ^0.46.14 to ^0.46.15 + ### [3.2.3](https://www.github.com/libp2p/js-libp2p/compare/webrtc-v3.2.2...webrtc-v3.2.3) (2023-10-10) @@ -495,4 +527,4 @@ ### Documentation -* fix 'browser to server' build config ([#66](https://github.com/libp2p/js-libp2p-webrtc/issues/66)) ([b54132c](https://github.com/libp2p/js-libp2p-webrtc/commit/b54132cecac180f0577a1b7905f79b20207c3647)) +* fix 'browser to server' build config ([#66](https://github.com/libp2p/js-libp2p-webrtc/issues/66)) ([b54132c](https://github.com/libp2p/js-libp2p-webrtc/commit/b54132cecac180f0577a1b7905f79b20207c3647)) \ No newline at end of file diff --git a/packages/transport-webrtc/README.md b/packages/transport-webrtc/README.md index 6b13043a49..c196f307fc 100644 --- a/packages/transport-webrtc/README.md +++ b/packages/transport-webrtc/README.md @@ -1,5 +1,3 @@ -# @libp2p/webrtc - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,41 +5,11 @@ > A libp2p transport using WebRTC connections -## Table of contents - -- [Install](#install) - - [Browser ` -``` - -## Usage +## Example ```js import { createLibp2p } from 'libp2p' @@ -55,7 +23,7 @@ import { webRTC } from '@libp2p/webrtc' const node = await createLibp2p({ transports: [webRTC()], connectionEncryption: [noise()], -}); +}) await node.start() @@ -66,123 +34,31 @@ const response = await pipe([fromString(message)], stream, async (source) => awa const responseDecoded = toString(response.slice(0, response.length)) ``` -## Examples - -Examples can be found in the [examples folder](examples/README.md). - -## Interfaces - -### Transport - -![https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-transport](https://raw.githubusercontent.com/libp2p/js-libp2p-interfaces/master/packages/interface-transport/img/badge.png) - -Browsers can usually only `dial`, but `listen` is supported in the WebRTC -transport when paired with another listener like CircuitV2, where you listen on -a relayed connection. Take a look at [index.js](examples/browser-to-browser/index.js) for -an example. - -### Connection - -![https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-connection](https://raw.githubusercontent.com/libp2p/js-libp2p-interfaces/master/packages/interface-connection/img/badge.png) - -```js -interface MultiaddrConnection extends Duplex { - close: (err?: Error) => Promise - remoteAddr: Multiaddr - timeline: MultiaddrConnectionTimeline -} - -class WebRTCMultiaddrConnection implements MultiaddrConnection { } -``` - -## Development - -Contributions are welcome! The libp2p implementation in JavaScript is a work in progress. As such, there's a few things you can do right now to help out: - -- [Check out the existing issues](//github.com/little-bear-labs/js-libp2p-webrtc/issues). -- **Perform code reviews**. -- **Add tests**. There can never be enough tests. -- Go through the modules and **check out existing issues**. This is especially useful for modules in active development. Some knowledge of IPFS/libp2p may be required, as well as the infrastructure behind it - for instance, you may need to read up on p2p and more complex operations like muxing to be able to help technically. - -Please be aware that all interactions related to libp2p are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md). - -Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification. - -This module leans heavily on (Aegir)\[] for most of the `package.json` scripts. - -### Build +# Install -The build script is a wrapper to `aegir build`. To build this package: - -```shell -npm run build -``` - -The build will be located in the `/dist` folder. - -### Protocol Buffers - -There is also `npm run generate:proto` script that uses protoc to populate the generated code directory `proto_ts` based on `*.proto` files in src. Don't forget to run this step before `build` any time you make a change to any of the `*.proto` files. - -### Test - -To run all tests: - -```shell -npm test -``` - -To run tests for Chrome only: - -```shell -npm run test:chrome -``` - -To run tests for Firefox only: - -```shell -npm run test:firefox -``` - -### Lint - -Aegir is also used to lint the code, which follows the [Standard](https://github.com/standard/standard) JS linter. -The VS Code plugin for this standard is located at . -To lint this repo: - -```shell -npm run lint -``` - -You can also auto-fix when applicable: - -```shell -npm run lint:fix +```console +$ npm i @libp2p/webrtc ``` -### Clean - -```shell -npm run clean -``` +## Browser ` ``` -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/transport-webrtc/package.json b/packages/transport-webrtc/package.json index 21254dbdea..2d55c579a6 100644 --- a/packages/transport-webrtc/package.json +++ b/packages/transport-webrtc/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/webrtc", - "version": "3.2.3", + "version": "3.2.5", "description": "A libp2p transport using WebRTC connections", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/transport-webrtc#readme", @@ -46,10 +46,10 @@ }, "dependencies": { "@chainsafe/libp2p-noise": "^13.0.0", - "@libp2p/interface": "^0.1.3", - "@libp2p/interface-internal": "^0.1.6", - "@libp2p/logger": "^3.0.3", - "@libp2p/peer-id": "^3.0.3", + "@libp2p/interface": "^0.1.4", + "@libp2p/interface-internal": "^0.1.7", + "@libp2p/logger": "^3.0.4", + "@libp2p/peer-id": "^3.0.4", "@multiformats/mafmt": "^12.1.2", "@multiformats/multiaddr": "^12.1.5", "@multiformats/multiaddr-matcher": "^1.0.1", @@ -75,9 +75,9 @@ }, "devDependencies": { "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/interface-compliance-tests": "^4.1.1", - "@libp2p/peer-id-factory": "^3.0.5", - "@libp2p/websockets": "^7.0.9", + "@libp2p/interface-compliance-tests": "^4.1.2", + "@libp2p/peer-id-factory": "^3.0.6", + "@libp2p/websockets": "^7.0.10", "@types/sinon": "^10.0.15", "aegir": "^41.0.2", "delay": "^6.0.0", @@ -85,11 +85,11 @@ "it-length": "^3.0.2", "it-map": "^3.0.3", "it-pair": "^2.0.6", - "libp2p": "^0.46.14", + "libp2p": "^0.46.16", "p-retry": "^6.1.0", "protons": "^7.0.2", - "sinon": "^16.0.0", - "sinon-ts": "^1.0.0" + "sinon": "^17.0.0", + "sinon-ts": "^2.0.0" }, "browser": { "./dist/src/webrtc/index.js": "./dist/src/webrtc/index.browser.js" diff --git a/packages/transport-webrtc/src/index.ts b/packages/transport-webrtc/src/index.ts index a8bbf37e75..6e27a5da6d 100644 --- a/packages/transport-webrtc/src/index.ts +++ b/packages/transport-webrtc/src/index.ts @@ -1,3 +1,34 @@ +/** + * @packageDocumentation + * + * A [libp2p transport](https://docs.libp2p.io/concepts/transports/overview/) based on [WebRTC datachannels](https://webrtc.org/). + * + * @example + * + * ```js + * import { createLibp2p } from 'libp2p' + * import { noise } from '@chainsafe/libp2p-noise' + * import { multiaddr } from '@multiformats/multiaddr' + * import first from 'it-first' + * import { pipe } from 'it-pipe' + * import { fromString, toString } from 'uint8arrays' + * import { webRTC } from '@libp2p/webrtc' + * + * const node = await createLibp2p({ + * transports: [webRTC()], + * connectionEncryption: [noise()], + * }) + * + * await node.start() + * + * const ma = multiaddr('/ip4/0.0.0.0/udp/56093/webrtc/certhash/uEiByaEfNSLBexWBNFZy_QB1vAKEj7JAXDizRs4_SnTflsQ') + * const stream = await node.dialProtocol(ma, ['/my-protocol/1.0.0']) + * const message = `Hello js-libp2p-webrtc\n` + * const response = await pipe([fromString(message)], stream, async (source) => await first(source)) + * const responseDecoded = toString(response.slice(0, response.length)) + * ``` + */ + import { WebRTCTransport } from './private-to-private/transport.js' import { WebRTCDirectTransport, type WebRTCTransportDirectInit, type WebRTCDirectTransportComponents } from './private-to-public/transport.js' import type { WebRTCTransportComponents, WebRTCTransportInit } from './private-to-private/transport.js' diff --git a/packages/transport-webrtc/src/private-to-private/listener.ts b/packages/transport-webrtc/src/private-to-private/listener.ts index 53a3d299c6..6a73e9e14a 100644 --- a/packages/transport-webrtc/src/private-to-private/listener.ts +++ b/packages/transport-webrtc/src/private-to-private/listener.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { Circuit } from '@multiformats/mafmt' import type { PeerId } from '@libp2p/interface/peer-id' import type { ListenerEvents, Listener } from '@libp2p/interface/transport' @@ -14,7 +14,7 @@ export interface WebRTCPeerListenerInit { shutdownController: AbortController } -export class WebRTCPeerListener extends EventEmitter implements Listener { +export class WebRTCPeerListener extends TypedEventEmitter implements Listener { private readonly peerId: PeerId private readonly transportManager: TransportManager private readonly shutdownController: AbortController diff --git a/packages/transport-webrtc/test/listener.spec.ts b/packages/transport-webrtc/test/listener.spec.ts index 036e727d7c..7280feadc3 100644 --- a/packages/transport-webrtc/test/listener.spec.ts +++ b/packages/transport-webrtc/test/listener.spec.ts @@ -1,6 +1,7 @@ import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' +import Sinon from 'sinon' import { stubInterface } from 'sinon-ts' import { WebRTCPeerListener } from '../src/private-to-private/listener.js' import type { Listener } from '@libp2p/interface/transport' @@ -21,11 +22,11 @@ describe('webrtc private-to-private listener', () => { }) const otherListener = stubInterface({ - getAddrs: [multiaddr(otherListenAddress)] + getAddrs: Sinon.stub().returns([multiaddr(otherListenAddress)]) }) const relayListener = stubInterface({ - getAddrs: [multiaddr(relayedAddress)] + getAddrs: Sinon.stub().returns([multiaddr(relayedAddress)]) }) transportManager.getListeners.returns([ diff --git a/packages/transport-websockets/.aegir.js b/packages/transport-websockets/.aegir.js index 1a81ef61be..d7e24c7d10 100644 --- a/packages/transport-websockets/.aegir.js +++ b/packages/transport-websockets/.aegir.js @@ -6,7 +6,7 @@ export default { async before () { const { multiaddr } = await import('@multiformats/multiaddr') const { mockRegistrar, mockUpgrader } = await import('@libp2p/interface-compliance-tests/mocks') - const { EventEmitter } = await import('@libp2p/interface/events') + const { TypedEventEmitter } = await import('@libp2p/interface/events') const { webSockets } = await import('./dist/src/index.js') const protocol = '/echo/1.0.0' @@ -19,7 +19,7 @@ export default { }) const upgrader = mockUpgrader({ registrar, - events: new EventEmitter() + events: new TypedEventEmitter() }) const ws = webSockets()() diff --git a/packages/transport-websockets/CHANGELOG.md b/packages/transport-websockets/CHANGELOG.md index 96384c9937..90d05f6a1c 100644 --- a/packages/transport-websockets/CHANGELOG.md +++ b/packages/transport-websockets/CHANGELOG.md @@ -6,6 +6,25 @@ * **dev:** bump @libp2p/interface-mocks from 11.0.3 to 12.0.1 ([#241](https://github.com/libp2p/js-libp2p-websockets/issues/241)) ([f956836](https://github.com/libp2p/js-libp2p-websockets/commit/f95683641bda2f9b250768768451e0c121afc2a0)) * **dev:** bump aegir from 38.1.8 to 39.0.9 ([#245](https://github.com/libp2p/js-libp2p-websockets/issues/245)) ([4a35f6b](https://github.com/libp2p/js-libp2p-websockets/commit/4a35f6b39a918fb7ef779292553cb452a543afb0)) +### [7.0.10](https://www.github.com/libp2p/js-libp2p/compare/websockets-v7.0.9...websockets-v7.0.10) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/utils bumped from ^4.0.4 to ^4.0.5 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + ### [7.0.9](https://www.github.com/libp2p/js-libp2p/compare/websockets-v7.0.8...websockets-v7.0.9) (2023-10-06) diff --git a/packages/transport-websockets/README.md b/packages/transport-websockets/README.md index 79d7aee6ea..7f61346cbb 100644 --- a/packages/transport-websockets/README.md +++ b/packages/transport-websockets/README.md @@ -1,5 +1,3 @@ -# @libp2p/websockets - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,27 +5,13 @@ > JavaScript implementation of the WebSockets module that libp2p uses and that implements the interface-transport spec -## Table of contents - -- [Install](#install) - - [Browser ` ``` -[![](https://raw.githubusercontent.com/libp2p/interface-transport/master/img/badge.png)](https://github.com/libp2p/interface-transport) -[![](https://raw.githubusercontent.com/libp2p/interface-connection/master/img/badge.png)](https://github.com/libp2p/interface-connection) - -## Usage - -```sh -> npm i @libp2p/websockets -``` - -### Constructor properties - -```js -import { createLibp2pNode } from 'libp2p' -import { webSockets } from '@libp2p/webrtc-direct' - -const node = await createLibp2p({ - transports: [ - webSockets() - ] - //... other config -}) -await node.start() -await node.dial('/ip4/127.0.0.1/tcp/9090/ws') -``` - -| Name | Type | Description | Default | -| -------- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------ | -| upgrader | [`Upgrader`](https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/transport#upgrader) | connection upgrader object with `upgradeOutbound` and `upgradeInbound` | **REQUIRED** | -| filter | `(multiaddrs: Array) => Array` | override transport addresses filter | **Browser:** DNS+WSS multiaddrs / **Node.js:** DNS+\[WS, WSS] multiaddrs | - -You can create your own address filters for this transports, or rely in the filters [provided](./src/filters.js). - -The available filters are: - -- `filters.all` - - Returns all TCP and DNS based addresses, both with `ws` or `wss`. -- `filters.dnsWss` - - Returns all DNS based addresses with `wss`. -- `filters.dnsWsOrWss` - - Returns all DNS based addresses, both with `ws` or `wss`. - -## Libp2p Usage Example - -```js -import { createLibp2pNode } from 'libp2p' -import { websockets } from '@libp2p/websockets' -import filters from '@libp2p/websockets/filters' -import { mplex } from '@libp2p/mplex' -import { noise } from '@libp2p/noise' - -const transportKey = Websockets.prototype[Symbol.toStringTag] -const node = await Libp2p.create({ - transport: [ - websockets({ - // connect to all sockets, even insecure ones - filter: filters.all - }) - ], - streamMuxers: [ - mplex() - ], - connectionEncryption: [ - noise() - ] -}) -``` - -For more information see [libp2p/js-libp2p/doc/CONFIGURATION.md#customizing-transports](https://github.com/libp2p/js-libp2p/blob/master/doc/CONFIGURATION.md#customizing-transports). - -## API - -### Transport - -[![](https://raw.githubusercontent.com/libp2p/interface-transport/master/img/badge.png)](https://github.com/libp2p/interface-transport) - -### Connection - -[![](https://raw.githubusercontent.com/libp2p/interface-connection/master/img/badge.png)](https://github.com/libp2p/interface-connection) - -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/transport-websockets/package.json b/packages/transport-websockets/package.json index df58354214..a6b4fdfdfe 100644 --- a/packages/transport-websockets/package.json +++ b/packages/transport-websockets/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/websockets", - "version": "7.0.9", + "version": "7.0.10", "description": "JavaScript implementation of the WebSockets module that libp2p uses and that implements the interface-transport spec", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/transport-websockets#readme", @@ -69,9 +69,9 @@ "test:electron-main": "aegir test -t electron-main -f ./dist/test/node.js --cov" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", - "@libp2p/utils": "^4.0.4", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", + "@libp2p/utils": "^4.0.5", "@multiformats/mafmt": "^12.1.2", "@multiformats/multiaddr": "^12.1.5", "@multiformats/multiaddr-to-uri": "^9.0.2", @@ -83,7 +83,7 @@ "ws": "^8.12.1" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^4.1.1", + "@libp2p/interface-compliance-tests": "^4.1.2", "aegir": "^41.0.2", "is-loopback-addr": "^2.0.1", "it-all": "^3.0.1", diff --git a/packages/transport-websockets/src/index.ts b/packages/transport-websockets/src/index.ts index 932b1a042e..09dbec822e 100644 --- a/packages/transport-websockets/src/index.ts +++ b/packages/transport-websockets/src/index.ts @@ -1,3 +1,68 @@ +/** + * @packageDocumentation + * + * A [libp2p transport](https://docs.libp2p.io/concepts/transports/overview/) based on [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API). + * + * @example + * + * ```js + * import { createLibp2pNode } from 'libp2p' + * import { webSockets } from '@libp2p/webrtc-direct' + * + * const node = await createLibp2p({ + * transports: [ + * webSockets() + * ] + * //... other config + * }) + * await node.start() + * await node.dial('/ip4/127.0.0.1/tcp/9090/ws') + * ``` + * + * ## Filters + * + * When run in a browser by default this module will only connect to secure web socket addresses. + * + * To change this you should pass a filter to the factory function. + * + * You can create your own address filters for this transports, or rely in the filters [provided](./src/filters.js). + * + * The available filters are: + * + * - `filters.all` + * - Returns all TCP and DNS based addresses, both with `ws` or `wss`. + * - `filters.dnsWss` + * - Returns all DNS based addresses with `wss`. + * - `filters.dnsWsOrWss` + * - Returns all DNS based addresses, both with `ws` or `wss`. + * + * @example + * + * ```js + * import { createLibp2pNode } from 'libp2p' + * import { websockets } from '@libp2p/websockets' + * import filters from '@libp2p/websockets/filters' + * import { mplex } from '@libp2p/mplex' + * import { noise } from '@libp2p/noise' + * + * const transportKey = Websockets.prototype[Symbol.toStringTag] + * const node = await Libp2p.create({ + * transport: [ + * websockets({ + * // connect to all sockets, even insecure ones + * filter: filters.all + * }) + * ], + * streamMuxers: [ + * mplex() + * ], + * connectionEncryption: [ + * noise() + * ] + * }) + * ``` + */ + import { AbortError, CodeError } from '@libp2p/interface/errors' import { type Transport, type MultiaddrFilter, symbol, type CreateListenerOptions, type DialOptions, type Listener } from '@libp2p/interface/transport' import { logger } from '@libp2p/logger' diff --git a/packages/transport-websockets/src/listener.ts b/packages/transport-websockets/src/listener.ts index 9adb5957ae..6f307c0ecb 100644 --- a/packages/transport-websockets/src/listener.ts +++ b/packages/transport-websockets/src/listener.ts @@ -1,5 +1,5 @@ import os from 'os' -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { ipPortToMultiaddr as toMultiaddr } from '@libp2p/utils/ip-port-to-multiaddr' import { multiaddr, protocols } from '@multiformats/multiaddr' @@ -14,7 +14,7 @@ import type { WebSocketServer } from 'it-ws/server' const log = logger('libp2p:websockets:listener') -class WebSocketListener extends EventEmitter implements Listener { +class WebSocketListener extends TypedEventEmitter implements Listener { private readonly connections: Set private listeningMultiaddr?: Multiaddr private readonly server: WebSocketServer diff --git a/packages/transport-websockets/test/browser.ts b/packages/transport-websockets/test/browser.ts index 616f09e37e..88e311c67c 100644 --- a/packages/transport-websockets/test/browser.ts +++ b/packages/transport-websockets/test/browser.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -23,7 +23,7 @@ describe('libp2p-websockets', () => { ws = webSockets()() conn = await ws.dial(ma, { upgrader: mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) }) }) diff --git a/packages/transport-websockets/test/node.ts b/packages/transport-websockets/test/node.ts index 32aa1b02ae..8c296900ce 100644 --- a/packages/transport-websockets/test/node.ts +++ b/packages/transport-websockets/test/node.ts @@ -4,7 +4,7 @@ import fs from 'fs' import http from 'http' import https from 'https' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockRegistrar, mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -41,7 +41,7 @@ void registrar.handle(protocol, (evt) => { }) const upgrader = mockUpgrader({ registrar, - events: new EventEmitter() + events: new TypedEventEmitter() }) describe('instantiate the transport', () => { diff --git a/packages/transport-webtransport/CHANGELOG.md b/packages/transport-webtransport/CHANGELOG.md index 84afa61866..59be4b9991 100644 --- a/packages/transport-webtransport/CHANGELOG.md +++ b/packages/transport-webtransport/CHANGELOG.md @@ -11,6 +11,29 @@ * bump @chainsafe/libp2p-noise from 11.0.4 to 12.0.1 ([#80](https://github.com/libp2p/js-libp2p-webtransport/issues/80)) ([599dab1](https://github.com/libp2p/js-libp2p-webtransport/commit/599dab1b4f6ae816b0c0feefc926c1b38d24b676)) +### [3.1.5](https://www.github.com/libp2p/js-libp2p/compare/webtransport-v3.1.4...webtransport-v3.1.5) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * devDependencies + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + * libp2p bumped from ^0.46.15 to ^0.46.16 + +### [3.1.4](https://www.github.com/libp2p/js-libp2p/compare/webtransport-v3.1.3...webtransport-v3.1.4) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * libp2p bumped from ^0.46.14 to ^0.46.15 + ### [3.1.3](https://www.github.com/libp2p/js-libp2p/compare/webtransport-v3.1.2...webtransport-v3.1.3) (2023-10-10) diff --git a/packages/transport-webtransport/README.md b/packages/transport-webtransport/README.md index b5bb4e72d0..f3338b7948 100644 --- a/packages/transport-webtransport/README.md +++ b/packages/transport-webtransport/README.md @@ -1,5 +1,3 @@ -# @libp2p/webtransport - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,48 +5,11 @@ > JavaScript implementation of the WebTransport module that libp2p uses and that implements the interface-transport spec -## Table of contents - -- [Install](#install) - - [Browser ` -``` - -[![](https://raw.githubusercontent.com/libp2p/interface-transport/master/img/badge.png)](https://github.com/libp2p/interface-transport) -[![](https://raw.githubusercontent.com/libp2p/interface-connection/master/img/badge.png)](https://github.com/libp2p/interface-connection) - -## Description +# About -`libp2p-webtransport` is the WebTransport transport implementation compatible with libp2p. +A [libp2p transport](https://docs.libp2p.io/concepts/transports/overview/) based on [WebTransport](https://www.w3.org/TR/webtransport/). -## Usage - -```sh -> npm i @libp2p/webtransport -``` - -## Libp2p Usage Example +## Example ```js import { createLibp2pNode } from 'libp2p' @@ -65,30 +26,34 @@ const node = await createLibp2pNode({ }) ``` -For more information see [libp2p/js-libp2p/doc/CONFIGURATION.md#customizing-transports](https://github.com/libp2p/js-libp2p/blob/master/doc/CONFIGURATION.md#customizing-transports). +# Install -## API +```console +$ npm i @libp2p/webtransport +``` -### Transport +## Browser ` +``` -[![](https://raw.githubusercontent.com/libp2p/interface-connection/master/img/badge.png)](https://github.com/libp2p/interface-connection) +For more information see [libp2p/js-libp2p/doc/CONFIGURATION.md#customizing-transports](https://github.com/libp2p/js-libp2p/blob/master/doc/CONFIGURATION.md#customizing-transports). -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/transport-webtransport/go-libp2p-webtransport-server/go.mod b/packages/transport-webtransport/go-libp2p-webtransport-server/go.mod index 311a59911f..a78490047f 100644 --- a/packages/transport-webtransport/go-libp2p-webtransport-server/go.mod +++ b/packages/transport-webtransport/go-libp2p-webtransport-server/go.mod @@ -81,13 +81,13 @@ require ( go.uber.org/fx v1.19.2 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.24.0 // indirect - golang.org/x/crypto v0.7.0 // indirect + golang.org/x/crypto v0.14.0 // indirect golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect golang.org/x/mod v0.10.0 // indirect - golang.org/x/net v0.8.0 // indirect + golang.org/x/net v0.17.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.7.0 // indirect - golang.org/x/text v0.8.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect golang.org/x/tools v0.7.0 // indirect google.golang.org/protobuf v1.30.0 // indirect lukechampine.com/blake3 v1.1.7 // indirect diff --git a/packages/transport-webtransport/go-libp2p-webtransport-server/go.sum b/packages/transport-webtransport/go-libp2p-webtransport-server/go.sum index 2ad1bc14c9..fae4ef6754 100644 --- a/packages/transport-webtransport/go-libp2p-webtransport-server/go.sum +++ b/packages/transport-webtransport/go-libp2p-webtransport-server/go.sum @@ -355,8 +355,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= @@ -388,8 +388,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -426,15 +426,15 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/packages/transport-webtransport/package.json b/packages/transport-webtransport/package.json index e0442f0712..4cab63776a 100644 --- a/packages/transport-webtransport/package.json +++ b/packages/transport-webtransport/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/webtransport", - "version": "3.1.3", + "version": "3.1.5", "description": "JavaScript implementation of the WebTransport module that libp2p uses and that implements the interface-transport spec", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/transport-webtransport#readme", @@ -62,9 +62,9 @@ }, "dependencies": { "@chainsafe/libp2p-noise": "^13.0.0", - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", - "@libp2p/peer-id": "^3.0.3", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", + "@libp2p/peer-id": "^3.0.4", "@multiformats/multiaddr": "^12.1.5", "@multiformats/multiaddr-matcher": "^1.0.1", "it-stream-types": "^2.0.1", @@ -73,9 +73,9 @@ "uint8arrays": "^4.0.6" }, "devDependencies": { - "@libp2p/peer-id-factory": "^3.0.5", + "@libp2p/peer-id-factory": "^3.0.6", "aegir": "^41.0.2", - "libp2p": "^0.46.14", + "libp2p": "^0.46.16", "p-defer": "^4.0.0" }, "browser": { diff --git a/packages/transport-webtransport/src/index.ts b/packages/transport-webtransport/src/index.ts index d37e5a6564..33b272fee6 100644 --- a/packages/transport-webtransport/src/index.ts +++ b/packages/transport-webtransport/src/index.ts @@ -1,3 +1,26 @@ +/** + * @packageDocumentation + * + * A [libp2p transport](https://docs.libp2p.io/concepts/transports/overview/) based on [WebTransport](https://www.w3.org/TR/webtransport/). + * + * @example + * + * ```js + * import { createLibp2pNode } from 'libp2p' + * import { webTransport } from '@libp2p/webtransport' + * import { noise } from 'libp2p-noise' + * + * const node = await createLibp2pNode({ + * transports: [ + * webTransport() + * ], + * connectionEncryption: [ + * noise() + * ] + * }) + * ``` + */ + import { noise } from '@chainsafe/libp2p-noise' import { type Transport, symbol, type CreateListenerOptions, type DialOptions, type Listener } from '@libp2p/interface/transport' import { logger } from '@libp2p/logger' diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md index b432d16d92..c9b606a8f8 100644 --- a/packages/utils/CHANGELOG.md +++ b/packages/utils/CHANGELOG.md @@ -11,6 +11,16 @@ * **dev:** bump aegir from 38.1.8 to 39.0.10 ([#100](https://github.com/libp2p/js-libp2p-utils/issues/100)) ([da6547c](https://github.com/libp2p/js-libp2p-utils/commit/da6547cdd073ba1a4225be5a419c6776c4ebe6f1)) +### [4.0.5](https://www.github.com/libp2p/js-libp2p/compare/utils-v4.0.4...utils-v4.0.5) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + ### [4.0.4](https://www.github.com/libp2p/js-libp2p/compare/utils-v4.0.3...utils-v4.0.4) (2023-10-06) diff --git a/packages/utils/README.md b/packages/utils/README.md index 4fbd0f1a5f..a8be91fe20 100644 --- a/packages/utils/README.md +++ b/packages/utils/README.md @@ -1,5 +1,3 @@ -# @libp2p/utils - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,22 +5,13 @@ > Package to aggregate shared logic and dependencies for the libp2p ecosystem -## Table of contents - -- [Install](#install) - - [Browser ` ``` -The libp2p ecosystem has lots of repos with it comes several problems like: - -- Domain logic dedupe - all modules shared a lot of logic like validation, streams handling, etc. -- Dependencies management - it's really easy with so many repos for dependencies to go out of control, they become outdated, different repos use different modules to do the same thing (like merging defaults options), browser bundles ends up with multiple versions of the same package, bumping versions is cumbersome to do because we need to go through several repos, etc. - -These problems are the motivation for this package, having shared logic in this package avoids creating cyclic dependencies, centralizes common use modules/functions (exactly like aegir does for the tooling), semantic versioning for 3rd party dependencies is handled in one single place (a good example is going from streams 2 to 3) and maintainers should only care about having `libp2p-utils` updated. - -## Usage - -Each function should be imported directly. - -```js -import ipAndPortToMultiaddr from '@libp2p/utils/ip-port-to-multiaddr' - -const ma = ipAndPortToMultiaddr('127.0.0.1', 9000) -``` - -You can check the [API docs](https://libp2p.github.io/js-libp2p-utils). - -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/utils/package.json b/packages/utils/package.json index 89b6c0f7e5..07b12e9467 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/utils", - "version": "4.0.4", + "version": "4.0.5", "description": "Package to aggregate shared logic and dependencies for the libp2p ecosystem", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/utils#readme", @@ -87,8 +87,8 @@ }, "dependencies": { "@chainsafe/is-ip": "^2.0.2", - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", "@multiformats/multiaddr": "^12.1.5", "@multiformats/multiaddr-matcher": "^1.0.1", "is-loopback-addr": "^2.0.1", diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 336ce12bb9..cd0c2aa243 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -1 +1,22 @@ +/** + * @packageDocumentation + * + * The libp2p ecosystem has lots of repos with it comes several problems like: + * + * - Domain logic dedupe - all modules shared a lot of logic like validation, streams handling, etc. + * - Dependencies management - it's really easy with so many repos for dependencies to go out of control, they become outdated, different repos use different modules to do the same thing (like merging defaults options), browser bundles ends up with multiple versions of the same package, bumping versions is cumbersome to do because we need to go through several repos, etc. + * + * These problems are the motivation for this package, having shared logic in this package avoids creating cyclic dependencies, centralizes common use modules/functions (exactly like aegir does for the tooling), semantic versioning for 3rd party dependencies is handled in one single place (a good example is going from streams 2 to 3) and maintainers should only care about having `libp2p-utils` updated. + * + * @example + * + * Each function should be imported directly. + * + * ```js + * import ipAndPortToMultiaddr from '@libp2p/utils/ip-port-to-multiaddr' + * + * const ma = ipAndPortToMultiaddr('127.0.0.1', 9000) + * ``` + */ + export {} diff --git a/typedoc.json b/typedoc.json index 55b1f87a5f..ecae64aac9 100644 --- a/typedoc.json +++ b/typedoc.json @@ -1,4 +1,8 @@ { "$schema": "https://typedoc.org/schema.json", - "name": "libp2p" + "name": "libp2p", + "exclude": [ + "interop", + "doc" + ] }