Skip to content
This repository has been archived by the owner on Feb 24, 2021. It is now read-only.

Commit

Permalink
refactor: use async await (#108)
Browse files Browse the repository at this point in the history
* chore: upgrade deps

* feat: first iteration of the idea

* feat: iterate a layer deeper

* feat: rewrite handshake

* feat: rewrite propose

* feat: rewrite finish

* feat: rewrite exchange

* feat: rewrite low-level stuff

* feat: work on rewriting tests

* refactor: browser tests

* refactor: .aegir.js

* feat: refactor benchmarks

* fix: try to make it work

* fix: lint

* refactor: move tests

* refactor: switch deps

* refactor: entry file

* refactor: a bit more

* fix: tests

* feat: inital iterables refactor

* refactor: streaming

* refactor: cleanup

* fix: turn bufferlist into buffer

* fix: use errors from interfaces

* refactor: etm

* fix: typo

* fix: .read error

* fix: satisfy output expectations

* fix: it works - WARNING: using varint instead of fixed lp, tests lie

* fix: use errors

* refactor: benchmarks

* fix: add suggestions from review

Co-Authored-By: Jacob Heun <jacobheun@gmail.com>

* fix: upgrade deps and use correct lp-encoder

* refactor: apply changes from review

* refactor: apply changes from review

* refactor: apply changes from review

* chore: remove old tests

test: add support tests back

* test: fix async benchmarks

* chore: clean up deps

* fix: use fixed encoding/decoding everywhere

fix: exchange final nonce handshake over encryption

* test: add verify inbound and outbound secio

* test: verify nonces are boxed

* chore: add node 12 to ci
  • Loading branch information
mkg20001 authored and jacobheun committed Nov 22, 2019
1 parent 774267f commit 8ad4c15
Show file tree
Hide file tree
Showing 24 changed files with 501 additions and 820 deletions.
40 changes: 0 additions & 40 deletions .aegir.js

This file was deleted.

1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ stages:

node_js:
- '10'
- '12'

os:
- linux
Expand Down
39 changes: 2 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,44 +42,9 @@ const secio = require('libp2p-secio')

## API

### `.tag`
This module exposes a crypto interface, as defined in the [js-interfaces](https://github.com/libp2p/js-interfaces)

The current `secio` tag, usable in `multistream`.

### `const encryptedConnection = secio.encrypt(localPeerId, plainTextConnection [, remotePeerId] [, callback])`

- `localPeerId: PeerId` - A PeerId object containing the Private, Public and Id of our node.
- `plainTextConnection: Connection` - The insecure connection to be secured.
- `remotePeerId: PeerId` - A PeerId object containing the Public and/or Id of the node we are doing the SECIO handshake with.
- `callback: Function` - Optional, Called if an error happens during the initialization.

Returns an encrypted [Connection object](https://github.com/libp2p/interface-connection) that is the upgraded `plainTextConnection` with now having every byte encrypted.

Both plainTextConnection and encryptedConnection are at their base, PullStreams.

### This module uses `pull-streams`

We expose a streaming interface based on `pull-streams`, rather then on the Node.js core streams implementation (aka Node.js streams). `pull-streams` offers us a better mechanism for error handling and flow control guarantees. If you would like to know more about why we did this, see the discussion at this [issue](https://github.com/ipfs/js-ipfs/issues/362).

You can learn more about pull-streams at:

- [The history of Node.js streams, nodebp April 2014](https://www.youtube.com/watch?v=g5ewQEuXjsQ)
- [The history of streams, 2016](http://dominictarr.com/post/145135293917/history-of-streams)
- [pull-streams, the simple streaming primitive](http://dominictarr.com/post/149248845122/pull-streams-pull-streams-are-a-very-simple)
- [pull-streams documentation](https://pull-stream.github.io/)

#### Converting `pull-streams` to Node.js Streams

If you are a Node.js streams user, you can convert a pull-stream to a Node.js stream using the module [`pull-stream-to-stream`](https://github.com/pull-stream/pull-stream-to-stream), giving you an instance of a Node.js stream that is linked to the pull-stream. For example:

```js
const pullToStream = require('pull-stream-to-stream')

const nodeStreamInstance = pullToStream(pullStreamInstance)
// nodeStreamInstance is an instance of a Node.js Stream
```

To learn more about this utility, visit https://pull-stream.github.io/#pull-stream-to-stream.
[ » API Docs ](https://github.com/libp2p/js-interfaces/tree/master/src/crypto#api)

## Contribute

Expand Down
124 changes: 65 additions & 59 deletions benchmarks/send.js
Original file line number Diff line number Diff line change
@@ -1,73 +1,70 @@
'use strict'

/* eslint-disable no-console */

const Benchmark = require('benchmark')
const pull = require('pull-stream/pull')
const infinite = require('pull-stream/sources/infinite')
const take = require('pull-stream/throughs/take')
const drain = require('pull-stream/sinks/drain')
const Connection = require('interface-connection').Connection
const parallel = require('async/parallel')
const pair = require('pull-pair/duplex')
const PeerId = require('peer-id')

const secio = require('../src')
const pipe = require('it-pipe')
const { reduce } = require('streaming-iterables')
const DuplexPair = require('it-pair/duplex')

const secio = require('..')

const suite = new Benchmark.Suite('secio')
let peers

function sendData (a, b, opts, finish) {
async function sendData (a, b, opts) {
opts = Object.assign({ times: 1, size: 100 }, opts)

pull(
infinite(() => Buffer.allocUnsafe(opts.size)),
take(opts.times),
let i = opts.times

pipe(
function * () {
while (i--) {
yield Buffer.allocUnsafe(opts.size)
}
},
a
)

let length = 0

pull(
const res = await pipe(
b,
drain((data) => {
length += data.length
}, () => {
if (length !== opts.times * opts.size) {
throw new Error('Did not receive enough chunks')
}
finish.resolve()
})
reduce((acc, val) => acc + val.length, 0)
)
}

function ifErr (err) {
if (err) {
throw err
if (res !== opts.times * opts.size) {
throw new Error('Did not receive enough chunks')
}
}

suite.add('create peers for test', (deferred) => {
parallel([
(cb) => PeerId.createFromJSON(require('./peer-a'), cb),
(cb) => PeerId.createFromJSON(require('./peer-b'), cb)
], (err, _peers) => {
if (err) { throw err }
peers = _peers

suite.add('create peers for test', {
defer: true,
fn: async (deferred) => {
peers = await Promise.all([
PeerId.createFromJSON(require('./peer-a')),
PeerId.createFromJSON(require('./peer-b'))
])
deferred.resolve()
})
}, { defer: true })

suite.add('establish an encrypted channel', (deferred) => {
const p = pair()
}
})
suite.add('establish an encrypted channel', {
defer: true,
fn: async (deferred) => {
const p = DuplexPair()

const peerA = peers[0]
const peerB = peers[1]
const peerA = peers[0]
const peerB = peers[1]

const aToB = secio.encrypt(peerA, new Connection(p[0]), peerB, ifErr)
const bToA = secio.encrypt(peerB, new Connection(p[1]), peerA, ifErr)
const [aToB, bToA] = await Promise.all([
secio.secureInbound(peerA, p[0], peerB),
secio.secureOutbound(peerB, p[1], peerA)
])

sendData(aToB, bToA, {}, deferred)
}, { defer: true })
await sendData(aToB.conn, bToA.conn, {})
deferred.resolve()
}
})

const cases = [
[10, 262144],
Expand All @@ -81,23 +78,32 @@ cases.forEach((el) => {
const times = el[0]
const size = el[1]

suite.add(`send plaintext ${times} x ${size} bytes`, (deferred) => {
const p = pair()
suite.add(`send plaintext ${times} x ${size} bytes`, {
defer: true,
fn: async (deferred) => {
const p = DuplexPair()
await sendData(p[0], p[1], { times: times, size: size })
deferred.resolve()
}
})

sendData(p[0], p[1], { times: times, size: size }, deferred)
}, { defer: true })
suite.add(`send encrypted ${times} x ${size} bytes`, {
defer: true,
fn: async (deferred) => {
const p = DuplexPair()

suite.add(`send encrypted ${times} x ${size} bytes`, (deferred) => {
const p = pair()
const peerA = peers[0]
const peerB = peers[1]

const peerA = peers[0]
const peerB = peers[1]
const [aToB, bToA] = await Promise.all([
secio.secureInbound(peerA, p[0], peerB),
secio.secureOutbound(peerB, p[1], peerA)
])

const aToB = secio.encrypt(peerA, new Connection(p[0]), peerB, ifErr)
const bToA = secio.encrypt(peerB, new Connection(p[1]), peerA, ifErr)

sendData(aToB, bToA, { times: times, size: size }, deferred)
}, { defer: true })
await sendData(aToB.conn, bToA.conn, { times: times, size: size })
deferred.resolve()
}
})
})

suite.on('cycle', (event) => {
Expand Down
33 changes: 14 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,31 +25,26 @@
],
"license": "MIT",
"dependencies": {
"async": "^2.6.2",
"bl": "^4.0.0",
"debug": "^4.1.1",
"interface-connection": "~0.3.3",
"libp2p-crypto": "~0.16.1",
"multiaddr": "^6.0.6",
"multihashing-async": "~0.6.0",
"once": "^1.4.0",
"peer-id": "~0.12.2",
"peer-info": "~0.15.1",
"protons": "^1.0.1",
"pull-defer": "~0.2.3",
"pull-handshake": "^1.1.4",
"pull-length-prefixed": "^1.3.2",
"pull-stream": "^3.6.9",
"safe-buffer": "^5.1.2"
"it-buffer": "^0.1.1",
"it-length-prefixed": "^3.0.0",
"it-pair": "^1.0.0",
"it-pb-rpc": "^0.1.4",
"it-pipe": "^1.1.0",
"libp2p-crypto": "~0.17.1",
"libp2p-interfaces": "~0.1.3",
"multiaddr": "^7.2.1",
"multihashing-async": "~0.8.0",
"peer-id": "~0.13.5",
"protons": "^1.0.1"
},
"devDependencies": {
"aegir": "^18.2.2",
"aegir": "^20.4.1",
"benchmark": "^2.1.4",
"chai": "^4.2.0",
"dirty-chai": "^2.0.1",
"libp2p-websockets": "~0.12.2",
"multistream-select": "~0.14.4",
"pull-goodbye": "~0.0.2",
"pull-pair": "^1.1.0"
"streaming-iterables": "^4.1.1"
},
"engines": {
"node": ">=6.0.0",
Expand Down
Loading

0 comments on commit 8ad4c15

Please sign in to comment.