Skip to content

Commit d8439b3

Browse files
authored
feat: add peer/content routing example (#174)
Restores peer/content routing example
1 parent 9a23d76 commit d8439b3

File tree

14 files changed

+366
-0
lines changed

14 files changed

+366
-0
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ jobs:
2727
- js-libp2p-example-custom-protocols
2828
- js-libp2p-example-delegated-routing
2929
- js-libp2p-example-discovery-mechanisms
30+
- js-libp2p-example-peer-and-content-routing
3031
- js-libp2p-example-webrtc-private-to-private
3132
defaults:
3233
run:
@@ -82,6 +83,7 @@ jobs:
8283
- js-libp2p-example-custom-protocols
8384
- js-libp2p-example-delegated-routing
8485
- js-libp2p-example-discovery-mechanisms
86+
- js-libp2p-example-peer-and-content-routing
8587
- js-libp2p-example-webrtc-private-to-private
8688
steps:
8789
- uses: convictional/trigger-workflow-and-wait@f69fa9eedd3c62a599220f4d5745230e237904be
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# ⚠️ IMPORTANT ⚠️
2+
3+
# Please do not create a Pull Request for this repository
4+
5+
The contents of this repository are automatically synced from the parent [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) so any changes made to the standalone repository will be lost after the next sync.
6+
7+
Please open a PR against [js-libp2p Examples](https://github.com/libp2p/js-libp2p-examples) instead.
8+
9+
## Contributing
10+
11+
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**.
12+
13+
1. Fork the [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples)
14+
2. Create your Feature Branch (`git checkout -b feature/amazing-example`)
15+
3. Commit your Changes (`git commit -a -m 'feat: add some amazing example'`)
16+
4. Push to the Branch (`git push origin feature/amazing-example`)
17+
5. Open a Pull Request
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: pull
2+
3+
on:
4+
workflow_dispatch
5+
6+
jobs:
7+
sync:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- uses: actions/checkout@v2
11+
- name: Pull from another repository
12+
uses: ipfs-examples/actions-pull-directory-from-repo@main
13+
with:
14+
source-repo: libp2p/js-libp2p-examples
15+
source-folder-path: examples/${{ github.event.repository.name }}
16+
source-branch: main
17+
target-branch: main
18+
git-username: github-actions
19+
git-email: [email protected]
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/* eslint-disable no-console */
2+
3+
import { noise } from '@chainsafe/libp2p-noise'
4+
import { yamux } from '@chainsafe/libp2p-yamux'
5+
import { identify, identifyPush } from '@libp2p/identify'
6+
import { kadDHT, removePublicAddressesMapper } from '@libp2p/kad-dht'
7+
import { tcp } from '@libp2p/tcp'
8+
import { createLibp2p } from 'libp2p'
9+
10+
const createNode = async () => {
11+
const node = await createLibp2p({
12+
addresses: {
13+
listen: ['/ip4/0.0.0.0/tcp/0']
14+
},
15+
transports: [tcp()],
16+
streamMuxers: [yamux()],
17+
connectionEncrypters: [noise()],
18+
services: {
19+
// configure Kad-DHT to run on the local network
20+
dht: kadDHT({
21+
protocol: '/ipfs/lan/kad/1.0.0',
22+
peerInfoMapper: removePublicAddressesMapper,
23+
clientMode: false
24+
}),
25+
identify: identify(),
26+
identifyPush: identifyPush()
27+
}
28+
})
29+
30+
return node
31+
}
32+
33+
const [node1, node2, node3] = await Promise.all([
34+
createNode(),
35+
createNode(),
36+
createNode()
37+
])
38+
39+
// Connect the nodes 1 -> 2 -> 3
40+
await Promise.all([
41+
node1.dial(node2.getMultiaddrs()),
42+
node2.dial(node3.getMultiaddrs())
43+
])
44+
45+
// find peer 3 from peer 1 (there is no direct connection)
46+
const peer = await node1.peerRouting.findPeer(node3.peerId)
47+
48+
console.log('Found it, multiaddrs are:')
49+
peer.multiaddrs.forEach((ma) => console.log(ma.toString()))
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/* eslint-disable no-console */
2+
3+
import { noise } from '@chainsafe/libp2p-noise'
4+
import { yamux } from '@chainsafe/libp2p-yamux'
5+
import { identify, identifyPush } from '@libp2p/identify'
6+
import { kadDHT, removePublicAddressesMapper } from '@libp2p/kad-dht'
7+
import { tcp } from '@libp2p/tcp'
8+
import all from 'it-all'
9+
import { createLibp2p } from 'libp2p'
10+
import { CID } from 'multiformats/cid'
11+
12+
const createNode = async () => {
13+
const node = await createLibp2p({
14+
addresses: {
15+
listen: ['/ip4/0.0.0.0/tcp/0']
16+
},
17+
transports: [tcp()],
18+
streamMuxers: [yamux()],
19+
connectionEncrypters: [noise()],
20+
services: {
21+
dht: kadDHT({
22+
protocol: '/ipfs/lan/kad/1.0.0',
23+
peerInfoMapper: removePublicAddressesMapper,
24+
clientMode: false
25+
}),
26+
identify: identify(),
27+
identifyPush: identifyPush()
28+
}
29+
})
30+
31+
return node
32+
}
33+
34+
const [node1, node2, node3] = await Promise.all([
35+
createNode(),
36+
createNode(),
37+
createNode()
38+
])
39+
40+
await Promise.all([
41+
node1.dial(node2.getMultiaddrs()),
42+
node2.dial(node3.getMultiaddrs())
43+
])
44+
45+
const cid = CID.parse('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnL')
46+
await node1.contentRouting.provide(cid)
47+
48+
console.log('Node %s is providing %s', node1.peerId.toString(), cid.toString())
49+
50+
const providers = await all(node3.contentRouting.findProviders(cid, { timeout: 3000 }))
51+
52+
console.log('Found provider:', providers[0].id.toString())
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
This project is dual licensed under MIT and Apache-2.0.
2+
3+
MIT: https://www.opensource.org/licenses/mit
4+
Apache-2.0: https://www.apache.org/licenses/license-2.0
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
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
2+
3+
http://www.apache.org/licenses/LICENSE-2.0
4+
5+
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.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
The MIT License (MIT)
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in
11+
all copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# @libp2p/example-peer-and-content-routing
2+
3+
[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/)
4+
[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io)
5+
[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-examples.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-examples)
6+
[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-examples/ci.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-examples/actions/workflows/ci.yml?query=branch%3Amain)
7+
8+
> How to use peer and content routing
9+
10+
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.
11+
12+
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.
13+
14+
## 1. Using Peer Routing to find other peers
15+
16+
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).
17+
18+
First, let's update our config to support Peer Routing and Content Routing.
19+
20+
```JavaScript
21+
import { noise } from '@chainsafe/libp2p-noise'
22+
import { yamux } from '@chainsafe/libp2p-yamux'
23+
import { identify, identifyPush } from '@libp2p/identify'
24+
import { kadDHT, removePublicAddressesMapper } from '@libp2p/kad-dht'
25+
import { tcp } from '@libp2p/tcp'
26+
import { createLibp2p } from 'libp2p'
27+
28+
const createNode = async () => {
29+
const node = await createLibp2p({
30+
addresses: {
31+
listen: ['/ip4/0.0.0.0/tcp/0']
32+
},
33+
transports: [tcp()],
34+
streamMuxers: [yamux()],
35+
connectionEncrypters: [noise()],
36+
services: {
37+
// configure Kad-DHT to run on the local network
38+
dht: kadDHT({
39+
protocol: '/ipfs/lan/kad/1.0.0',
40+
peerInfoMapper: removePublicAddressesMapper,
41+
clientMode: false
42+
}),
43+
identify: identify(),
44+
identifyPush: identifyPush()
45+
}
46+
})
47+
48+
return node
49+
}
50+
```
51+
52+
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
53+
54+
```JavaScript
55+
const [node1, node2, node3] = await Promise.all([
56+
createNode(),
57+
createNode(),
58+
createNode()
59+
])
60+
61+
await Promise.all([
62+
node1.dial(node2.getMultiaddrs()),
63+
node2.dial(node3.getMultiaddrs())
64+
])
65+
66+
const peer = await node1.peerRouting.findPeer(node3.peerId)
67+
68+
console.log('Found it, multiaddrs are:')
69+
peer.multiaddrs.forEach((ma) => console.log(ma.toString()))
70+
```
71+
72+
You should see the output being something like:
73+
74+
```Bash
75+
> node 1.js
76+
Found it, multiaddrs are:
77+
/ip4/127.0.0.1/tcp/63617
78+
/ip4/192.168.86.41/tcp/63617
79+
```
80+
81+
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.
82+
83+
## 2. Using Content Routing to find providers of content
84+
85+
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.
86+
87+
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.
88+
89+
Instead of calling `peerRouting.findPeer`, we will use `contentRouting.provide` and `contentRouting.findProviders`.
90+
91+
```JavaScript
92+
import { CID } from 'multiformats/cid'
93+
import all from 'it-all'
94+
95+
const cid = CID.parse('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnL')
96+
await node1.contentRouting.provide(cid)
97+
98+
console.log('Node %s is providing %s', node1.peerId.toString(), cid.toString())
99+
100+
const providers = await all(node3.contentRouting.findProviders(cid, { timeout: 5000 }))
101+
102+
console.log('Found provider:', providers[0].id.toString())
103+
```
104+
105+
The output of your program should look like:
106+
107+
```bash
108+
> node 2.js
109+
Node QmSsmVPoTy3WpzwiNPnsKmonBaZjK2HitFs2nWUvwK31Pz is providing QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnL
110+
Found provider: QmSsmVPoTy3WpzwiNPnsKmonBaZjK2HitFs2nWUvwK31Pz
111+
```
112+
113+
That's it, now you know how to find peers that have pieces of information that interest you!
114+
115+
## License
116+
117+
Licensed under either of
118+
119+
- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)
120+
- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)
121+
122+
## Contribution
123+
124+
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.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"name": "@libp2p/example-peer-and-content-routing",
3+
"version": "0.0.0",
4+
"description": "How to use peer and content routing",
5+
"license": "Apache-2.0 OR MIT",
6+
"homepage": "https://github.com/libp2p/js-libp2p-examples/tree/master/examples/js-libp2p-example-peer-and-content-routing#readme",
7+
"repository": {
8+
"type": "git",
9+
"url": "git+https://github.com/libp2p/js-libp2p-examples.git"
10+
},
11+
"bugs": {
12+
"url": "https://github.com/libp2p/js-libp2p-examples/issues"
13+
},
14+
"type": "module",
15+
"scripts": {
16+
"lint": "aegir lint",
17+
"test": "test-node-example test/*"
18+
},
19+
"dependencies": {
20+
"@chainsafe/libp2p-noise": "^16.0.0",
21+
"@chainsafe/libp2p-yamux": "^7.0.0",
22+
"@libp2p/identify": "^3.0.1",
23+
"@libp2p/kad-dht": "^13.0.0",
24+
"@libp2p/tcp": "^10.0.0",
25+
"it-all": "^3.0.2",
26+
"libp2p": "^2.0.0",
27+
"multiformats": "^13.1.1"
28+
},
29+
"devDependencies": {
30+
"test-ipfs-example": "^1.1.0"
31+
},
32+
"private": true
33+
}

0 commit comments

Comments
 (0)