Skip to content

Commit e89dc34

Browse files
committed
chore: add discovery example with relay and pubsub
1 parent 164acc7 commit e89dc34

File tree

5 files changed

+201
-1
lines changed

5 files changed

+201
-1
lines changed

examples/discovery-mechanisms/3.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/* eslint-disable no-console */
2+
'use strict'
3+
4+
const Libp2p = require('../../')
5+
const TCP = require('libp2p-tcp')
6+
const Mplex = require('libp2p-mplex')
7+
const { NOISE } = require('libp2p-noise')
8+
const Gossipsub = require('libp2p-gossipsub')
9+
const Bootstrap = require('libp2p-bootstrap')
10+
const PubsubPeerDiscovery = require('libp2p-pubsub-peer-discovery')
11+
12+
const createRelayServer = require('libp2p-relay-server')
13+
14+
const createNode = async (bootstrapers) => {
15+
const node = await Libp2p.create({
16+
addresses: {
17+
listen: ['/ip4/0.0.0.0/tcp/0']
18+
},
19+
modules: {
20+
transport: [TCP],
21+
streamMuxer: [Mplex],
22+
connEncryption: [NOISE],
23+
pubsub: Gossipsub,
24+
peerDiscovery: [Bootstrap, PubsubPeerDiscovery]
25+
},
26+
config: {
27+
peerDiscovery: {
28+
[PubsubPeerDiscovery.tag]: {
29+
interval: 1000,
30+
enabled: true
31+
},
32+
[Bootstrap.tag]: {
33+
enabled: true,
34+
list: bootstrapers
35+
}
36+
}
37+
}
38+
})
39+
40+
return node
41+
}
42+
43+
;(async () => {
44+
const relay = await createRelayServer({
45+
listenAddresses: ['/ip4/0.0.0.0/tcp/0']
46+
})
47+
console.log(`libp2p relay starting with id: ${relay.peerId.toB58String()}`)
48+
await relay.start()
49+
const relayMultiaddrs = relay.multiaddrs.map((m) => `${m.toString()}/p2p/${relay.peerId.toB58String()}`)
50+
51+
const [node1, node2] = await Promise.all([
52+
createNode(relayMultiaddrs),
53+
createNode(relayMultiaddrs)
54+
])
55+
56+
node1.on('peer:discovery', (peerId) => {
57+
console.log(`Peer ${node1.peerId.toB58String()} discovered: ${peerId.toB58String()}`)
58+
})
59+
node2.on('peer:discovery', (peerId) => {
60+
console.log(`Peer ${node2.peerId.toB58String()} discovered: ${peerId.toB58String()}`)
61+
})
62+
63+
;[node1, node2].forEach((node, index) => console.log(`Node ${index} starting with id: ${node.peerId.toB58String()}`))
64+
await Promise.all([
65+
node1.start(),
66+
node2.start()
67+
])
68+
})();

