mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-03-30 22:31:03 +00:00
refactor: examples/pnet (#523)
* refactor: examples/pnet * chore: rename pnet-ipfs to pnet * chore: address review
This commit is contained in:
parent
efc96c2f19
commit
721151b9fc
@ -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)
|
|
@ -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
|
|
@ -1,5 +1,5 @@
|
|||||||
# Private Networking with IPFS
|
# Private Networking
|
||||||
This example shows how to set up a private network of IPFS nodes.
|
This example shows how to set up a private network of libp2p nodes.
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
Install dependencies:
|
Install dependencies:
|
50
examples/pnet/index.js
Normal file
50
examples/pnet/index.js
Normal file
@ -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
|
||||||
|
)
|
||||||
|
})();
|
36
examples/pnet/libp2p-node.js
Normal file
36
examples/pnet/libp2p-node.js
Normal file
@ -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<libp2p>} 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
|
@ -11,10 +11,9 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ipfs": "^0.38.0",
|
"libp2p": "../..",
|
||||||
"libp2p": "^0.26.2",
|
"libp2p-mplex": "^0.9.3",
|
||||||
"libp2p-mplex": "^0.8.5",
|
"libp2p-secio": "^0.12.1",
|
||||||
"libp2p-secio": "^0.11.1",
|
"libp2p-tcp": "^0.14.2"
|
||||||
"libp2p-tcp": "^0.13.2"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user