diff --git a/examples/pnet-ipfs/index.js b/examples/pnet-ipfs/index.js deleted file mode 100644 index 1df94171..00000000 --- a/examples/pnet-ipfs/index.js +++ /dev/null @@ -1,145 +0,0 @@ -/* 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') - -// 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) - -// Create a buffer and write the swarm key to it -const swarmKey = Buffer.alloc(95) -writeKey(swarmKey) - -// This key is for the `TASK` mentioned in the writeFileSync calls below -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) diff --git a/examples/pnet-ipfs/libp2p-bundle.js b/examples/pnet-ipfs/libp2p-bundle.js deleted file mode 100644 index ff4fd37e..00000000 --- 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/.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 90% rename from examples/pnet-ipfs/README.md rename to examples/pnet/README.md index 3e822767..b7515e96 100644 --- a/examples/pnet-ipfs/README.md +++ b/examples/pnet/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/index.js b/examples/pnet/index.js new file mode 100644 index 00000000..7e675930 --- /dev/null +++ b/examples/pnet/index.js @@ -0,0 +1,50 @@ +/* eslint no-console: ["off"] */ +'use strict' + +const { generate } = require('libp2p/src/pnet') +const privateLibp2pNode = require('./libp2p-node') + +const pipe = require('it-pipe') + +// Create a buffer and write the swarm key to it +const swarmKey = Buffer.alloc(95) +generate(swarmKey) + +// This key is for testing a different key not working +const otherSwarmKey = Buffer.alloc(95) +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) + + 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/libp2p-node.js b/examples/pnet/libp2p-node.js new file mode 100644 index 00000000..1c5ff799 --- /dev/null +++ b/examples/pnet/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/package.json similarity index 70% rename from examples/pnet-ipfs/package.json rename to examples/pnet/package.json index 649e2711..22f9fae1 100644 --- a/examples/pnet-ipfs/package.json +++ b/examples/pnet/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" } } 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