-
Notifications
You must be signed in to change notification settings - Fork 504
chore: auto relay example #795
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
43b7afa
2bd1a2f
a09ac4a
5623449
05bdb1f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,192 @@ | ||||||||||||||||
| # Auto relay | ||||||||||||||||
|
|
||||||||||||||||
| Auto Relay enables libp2p nodes to dynamically find and bind to relays on the network. Once binding (listening) is done, the node can and should advertise its addresses on the network, allowing any other node to dial it over its bound relay(s). | ||||||||||||||||
| While direct connections to nodes are preferable, it's not always possible to do so due to NATs or browser limitations. | ||||||||||||||||
|
|
||||||||||||||||
| ## 0. Setup the example | ||||||||||||||||
|
|
||||||||||||||||
| Before moving into the examples, you should run `npm install` on the top level `js-libp2p` folder, in order to install all the dependencies needed for this example. | ||||||||||||||||
|
|
||||||||||||||||
| This example comes with 3 main files. A `relay.js` file to be used in the first step, a `auto-relay.js` file to be used in the second step and a `other-node.js` file to be used on the third step. All of this scripts will run their own libp2p node, which will interact with the previous ones. This way, you need to have all of them running as you proceed. | ||||||||||||||||
vasco-santos marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||
|
|
||||||||||||||||
| ## 1. Set up a relay node | ||||||||||||||||
|
|
||||||||||||||||
| Aiming to support nodes with connectivity issues, you will need to set up a relay node for the former nodes to bind. | ||||||||||||||||
vasco-santos marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||
|
|
||||||||||||||||
| The relay node will need to have its relay subsystem enabled, as well as its HOP capability. It can be configured as follows: | ||||||||||||||||
|
|
||||||||||||||||
| ```js | ||||||||||||||||
| const Libp2p = require('libp2p') | ||||||||||||||||
| const Websockets = require('libp2p-websockets') | ||||||||||||||||
| const { NOISE } = require('libp2p-noise') | ||||||||||||||||
| const MPLEX = require('libp2p-mplex') | ||||||||||||||||
|
|
||||||||||||||||
| const node = await Libp2p.create({ | ||||||||||||||||
| modules: { | ||||||||||||||||
| transport: [Websockets], | ||||||||||||||||
| connEncryption: [NOISE], | ||||||||||||||||
| streamMuxer: [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'] | ||||||||||||||||
| // announceFilter: (addresses) => addresses | ||||||||||||||||
| }, | ||||||||||||||||
| config: { | ||||||||||||||||
| relay: { | ||||||||||||||||
| enabled: true, | ||||||||||||||||
| hop: { | ||||||||||||||||
| enabled: true | ||||||||||||||||
| }, | ||||||||||||||||
| advertise: { | ||||||||||||||||
| enabled: true, | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| }) | ||||||||||||||||
|
|
||||||||||||||||
| await node.start() | ||||||||||||||||
|
|
||||||||||||||||
| console.log(`Node started: ${node.peerId.toB58String()}`) | ||||||||||||||||
| console.log('Listening on:') | ||||||||||||||||
| node.multiaddrs.forEach((ma) => console.log(`${ma.toString()}/p2p/${node.peerId.toB58String()}`)) | ||||||||||||||||
| ``` | ||||||||||||||||
|
|
||||||||||||||||
| 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. | ||||||||||||||||
|
||||||||||||||||
|
|
||||||||||||||||
| You should now run the following to start the relay node: | ||||||||||||||||
|
|
||||||||||||||||
| ```sh | ||||||||||||||||
| node relay.js | ||||||||||||||||
jacobheun marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
| ``` | ||||||||||||||||
|
|
||||||||||||||||
| This should print out something similar to the following: | ||||||||||||||||
|
|
||||||||||||||||
| ```sh | ||||||||||||||||
| Node started: QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3 | ||||||||||||||||
| Listening on: | ||||||||||||||||
| /ip4/127.0.0.1/tcp/61592/ws/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3 | ||||||||||||||||
| /ip4/192.168.1.120/tcp/61592/ws/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3 | ||||||||||||||||
| ``` | ||||||||||||||||
|
|
||||||||||||||||
| TODO: Docker Image with a repo | ||||||||||||||||
|
||||||||||||||||
|
|
||||||||||||||||
| ## 2. Set up a node with Auto Relay Enabled | ||||||||||||||||
|
|
||||||||||||||||
| One of the typical use cases for Auto Relay is nodes behind a NAT or browser nodes thanks to their limitations regarding listening for new connections. For running a libp2p node that automatically binds itself to connected HOP relays, you can see the following: | ||||||||||||||||
vasco-santos marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||
|
|
||||||||||||||||
| ```js | ||||||||||||||||
| const Libp2p = require('libp2p') | ||||||||||||||||
| const Websockets = require('libp2p-websockets') | ||||||||||||||||
| const { NOISE } = require('libp2p-noise') | ||||||||||||||||
| const MPLEX = require('libp2p-mplex') | ||||||||||||||||
|
|
||||||||||||||||
| const pWaitFor = require('p-wait-for') | ||||||||||||||||
|
|
||||||||||||||||
| const relayAddr = process.argv[2] | ||||||||||||||||
| if (!relayAddr) { | ||||||||||||||||
| throw new Error('the relay address needs to be specified as a parameter') | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| const node = await Libp2p.create({ | ||||||||||||||||
| modules: { | ||||||||||||||||
| transport: [Websockets], | ||||||||||||||||
| connEncryption: [NOISE], | ||||||||||||||||
| streamMuxer: [MPLEX] | ||||||||||||||||
| }, | ||||||||||||||||
| config: { | ||||||||||||||||
| relay: { | ||||||||||||||||
| enabled: true, | ||||||||||||||||
| autoRelay: { | ||||||||||||||||
| enabled: true, | ||||||||||||||||
| maxListeners: 2 | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| }) | ||||||||||||||||
|
|
||||||||||||||||
| await node.start() | ||||||||||||||||
| console.log(`Node started: ${node.peerId.toB58String()}`) | ||||||||||||||||
|
|
||||||||||||||||
| await node.dial(relayAddr) | ||||||||||||||||
|
|
||||||||||||||||
| // Wait for connection and relay to be bind for the example purpose | ||||||||||||||||
vasco-santos marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
| await pWaitFor(() => node.multiaddrs.length > 0) | ||||||||||||||||
|
|
||||||||||||||||
| console.log('connected to the HOP relay') | ||||||||||||||||
| console.log('Listening on:') | ||||||||||||||||
| node.multiaddrs.forEach((ma) => console.log(`${ma.toString()}/p2p/${node.peerId.toB58String()}`)) | ||||||||||||||||
| ``` | ||||||||||||||||
|
|
||||||||||||||||
| As you can see in the code, we need to provide the `relayAddr` as a process argument. This node will dial the relay and automatically bind to the relay. | ||||||||||||||||
vasco-santos marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||
|
|
||||||||||||||||
| You should now run the following to start the relay node: | ||||||||||||||||
vasco-santos marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||
|
|
||||||||||||||||
| ```sh | ||||||||||||||||
| node auto-relay.js /ip4/192.168.1.120/tcp/58941/ws/p2p/QmQKCBm87HQMbFqy14oqC85pMmnRrj6iD46ggM6reqNpsd | ||||||||||||||||
| ``` | ||||||||||||||||
|
|
||||||||||||||||
| This should print out something similar to the following: | ||||||||||||||||
|
|
||||||||||||||||
| ```sh | ||||||||||||||||
| Node started: QmerrWofKF358JE6gv3z74cEAyL7z1KqhuUoVfGEynqjRm | ||||||||||||||||
| connected to the HOP relay | ||||||||||||||||
| Listening on: | ||||||||||||||||
| /ip4/192.168.1.120/tcp/61592/ws/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3/p2p-circuit/p2p/QmerrWofKF358JE6gv3z74cEAyL7z1KqhuUoVfGEynqjRm | ||||||||||||||||
|
||||||||||||||||
| Node started: QmerrWofKF358JE6gv3z74cEAyL7z1KqhuUoVfGEynqjRm | |
| connected to the HOP relay | |
| Listening on: | |
| /ip4/192.168.1.120/tcp/61592/ws/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3/p2p-circuit/p2p/QmerrWofKF358JE6gv3z74cEAyL7z1KqhuUoVfGEynqjRm | |
| 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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| 'use strict' | ||
|
|
||
| const Libp2p = require('libp2p') | ||
| const Websockets = require('libp2p-websockets') | ||
| const { NOISE } = require('libp2p-noise') | ||
| const MPLEX = require('libp2p-mplex') | ||
|
|
||
| const pWaitFor = require('p-wait-for') | ||
|
|
||
| const relayAddr = process.argv[2] | ||
| if (!relayAddr) { | ||
| throw new Error('the relay address needs to be specified as a parameter') | ||
| } | ||
|
|
||
| ;(async () => { | ||
| const node = await Libp2p.create({ | ||
| modules: { | ||
| transport: [Websockets], | ||
| connEncryption: [NOISE], | ||
| streamMuxer: [MPLEX] | ||
| }, | ||
| config: { | ||
| relay: { | ||
| enabled: true, | ||
| autoRelay: { | ||
| enabled: true, | ||
| maxListeners: 2 | ||
| } | ||
| } | ||
| } | ||
| }) | ||
|
|
||
| await node.start() | ||
| console.log(`Node started: ${node.peerId.toB58String()}`) | ||
|
|
||
| await node.dial(relayAddr) | ||
|
|
||
| // Wait for connection and relay to be bind for the example purpose | ||
| await pWaitFor(() => node.multiaddrs.length > 0) | ||
|
||
|
|
||
| console.log('connected to the HOP relay') | ||
| console.log('Listening on:') | ||
| node.multiaddrs.forEach((ma) => console.log(`${ma.toString()}/p2p/${node.peerId.toB58String()}`)) | ||
| })() | ||
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| 'use strict' | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of |
||
|
|
||
| const Libp2p = require('libp2p') | ||
| const Websockets = require('libp2p-websockets') | ||
| const { NOISE } = require('libp2p-noise') | ||
| const MPLEX = require('libp2p-mplex') | ||
|
|
||
| const autoRelayNodeAddr = process.argv[2] | ||
| if (!autoRelayNodeAddr) { | ||
| throw new Error('the auto relay node address needs to be specified') | ||
| } | ||
|
|
||
| ;(async () => { | ||
| const node = await Libp2p.create({ | ||
| modules: { | ||
| transport: [Websockets], | ||
| connEncryption: [NOISE], | ||
| streamMuxer: [MPLEX] | ||
| } | ||
| }) | ||
|
|
||
| await node.start() | ||
| console.log(`Node started: ${node.peerId.toB58String()}`) | ||
|
|
||
| const conn = await node.dial(autoRelayNodeAddr) | ||
| console.log(`Connected to the auto relay node via ${conn.remoteAddr.toString()}`) | ||
| })() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| 'use strict' | ||
|
|
||
| const Libp2p = require('libp2p') | ||
| const Websockets = require('libp2p-websockets') | ||
| const { NOISE } = require('libp2p-noise') | ||
| const MPLEX = require('libp2p-mplex') | ||
|
|
||
| ;(async () => { | ||
| const node = await Libp2p.create({ | ||
| modules: { | ||
| transport: [Websockets], | ||
| connEncryption: [NOISE], | ||
| streamMuxer: [MPLEX] | ||
| }, | ||
| addresses: { | ||
| listen: ['/ip4/0.0.0.0/tcp/0/ws'] | ||
| // announceFilter: TODO check production section | ||
|
||
| }, | ||
| config: { | ||
| relay: { | ||
| enabled: true, | ||
| hop: { | ||
| enabled: true | ||
| }, | ||
| advertise: { | ||
| enabled: true, | ||
| } | ||
| } | ||
| } | ||
| }) | ||
|
|
||
| await node.start() | ||
|
|
||
| console.log(`Node started: ${node.peerId.toB58String()}`) | ||
| console.log('Listening on:') | ||
| node.multiaddrs.forEach((ma) => console.log(`${ma.toString()}/p2p/${node.peerId.toB58String()}`)) | ||
| })() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should examples just run on PR? Ideally I think they'd only run on a release but we dont have that flow atm. Running on branches seems excessive.