-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add peer/content routing example (#174)
Restores peer/content routing example
- Loading branch information
1 parent
9a23d76
commit d8439b3
Showing
14 changed files
with
366 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
...les/js-libp2p-example-peer-and-content-routing/.github/pull_request_template.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# ⚠️ IMPORTANT ⚠️ | ||
|
||
# Please do not create a Pull Request for this repository | ||
|
||
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. | ||
|
||
Please open a PR against [js-libp2p Examples](https://github.com/libp2p/js-libp2p-examples) instead. | ||
|
||
## 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 [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) | ||
2. Create your Feature Branch (`git checkout -b feature/amazing-example`) | ||
3. Commit your Changes (`git commit -a -m 'feat: add some amazing example'`) | ||
4. Push to the Branch (`git push origin feature/amazing-example`) | ||
5. Open a Pull Request |
19 changes: 19 additions & 0 deletions
19
examples/js-libp2p-example-peer-and-content-routing/.github/workflows/sync.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
name: pull | ||
|
||
on: | ||
workflow_dispatch | ||
|
||
jobs: | ||
sync: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Pull from another repository | ||
uses: ipfs-examples/actions-pull-directory-from-repo@main | ||
with: | ||
source-repo: libp2p/js-libp2p-examples | ||
source-folder-path: examples/${{ github.event.repository.name }} | ||
source-branch: main | ||
target-branch: main | ||
git-username: github-actions | ||
git-email: github-actions@github.com |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/* eslint-disable no-console */ | ||
|
||
import { noise } from '@chainsafe/libp2p-noise' | ||
import { yamux } from '@chainsafe/libp2p-yamux' | ||
import { identify, identifyPush } from '@libp2p/identify' | ||
import { kadDHT, removePublicAddressesMapper } from '@libp2p/kad-dht' | ||
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()], | ||
connectionEncrypters: [noise()], | ||
services: { | ||
// configure Kad-DHT to run on the local network | ||
dht: kadDHT({ | ||
protocol: '/ipfs/lan/kad/1.0.0', | ||
peerInfoMapper: removePublicAddressesMapper, | ||
clientMode: false | ||
}), | ||
identify: identify(), | ||
identifyPush: identifyPush() | ||
} | ||
}) | ||
|
||
return node | ||
} | ||
|
||
const [node1, node2, node3] = await Promise.all([ | ||
createNode(), | ||
createNode(), | ||
createNode() | ||
]) | ||
|
||
// Connect the nodes 1 -> 2 -> 3 | ||
await Promise.all([ | ||
node1.dial(node2.getMultiaddrs()), | ||
node2.dial(node3.getMultiaddrs()) | ||
]) | ||
|
||
// find peer 3 from peer 1 (there is no direct connection) | ||
const peer = await node1.peerRouting.findPeer(node3.peerId) | ||
|
||
console.log('Found it, multiaddrs are:') | ||
peer.multiaddrs.forEach((ma) => console.log(ma.toString())) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* eslint-disable no-console */ | ||
|
||
import { noise } from '@chainsafe/libp2p-noise' | ||
import { yamux } from '@chainsafe/libp2p-yamux' | ||
import { identify, identifyPush } from '@libp2p/identify' | ||
import { kadDHT, removePublicAddressesMapper } from '@libp2p/kad-dht' | ||
import { tcp } from '@libp2p/tcp' | ||
import all from 'it-all' | ||
import { createLibp2p } from 'libp2p' | ||
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()], | ||
connectionEncrypters: [noise()], | ||
services: { | ||
dht: kadDHT({ | ||
protocol: '/ipfs/lan/kad/1.0.0', | ||
peerInfoMapper: removePublicAddressesMapper, | ||
clientMode: false | ||
}), | ||
identify: identify(), | ||
identifyPush: identifyPush() | ||
} | ||
}) | ||
|
||
return node | ||
} | ||
|
||
const [node1, node2, node3] = await Promise.all([ | ||
createNode(), | ||
createNode(), | ||
createNode() | ||
]) | ||
|
||
await Promise.all([ | ||
node1.dial(node2.getMultiaddrs()), | ||
node2.dial(node3.getMultiaddrs()) | ||
]) | ||
|
||
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: 3000 })) | ||
|
||
console.log('Found provider:', providers[0].id.toString()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
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 |
5 changes: 5 additions & 0 deletions
5
examples/js-libp2p-example-peer-and-content-routing/LICENSE-APACHE
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
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. |
19 changes: 19 additions & 0 deletions
19
examples/js-libp2p-example-peer-and-content-routing/LICENSE-MIT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
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. |
124 changes: 124 additions & 0 deletions
124
examples/js-libp2p-example-peer-and-content-routing/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
# @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-examples.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-examples) | ||
[![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) | ||
|
||
> How to use peer and content routing | ||
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 { noise } from '@chainsafe/libp2p-noise' | ||
import { yamux } from '@chainsafe/libp2p-yamux' | ||
import { identify, identifyPush } from '@libp2p/identify' | ||
import { kadDHT, removePublicAddressesMapper } from '@libp2p/kad-dht' | ||
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()], | ||
connectionEncrypters: [noise()], | ||
services: { | ||
// configure Kad-DHT to run on the local network | ||
dht: kadDHT({ | ||
protocol: '/ipfs/lan/kad/1.0.0', | ||
peerInfoMapper: removePublicAddressesMapper, | ||
clientMode: false | ||
}), | ||
identify: identify(), | ||
identifyPush: identifyPush() | ||
} | ||
}) | ||
|
||
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 Promise.all([ | ||
node1.dial(node2.getMultiaddrs()), | ||
node2.dial(node3.getMultiaddrs()) | ||
]) | ||
|
||
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! | ||
|
||
## License | ||
|
||
Licensed under either of | ||
|
||
- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>) | ||
- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/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. |
33 changes: 33 additions & 0 deletions
33
examples/js-libp2p-example-peer-and-content-routing/package.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
{ | ||
"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-examples/tree/master/examples/js-libp2p-example-peer-and-content-routing#readme", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/libp2p/js-libp2p-examples.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/libp2p/js-libp2p-examples/issues" | ||
}, | ||
"type": "module", | ||
"scripts": { | ||
"lint": "aegir lint", | ||
"test": "test-node-example test/*" | ||
}, | ||
"dependencies": { | ||
"@chainsafe/libp2p-noise": "^16.0.0", | ||
"@chainsafe/libp2p-yamux": "^7.0.0", | ||
"@libp2p/identify": "^3.0.1", | ||
"@libp2p/kad-dht": "^13.0.0", | ||
"@libp2p/tcp": "^10.0.0", | ||
"it-all": "^3.0.2", | ||
"libp2p": "^2.0.0", | ||
"multiformats": "^13.1.1" | ||
}, | ||
"devDependencies": { | ||
"test-ipfs-example": "^1.1.0" | ||
}, | ||
"private": true | ||
} |
5 changes: 5 additions & 0 deletions
5
examples/js-libp2p-example-peer-and-content-routing/test/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { test as test1 } from './test-1.js' | ||
import { test as test2 } from './test-2.js' | ||
|
||
await test1() | ||
await test2() |
13 changes: 13 additions & 0 deletions
13
examples/js-libp2p-example-peer-and-content-routing/test/test-1.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
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 | ||
}) | ||
} |
13 changes: 13 additions & 0 deletions
13
examples/js-libp2p-example-peer-and-content-routing/test/test-2.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
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 | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters