From ef9e29cd63447a62552dcbf3833ab04ae4bbfb55 Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Wed, 18 Dec 2019 19:29:05 +0000 Subject: [PATCH 1/3] refactor: examples/pnet --- examples/pnet-ipfs/README.md | 4 +- examples/pnet-ipfs/index.js | 175 +++++++--------------------- examples/pnet-ipfs/libp2p-bundle.js | 60 ---------- examples/pnet-ipfs/libp2p-node.js | 36 ++++++ examples/pnet-ipfs/package.json | 9 +- 5 files changed, 81 insertions(+), 203 deletions(-) delete mode 100644 examples/pnet-ipfs/libp2p-bundle.js create mode 100644 examples/pnet-ipfs/libp2p-node.js diff --git a/examples/pnet-ipfs/README.md b/examples/pnet-ipfs/README.md index 3e822767f7..b7515e9619 100644 --- a/examples/pnet-ipfs/README.md +++ b/examples/pnet-ipfs/README.md @@ -1,5 +1,5 @@ -# Private Networking with IPFS -This example shows how to set up a private network of IPFS nodes. +# Private Networking +This example shows how to set up a private network of libp2p nodes. ## Setup Install dependencies: diff --git a/examples/pnet-ipfs/index.js b/examples/pnet-ipfs/index.js index 1df9417157..3b90e7508c 100644 --- a/examples/pnet-ipfs/index.js +++ b/examples/pnet-ipfs/index.js @@ -1,145 +1,48 @@ /* eslint no-console: ["off"] */ 'use strict' -const IPFS = require('ipfs') -const assert = require('assert').strict -const { generate: writeKey } = require('libp2p/src/pnet') -const path = require('path') -const fs = require('fs') -const privateLibp2pBundle = require('./libp2p-bundle') -const { mkdirp } = require('./utils') +const { generate } = require('libp2p/src/pnet') +const privateLibp2pNode = require('./libp2p-node') -// Create two separate repo paths so we can run two nodes and check their output -const repo1 = path.resolve('./tmp', 'repo1', '.ipfs') -const repo2 = path.resolve('./tmp', 'repo2', '.ipfs') -mkdirp(repo1) -mkdirp(repo2) +const pipe = require('it-pipe') // Create a buffer and write the swarm key to it const swarmKey = Buffer.alloc(95) -writeKey(swarmKey) +generate(swarmKey) -// This key is for the `TASK` mentioned in the writeFileSync calls below +// This key is for testing a different key not working const otherSwarmKey = Buffer.alloc(95) -writeKey(otherSwarmKey) - -// Add the swarm key to both repos -const swarmKey1Path = path.resolve(repo1, 'swarm.key') -const swarmKey2Path = path.resolve(repo2, 'swarm.key') -fs.writeFileSync(swarmKey1Path, swarmKey) -// TASK: switch the commented out line below so we're using a different key, to see the nodes fail to connect -fs.writeFileSync(swarmKey2Path, swarmKey) -// fs.writeFileSync(swarmKey2Path, otherSwarmKey) - -// Create the first ipfs node -const node1 = new IPFS({ - repo: repo1, - libp2p: privateLibp2pBundle(swarmKey1Path), - config: { - Addresses: { - // Set the swarm address so we dont get port collision on the nodes - Swarm: ['/ip4/0.0.0.0/tcp/9101'] - } - } -}) - -// Create the second ipfs node -const node2 = new IPFS({ - repo: repo2, - libp2p: privateLibp2pBundle(swarmKey2Path), - config: { - Addresses: { - // Set the swarm address so we dont get port collision on the nodes - Swarm: ['/ip4/0.0.0.0/tcp/9102'] - } - } -}) - -console.log('auto starting the nodes...') - -// `nodesStarted` keeps track of how many of our nodes have started -let nodesStarted = 0 -/** - * Calls `connectAndTalk` when both nodes have started - * @returns {void} - */ -const didStartHandler = () => { - if (++nodesStarted === 2) { - // If both nodes are up, start talking - connectAndTalk() - } -} - -/** - * Exits the process when all started nodes have stopped - * @returns {void} - */ -const didStopHandler = () => { - if (--nodesStarted < 1) { - console.log('all nodes stopped, exiting.') - process.exit(0) - } -} - -/** - * Stops the running nodes - * @param {Error} err An optional error to log to the console - * @returns {void} - */ -const doStop = (err) => { - if (err) { - console.error(err) - } - - console.log('Shutting down...') - node1.stop() - node2.stop() -} - -/** - * Connects the IPFS nodes and transfers data between them - * @returns {void} - */ -const connectAndTalk = async () => { - console.log('connecting the nodes...') - const node2Id = await node2.id() - const dataToAdd = Buffer.from('Hello, private friend!') - - // Connect the nodes - // This will error when different private keys are used - try { - await node1.swarm.connect(node2Id.addresses[0]) - } catch (err) { - return doStop(err) - } - console.log('the nodes are connected, let\'s add some data') - - // Add some data to node 1 - let addedCID - try { - addedCID = await node1.add(dataToAdd) - } catch (err) { - return doStop(err) - } - console.log(`added ${addedCID[0].path} to the node1`) - - // Retrieve the data from node 2 - let cattedData - try { - cattedData = await node2.cat(addedCID[0].path) - } catch (err) { - return doStop(err) - } - assert.deepEqual(cattedData.toString(), dataToAdd.toString(), 'Should have equal data') - console.log(`successfully retrieved "${dataToAdd.toString()}" from node2`) - - doStop() -} - -// Wait for the nodes to boot -node1.once('start', didStartHandler) -node2.once('start', didStartHandler) - -// Listen for the nodes stopping so we can cleanup -node1.once('stop', didStopHandler) -node2.once('stop', didStopHandler) +generate(otherSwarmKey) + +;(async () => { + const node1 = await privateLibp2pNode(swarmKey) + const node2 = await privateLibp2pNode(otherSwarmKey) + // const node2 = await privateLibp2pNode(otherSwarmKey) + + await Promise.all([ + node1.start(), + node2.start() + ]) + + console.log('nodes started...') + + await node1.dial(node2.peerInfo) + + node2.handle('/private', ({ stream }) => { + pipe( + stream, + async function (source) { + for await (const msg of source) { + console.log(msg.toString()) + } + } + ) + }) + + const { stream } = await node1.dialProtocol(node2.peerInfo, '/private') + + await pipe( + ['This message is sent on a private network'], + stream + ) +})(); diff --git a/examples/pnet-ipfs/libp2p-bundle.js b/examples/pnet-ipfs/libp2p-bundle.js deleted file mode 100644 index ff4fd37e82..0000000000 --- a/examples/pnet-ipfs/libp2p-bundle.js +++ /dev/null @@ -1,60 +0,0 @@ -'use strict' - -const Libp2p = require('libp2p') -const TCP = require('libp2p-tcp') -const MPLEX = require('libp2p-mplex') -const SECIO = require('libp2p-secio') -const fs = require('fs') -const Protector = require('libp2p/src/pnet') - -/** - * 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 - */ - -/** - * privateLibp2pBundle returns a libp2p bundle function that will use the swarm - * key at the given `swarmKeyPath` to create the Protector - * - * @param {string} swarmKeyPath The path to our swarm key - * @returns {libp2pBundle} Returns a libp2pBundle function for use in IPFS creation - */ -const privateLibp2pBundle = (swarmKeyPath) => { - /** - * 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 - - // Build and return our libp2p node - return new Libp2p({ - peerInfo, - peerBook, - modules: { - transport: [TCP], // We're only using the TCP transport for this example - streamMuxer: [MPLEX], // We're only using mplex muxing - // Let's make sure to use identifying crypto in our pnet since the protector doesn't - // care about node identity, and only the presence of private keys - connEncryption: [SECIO], - // Leave peer discovery empty, we don't want to find peers. We could omit the property, but it's - // being left in for explicit readability. - // We should explicitly dial pnet peers, or use a custom discovery service for finding nodes in our pnet - peerDiscovery: [], - connProtector: new Protector(fs.readFileSync(swarmKeyPath)) - } - }) - } - - return libp2pBundle -} - -module.exports = privateLibp2pBundle diff --git a/examples/pnet-ipfs/libp2p-node.js b/examples/pnet-ipfs/libp2p-node.js new file mode 100644 index 0000000000..1c5ff79926 --- /dev/null +++ b/examples/pnet-ipfs/libp2p-node.js @@ -0,0 +1,36 @@ +'use strict' + +const Libp2p = require('libp2p') +const TCP = require('libp2p-tcp') +const MPLEX = require('libp2p-mplex') +const SECIO = require('libp2p-secio') +const Protector = require('libp2p/src/pnet') + +/** + * privateLibp2pNode returns a libp2p node function that will use the swarm + * key at the given `swarmKeyPath` to create the Protector + * + * @param {Buffer} swarmKey + * @returns {Promise} Returns a libp2pNode function for use in IPFS creation + */ +const privateLibp2pNode = async (swarmKeyPath) => { + const node = await Libp2p.create({ + modules: { + transport: [TCP], // We're only using the TCP transport for this example + streamMuxer: [MPLEX], // We're only using mplex muxing + // Let's make sure to use identifying crypto in our pnet since the protector doesn't + // care about node identity, and only the presence of private keys + connEncryption: [SECIO], + // Leave peer discovery empty, we don't want to find peers. We could omit the property, but it's + // being left in for explicit readability. + // We should explicitly dial pnet peers, or use a custom discovery service for finding nodes in our pnet + peerDiscovery: [], + connProtector: new Protector(swarmKeyPath) + } + }) + + node.peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0') + return node +} + +module.exports = privateLibp2pNode diff --git a/examples/pnet-ipfs/package.json b/examples/pnet-ipfs/package.json index 649e2711d9..22f9fae1e4 100644 --- a/examples/pnet-ipfs/package.json +++ b/examples/pnet-ipfs/package.json @@ -11,10 +11,9 @@ "author": "", "license": "ISC", "dependencies": { - "ipfs": "^0.38.0", - "libp2p": "^0.26.2", - "libp2p-mplex": "^0.8.5", - "libp2p-secio": "^0.11.1", - "libp2p-tcp": "^0.13.2" + "libp2p": "../..", + "libp2p-mplex": "^0.9.3", + "libp2p-secio": "^0.12.1", + "libp2p-tcp": "^0.14.2" } } From eb7649ee49b349c776f8d42dd29f87207eaa5931 Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Thu, 19 Dec 2019 18:08:30 +0000 Subject: [PATCH 2/3] chore: rename pnet-ipfs to pnet --- examples/{pnet-ipfs => pnet}/.gitignore | 0 examples/{pnet-ipfs => pnet}/README.md | 0 examples/{pnet-ipfs => pnet}/index.js | 2 +- examples/{pnet-ipfs => pnet}/libp2p-node.js | 0 examples/{pnet-ipfs => pnet}/package.json | 0 examples/{pnet-ipfs => pnet}/utils.js | 0 6 files changed, 1 insertion(+), 1 deletion(-) rename examples/{pnet-ipfs => pnet}/.gitignore (100%) rename examples/{pnet-ipfs => pnet}/README.md (100%) rename examples/{pnet-ipfs => pnet}/index.js (94%) rename examples/{pnet-ipfs => pnet}/libp2p-node.js (100%) rename examples/{pnet-ipfs => pnet}/package.json (100%) rename examples/{pnet-ipfs => pnet}/utils.js (100%) diff --git a/examples/pnet-ipfs/.gitignore b/examples/pnet/.gitignore similarity index 100% rename from examples/pnet-ipfs/.gitignore rename to examples/pnet/.gitignore diff --git a/examples/pnet-ipfs/README.md b/examples/pnet/README.md similarity index 100% rename from examples/pnet-ipfs/README.md rename to examples/pnet/README.md diff --git a/examples/pnet-ipfs/index.js b/examples/pnet/index.js similarity index 94% rename from examples/pnet-ipfs/index.js rename to examples/pnet/index.js index 3b90e7508c..feccefb46b 100644 --- a/examples/pnet-ipfs/index.js +++ b/examples/pnet/index.js @@ -16,7 +16,7 @@ generate(otherSwarmKey) ;(async () => { const node1 = await privateLibp2pNode(swarmKey) - const node2 = await privateLibp2pNode(otherSwarmKey) + const node2 = await privateLibp2pNode(swarmKey) // const node2 = await privateLibp2pNode(otherSwarmKey) await Promise.all([ diff --git a/examples/pnet-ipfs/libp2p-node.js b/examples/pnet/libp2p-node.js similarity index 100% rename from examples/pnet-ipfs/libp2p-node.js rename to examples/pnet/libp2p-node.js diff --git a/examples/pnet-ipfs/package.json b/examples/pnet/package.json similarity index 100% rename from examples/pnet-ipfs/package.json rename to examples/pnet/package.json diff --git a/examples/pnet-ipfs/utils.js b/examples/pnet/utils.js similarity index 100% rename from examples/pnet-ipfs/utils.js rename to examples/pnet/utils.js From 1f72540b6c2452844a2dc15c6624d79e48f52a1e Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Tue, 7 Jan 2020 11:47:42 +0100 Subject: [PATCH 3/3] chore: address review --- examples/pnet/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/pnet/index.js b/examples/pnet/index.js index feccefb46b..7e675930ac 100644 --- a/examples/pnet/index.js +++ b/examples/pnet/index.js @@ -16,6 +16,8 @@ generate(otherSwarmKey) ;(async () => { const node1 = await privateLibp2pNode(swarmKey) + + // TASK: switch the commented out line below so we're using a different key, to see the nodes fail to connect const node2 = await privateLibp2pNode(swarmKey) // const node2 = await privateLibp2pNode(otherSwarmKey)