From 1f1238e17ba64b7f9909e442337a22b5add42437 Mon Sep 17 00:00:00 2001 From: Jacob Heun Date: Thu, 30 Aug 2018 09:23:24 +0200 Subject: [PATCH] feat: add libp2p factory config option with example (#1470) Resolves #1463 and https://github.com/libp2p/js-libp2p/issues/222 This adds the ability to pass a libp2p generator function to the ipfs configuration. This makes it easier for users to add custom modules to libp2p that require some startup time properties, like peerInfo (https://github.com/libp2p/js-libp2p/issues/222). I have also included an example of how to do this. I think this makes complex libp2p configuration much cleaner and easier to do. Tests have been added for the old configuration options and the new generator option. I isolated them to avoid spinning up a full ipfs node. --- README.md | 18 +++++++ index.js | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 23 +++++++++ 3 files changed, 170 insertions(+) create mode 100644 README.md create mode 100644 index.js create mode 100644 package.json diff --git a/README.md b/README.md new file mode 100644 index 0000000..ff4b376 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# Customizing your libp2p bundle + +This example shows you how to make full use of the ipfs configuration to create a libp2p bundle function. As IPFS applications become more complex, their needs for a custom libp2p bundle also grow. Instead of fighting with configuration options, you can use your own libp2p bundle function to get exactly what you need. + +## Run this example + +Running this example should result in metrics being logged out to the console every few seconds. + +``` +> npm install +> npm start +``` + +## Play with the configuration! + +With the metrics for peers and bandwidth stats being logged out, try playing around with the nodes configuration to see what kind of metrics you can get. How many peers are you getting? What does your bandwidth look like? + +This is also a good opportunity to explore the various stats that ipfs offers! Not seeing a statistic you think would be useful? We'd love to have you [contribute](https://github.com/ipfs/js-ipfs/blob/master/CONTRIBUTING.md)! diff --git a/index.js b/index.js new file mode 100644 index 0000000..ede982a --- /dev/null +++ b/index.js @@ -0,0 +1,129 @@ +'use strict' + +const Libp2p = require('libp2p') +const IPFS = require('ipfs') +const TCP = require('libp2p-tcp') +const MulticastDNS = require('libp2p-mdns') +const WebSocketStar = require('libp2p-websocket-star') +const Bootstrap = require('libp2p-railing') +const SPDY = require('libp2p-spdy') +const KadDHT = require('libp2p-kad-dht') +const MPLEX = require('libp2p-mplex') +const SECIO = require('libp2p-secio') +const assert = require('assert') + +/** + * Options for the libp2p bundle + * @typedef {Object} libp2pBundle~options + * @property {PeerInfo} peerInfo - The PeerInfo of the IPFS node + * @property {PeerBook} peerBook - The PeerBook of the IPFS node + * @property {Object} config - The config of the IPFS node + * @property {Object} options - The options given to the IPFS node + */ + +/** + * This is the bundle we will use to create our fully customized libp2p bundle. + * + * @param {libp2pBundle~options} opts The options to use when generating the libp2p node + * @returns {Libp2p} Our new libp2p node + */ +const libp2pBundle = (opts) => { + // Set convenience variables to clearly showcase some of the useful things that are available + const peerInfo = opts.peerInfo + const peerBook = opts.peerBook + const bootstrapList = opts.config.Bootstrap + + // Create our WebSocketStar transport and give it our PeerId, straight from the ipfs node + const wsstar = new WebSocketStar({ + id: peerInfo.id + }) + + // Build and return our libp2p node + return new Libp2p({ + peerInfo, + peerBook, + // Lets limit the connection managers peers and have it check peer health less frequently + connectionManager: { + maxPeers: 25, + pollInterval: 5000 + }, + modules: { + transport: [ + TCP, + wsstar + ], + streamMuxer: [ + MPLEX, + SPDY + ], + connEncryption: [ + SECIO + ], + peerDiscovery: [ + MulticastDNS, + Bootstrap, + wsstar.discovery + ], + dht: KadDHT + }, + config: { + peerDiscovery: { + mdns: { + interval: 10000, + enabled: true + }, + bootstrap: { + interval: 10000, + enabled: true, + list: bootstrapList + } + }, + // Turn on relay with hop active so we can connect to more peers + relay: { + enabled: true, + hop: { + enabled: true, + active: true + } + }, + dht: { + kBucketSize: 20 + }, + EXPERIMENTAL: { + dht: true, + pubsub: true + } + } + }) +} + +// Now that we have our custom libp2p bundle, let's start up the ipfs node! +const node = new IPFS({ + libp2p: libp2pBundle +}) + +// Listen for the node to start, so we can log out some metrics +node.once('start', (err) => { + assert.ifError(err, 'Should startup without issue') + + // Lets log out the number of peers we have every 2 seconds + setInterval(() => { + node.swarm.peers((err, peers) => { + if (err) { + console.log('An error occurred trying to check our peers:', err) + process.exit(1) + } + console.log(`The node now has ${peers.length} peers.`) + }) + }, 2000) + + // Log out the bandwidth stats every 4 seconds so we can see how our configuration is doing + setInterval(() => { + node.stats.bw((err, stats) => { + if (err) { + console.log('An error occurred trying to check our stats:', err) + } + console.log(`\nBandwidth Stats: ${JSON.stringify(stats, null, 2)}\n`) + }) + }, 4000) +}) diff --git a/package.json b/package.json new file mode 100644 index 0000000..8e28bc6 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "custom-libp2p", + "version": "0.1.0", + "description": "Customizing your libp2p node", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node index.js" + }, + "license": "MIT", + "dependencies": { + "ipfs": "file:../../", + "libp2p": "~0.22.0", + "libp2p-kad-dht": "~0.10.1", + "libp2p-mdns": "~0.12.0", + "libp2p-mplex": "~0.8.0", + "libp2p-railing": "~0.9.2", + "libp2p-secio": "~0.10.0", + "libp2p-spdy": "~0.12.1", + "libp2p-tcp": "~0.12.0", + "libp2p-websocket-star": "~0.8.1" + } +}