-
Notifications
You must be signed in to change notification settings - Fork 448
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #99 from libp2p/docs/stellar-examples
docs: examples - transports, crypto channels, protocol and stream muxing
- Loading branch information
Showing
19 changed files
with
1,051 additions
and
6 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
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
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,2 @@ | ||
# WIP - This example is still in the works | ||
![](http://1.bp.blogspot.com/-tNvSnCW0KlQ/U-KOKGVoJkI/AAAAAAAAA3Q/aiSLMeSJFtw/s1600/WIP-sign.jpg) |
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,59 @@ | ||
'use strict' | ||
|
||
const libp2p = require('libp2p') | ||
const TCP = require('libp2p-tcp') | ||
const SPDY = require('libp2p-spdy') | ||
const SECIO = require('libp2p-secio') | ||
const PeerInfo = require('peer-info') | ||
const waterfall = require('async/waterfall') | ||
const parallel = require('async/parallel') | ||
const pull = require('pull-stream') | ||
|
||
class MyBundle extends libp2p { | ||
constructor (peerInfo) { | ||
const modules = { | ||
transport: [new TCP()], | ||
connection: { | ||
muxer: [SPDY], | ||
crypto: [SECIO] | ||
} | ||
} | ||
super(modules, peerInfo) | ||
} | ||
} | ||
|
||
function createNode (callback) { | ||
let node | ||
|
||
waterfall([ | ||
(cb) => PeerInfo.create(cb), | ||
(peerInfo, cb) => { | ||
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0') | ||
node = new MyBundle(peerInfo) | ||
node.start(cb) | ||
} | ||
], (err) => callback(err, node)) | ||
} | ||
|
||
parallel([ | ||
(cb) => createNode(cb), | ||
(cb) => createNode(cb) | ||
], (err, nodes) => { | ||
if (err) { throw err } | ||
|
||
const node1 = nodes[0] | ||
const node2 = nodes[1] | ||
|
||
node2.handle('/a-protocol', (protocol, conn) => { | ||
pull( | ||
conn, | ||
pull.map((v) => v.toString()), | ||
pull.log() | ||
) | ||
}) | ||
|
||
node1.dial(node2.peerInfo, '/a-protocol', (err, conn) => { | ||
if (err) { throw err } | ||
pull(pull.values(['This information is sent out encrypted to the other peer']), conn) | ||
}) | ||
}) |
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,39 @@ | ||
# Encrypted Communications | ||
|
||
libp2p can leverage the encrypted communications from the transports it uses (i.e WebRTC). To ensure that every connection is encrypted, independently of how it was set up, libp2p also supports a set of modules that encrypt every communication established. | ||
|
||
We call this usage a _connection upgrade_ where given a connection between peer A to peer B, a protocol handshake can be performed that gives that connection new properties. | ||
|
||
A byproduct of having these encrypted communications modules is that we can authenticate the peers we are dialing to. You might have noticed that every time we dial to a peer in libp2p space, we always use its PeerId at the end (e.g /ip4/127.0.0.1/tcp/89765/ipfs/QmWCbVw1XZ8hiYBwwshPce2yaTDYTqTaP7GCHGpry3ykWb), this PeerId is generated by hashing the Public Key of the peer. With this, we can create a crypto challenge when dialing to another peer and prove that peer is the owner of a PrivateKey that matches the Public Key we know. | ||
|
||
# 1. Set up encrypted communications with SECIO | ||
|
||
We will build this example on top of example for [Protocol and Stream Multiplexing](../protocol-and-stream-multiplexing). You will need the module `libp2p-secio` to complete it, go ahead and `npm install libp2p-secio`. | ||
|
||
SECIO is the crypto channel developed for IPFS, it is a TLS 1.3 like crypto channel that established an encrypted communication channel between two peers. | ||
|
||
To add it to your libp2p bundle, all you have to do is: | ||
|
||
```JavaScript | ||
const SECIO = require('libp2p-secio') | ||
|
||
class MyBundle extends libp2p { | ||
constructor (peerInfo) { | ||
const modules = { | ||
transport: [new TCP()], | ||
connection: { | ||
muxer: [SPDY], | ||
// Attach secio as the crypto channel to use | ||
crypto: [SECIO] | ||
} | ||
} | ||
super(modules, peerInfo) | ||
} | ||
} | ||
``` | ||
|
||
And that's it, from now on, all your libp2p communications are encrypted. Try running the exampme [1.js](./1.js) to see it working. | ||
|
||
If you want to want to learn more about how SECIO works, you can read the [great write up done by Dominic Tarr](https://github.com/auditdrivencrypto/secure-channel/blob/master/prior-art.md#ipfss-secure-channel). | ||
|
||
Importante note: SECIO hasn't been audited and so, we do not recommend to trust its security. We intent to move to TLS 1.3 once the specification is finalized and an implementation exists that we can use. |
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,2 @@ | ||
# WIP - This example is still in the works | ||
![](http://1.bp.blogspot.com/-tNvSnCW0KlQ/U-KOKGVoJkI/AAAAAAAAA3Q/aiSLMeSJFtw/s1600/WIP-sign.jpg) |
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,2 @@ | ||
# WIP - This example is still in the works | ||
![](http://1.bp.blogspot.com/-tNvSnCW0KlQ/U-KOKGVoJkI/AAAAAAAAA3Q/aiSLMeSJFtw/s1600/WIP-sign.jpg) |
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,2 @@ | ||
# WIP - This example is still in the works | ||
![](http://1.bp.blogspot.com/-tNvSnCW0KlQ/U-KOKGVoJkI/AAAAAAAAA3Q/aiSLMeSJFtw/s1600/WIP-sign.jpg) |
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,96 @@ | ||
'use strict' | ||
|
||
const libp2p = require('libp2p') | ||
const TCP = require('libp2p-tcp') | ||
const PeerInfo = require('peer-info') | ||
const waterfall = require('async/waterfall') | ||
const parallel = require('async/parallel') | ||
const pull = require('pull-stream') | ||
|
||
class MyBundle extends libp2p { | ||
constructor (peerInfo) { | ||
const modules = { | ||
transport: [new TCP()] | ||
} | ||
super(modules, peerInfo) | ||
} | ||
} | ||
|
||
function createNode (callback) { | ||
let node | ||
|
||
waterfall([ | ||
(cb) => PeerInfo.create(cb), | ||
(peerInfo, cb) => { | ||
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0') | ||
node = new MyBundle(peerInfo) | ||
node.start(cb) | ||
} | ||
], (err) => callback(err, node)) | ||
} | ||
|
||
parallel([ | ||
(cb) => createNode(cb), | ||
(cb) => createNode(cb) | ||
], (err, nodes) => { | ||
if (err) { throw err } | ||
|
||
const node1 = nodes[0] | ||
const node2 = nodes[1] | ||
|
||
// exact matching | ||
node2.handle('/your-protocol', (protocol, conn) => { | ||
pull( | ||
conn, | ||
pull.map((v) => v.toString()), | ||
pull.log() | ||
) | ||
}) | ||
|
||
// semver matching | ||
/* | ||
node2.handle('/another-protocol/1.0.1', (protocol, conn) => { | ||
pull( | ||
conn, | ||
pull.map((v) => v.toString()), | ||
pull.log() | ||
) | ||
}) | ||
*/ | ||
|
||
// custom func matching | ||
/* | ||
node2.handle('/custom-match-func', (protocol, conn) => { | ||
pull( | ||
conn, | ||
pull.map((v) => v.toString()), | ||
pull.log() | ||
) | ||
}, (myProtocol, requestedProtocol, callback) => { | ||
if (myProtocol.indexOf(requestedProtocol)) { | ||
callback(null, true) | ||
} else { | ||
callback(null, false) | ||
} | ||
}) | ||
*/ | ||
|
||
node1.dial(node2.peerInfo, '/your-protocol', (err, conn) => { | ||
if (err) { throw err } | ||
pull(pull.values(['my own protocol, wow!']), conn) | ||
}) | ||
|
||
/* | ||
node1.dial(node2.peerInfo, '/another-protocol/1.0.0', (err, conn) => { | ||
if (err) { throw err } | ||
pull(pull.values(['semver me please']), conn) | ||
}) | ||
*/ | ||
|
||
/* | ||
node1.dial(node2.peerInfo, '/custom-match-func/some-query', (err, conn) => { | ||
if (err) { throw err } | ||
pull(pull.values(['do I fall into your criteria?']), conn) | ||
}) | ||
*/ | ||
}) |
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,79 @@ | ||
'use strict' | ||
|
||
const libp2p = require('libp2p') | ||
const TCP = require('libp2p-tcp') | ||
const SPDY = require('libp2p-spdy') | ||
const PeerInfo = require('peer-info') | ||
const waterfall = require('async/waterfall') | ||
const parallel = require('async/parallel') | ||
const series = require('async/series') | ||
const pull = require('pull-stream') | ||
|
||
class MyBundle extends libp2p { | ||
constructor (peerInfo) { | ||
const modules = { | ||
transport: [new TCP()], | ||
connection: { | ||
muxer: [SPDY] | ||
} | ||
} | ||
super(modules, peerInfo) | ||
} | ||
} | ||
|
||
function createNode (callback) { | ||
let node | ||
|
||
waterfall([ | ||
(cb) => PeerInfo.create(cb), | ||
(peerInfo, cb) => { | ||
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0') | ||
node = new MyBundle(peerInfo) | ||
node.start(cb) | ||
} | ||
], (err) => callback(err, node)) | ||
} | ||
|
||
parallel([ | ||
(cb) => createNode(cb), | ||
(cb) => createNode(cb) | ||
], (err, nodes) => { | ||
if (err) { throw err } | ||
|
||
const node1 = nodes[0] | ||
const node2 = nodes[1] | ||
|
||
node2.handle('/a', (protocol, conn) => { | ||
pull( | ||
conn, | ||
pull.map((v) => v.toString()), | ||
pull.log() | ||
) | ||
}) | ||
|
||
node2.handle('/b', (protocol, conn) => { | ||
pull( | ||
conn, | ||
pull.map((v) => v.toString()), | ||
pull.log() | ||
) | ||
}) | ||
|
||
series([ | ||
(cb) => node1.dial(node2.peerInfo, '/a', (err, conn) => { | ||
if (err) { throw err } | ||
pull(pull.values(['protocol (a)']), conn) | ||
cb() | ||
}), | ||
(cb) => node1.dial(node2.peerInfo, '/b', (err, conn) => { | ||
if (err) { throw err } | ||
pull(pull.values(['protocol (b)']), conn) | ||
cb() | ||
}), | ||
(cb) => node1.dial(node2.peerInfo, '/b', (err, conn) => { | ||
if (err) { throw err } | ||
pull(pull.values(['another conn on protocol (b)']), conn) | ||
cb() | ||
}) | ||
]) | ||
}) |
Oops, something went wrong.