examples/discovery-mechanisms/README.md

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,100 @@ Discovered: QmSSbQpuKrxkoXHm1v4Pi35hPN5hUHMZoBoawEs2Nhvi8m
156156
Discovered: QmRcXXhtG8vTqwVBRonKWtV4ovDoC1Fe56WYtcrw694eiJ
157157
```
158158

159-
## 3. Where to find other Peer Discovery Mechanisms
159+
## 3. Pubsub based Peer Discovery
160+
161+
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.
162+
163+
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).
164+
165+
You can create your libp2p nodes as follows:
166+
167+
```js
168+
const Libp2p = require('libp2p')
169+
const TCP = require('libp2p-tcp')
170+
const Mplex = require('libp2p-mplex')
171+
const { NOISE } = require('libp2p-noise')
172+
const Gossipsub = require('libp2p-gossipsub')
173+
const Bootstrap = require('libp2p-bootstrap')
174+
const PubsubPeerDiscovery = require('libp2p-pubsub-peer-discovery')
175+
176+
const createNode = async (bootstrapers) => {
177+
const node = await Libp2p.create({
178+
addresses: {
179+
listen: ['/ip4/0.0.0.0/tcp/0']
180+
},
181+
modules: {
182+
transport: [TCP],
183+
streamMuxer: [Mplex],
184+
connEncryption: [NOISE],
185+
pubsub: Gossipsub,
186+
peerDiscovery: [Bootstrap, PubsubPeerDiscovery]
187+
},
188+
config: {
189+
peerDiscovery: {
190+
[PubsubPeerDiscovery.tag]: {
191+
interval: 1000,
192+
enabled: true
193+
},
194+
[Bootstrap.tag]: {
195+
enabled: true,
196+
list: bootstrapers
197+
}
198+
}
199+
}
200+
})
201+
202+
return node
203+
}
204+
```
205+
206+
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 an the relay will advertise them.
207+
208+
```js
209+
const relay = await createRelayServer({
210+
listenAddresses: ['/ip4/0.0.0.0/tcp/0']
211+
})
212+
console.log(`libp2p relay starting with id: ${relay.peerId.toB58String()}`)
213+
await relay.start()
214+
const relayMultiaddrs = relay.multiaddrs.map((m) => `${m.toString()}/p2p/${relay.peerId.toB58String()}`)
215+
216+
const [node1, node2] = await Promise.all([
217+
createNode(relayMultiaddrs),
218+
createNode(relayMultiaddrs)
219+
])
220+
221+
node1.on('peer:discovery', (peerId) => {
222+
console.log(`Peer ${node1.peerId.toB58String()} discovered: ${peerId.toB58String()}`)
223+
})
224+
node2.on('peer:discovery', (peerId) => {
225+
console.log(`Peer ${node2.peerId.toB58String()} discovered: ${peerId.toB58String()}`)
226+
})
227+
228+
;[node1, node2].forEach((node, index) => console.log(`Node ${index} starting with id: ${node.peerId.toB58String()}`))
229+
await Promise.all([
230+
node1.start(),
231+
node2.start()
232+
])
233+
```
234+
235+
If you run this example, you will see the other peers being discovered.
236+
237+
```bash
238+
> node 3.js
239+
libp2p relay starting with id: QmW6FqVV6RsyoGC5zaeFGW9gSWA3LcBRVZrjkKMruh38Bo
240+
Node 0 starting with id: QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N
241+
Node 1 starting with id: QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv
242+
Peer QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N discovered: QmW6FqVV6RsyoGC5zaeFGW9gSWA3LcBRVZrjkKMruh38Bo
243+
Peer QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv discovered: QmW6FqVV6RsyoGC5zaeFGW9gSWA3LcBRVZrjkKMruh38Bo
244+
Peer QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv discovered: QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N
245+
Peer QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N discovered: QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv
246+
```
247+
248+
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.
249+
250+
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.
251+
252+
## 4. Where to find other Peer Discovery Mechanisms
160253

161254
There are plenty more Peer Discovery Mechanisms out there, you can:
162255

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use strict'
2+
3+
const path = require('path')
4+
const execa = require('execa')
5+
const pWaitFor = require('p-wait-for')
6+
const uint8ArrayToString = require('uint8arrays/to-string')
7+
8+
const discoveredCopy = 'discovered:'
9+
10+
async function test() {
11+
let discoverCount = 0
12+
13+
process.stdout.write('3.js\n')
14+
15+
const proc = execa('node', [path.join(__dirname, '3.js')], {
16+
cwd: path.resolve(__dirname),
17+
all: true
18+
})
19+
20+
proc.all.on('data', async (data) => {
21+
process.stdout.write(data)
22+
const line = uint8ArrayToString(data)
23+
24+
// Discovered or Connected
25+
if (line.includes(discoveredCopy)) {
26+
discoverCount++
27+
}
28+
})
29+
30+
await pWaitFor(() => discoverCount === 4)
31+
32+
proc.kill()
33+
}
34+
35+
module.exports = test

examples/discovery-mechanisms/test.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
const test1 = require('./test-1')
44
const test2 = require('./test-2')
5+
const test3 = require('./test-3')
56

67
async function test () {
78
await test1()
89
await test2()
10+
await test3()
911
}
1012

1113
module.exports = test

examples/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
"dependencies": {
1111
"execa": "^2.1.0",
1212
"fs-extra": "^8.1.0",
13+
"libp2p-pubsub-peer-discovery": "^3.0.0",
14+
"libp2p-relay-server": "^0.1.2",
1315
"p-defer": "^3.0.0",
1416
"which": "^2.0.1"
1517
},

0 commit comments

Comments
 (0)