From ab64395da2d29992fff11e78c10f8e1a2805e4f0 Mon Sep 17 00:00:00 2001 From: David Dias Date: Thu, 30 Mar 2017 15:56:23 +0100 Subject: [PATCH 1/2] new peer-book --- package.json | 4 +-- src/index.js | 56 +++++++++++++++++++++++------------------- test/peer-book.spec.js | 12 ++++----- 3 files changed, 39 insertions(+), 33 deletions(-) diff --git a/package.json b/package.json index 32881d0..f750860 100644 --- a/package.json +++ b/package.json @@ -44,8 +44,8 @@ "async": "^2.2.0", "chai": "^3.5.0", "dirty-chai": "^1.2.2", - "multiaddr": "^2.2.3", - "peer-info": "~0.8.5", + "multiaddr": "^2.3.0", + "peer-info": "~0.9.0", "pre-commit": "^1.2.2" }, "contributors": [ diff --git a/src/index.js b/src/index.js index 0f7697e..103e2a0 100644 --- a/src/index.js +++ b/src/index.js @@ -2,25 +2,30 @@ const bs58 = require('bs58') -module.exports = PeerBook - -function PeerBook () { - if (!(this instanceof PeerBook)) { - return new PeerBook() +class PeerBook { + constructor () { + this._peers = {} } - const peers = {} - - this.put = (peerInfo, replace) => { - if (peers[peerInfo.id.toB58String()] && !replace) { - // peerInfo.replace merges by default - peers[peerInfo.id.toB58String()].multiaddr.replace([], peerInfo.multiaddrs) + /** + * Stores a peerInfo, if already exist, only adds the multiaddrs + * + * @param {PeerInfo} peerInfo + * @param {replace} boolean + * @returns {null} + */ + put (peerInfo, replace) { + if (this._peers[peerInfo.id.toB58String()] && !replace) { + // peerInfo.replace merges by default if none to replace are passed + this._peers[peerInfo.id.toB58String()] + .multiaddrs.replace([], peerInfo.multiaddrs.toArray()) } - peers[peerInfo.id.toB58String()] = peerInfo + + this._peers[peerInfo.id.toB58String()] = peerInfo } - this.getAll = () => { - return peers + getAll () { + return this._peers } /** @@ -29,30 +34,31 @@ function PeerBook () { * @param {PeerId} id * @returns {PeerInfo} */ - this.get = (id) => { + get (id) { return this.getByB58String(id.toB58String()) } - this.getByB58String = (b58String) => { - const peerInfo = peers[b58String] + getByB58String (b58String) { + const peerInfo = this._peers[b58String] + if (peerInfo) { return peerInfo } throw new Error('PeerInfo not found') } - this.getByMultihash = (multihash) => { + getByMultihash (multihash) { const b58multihash = bs58.encode(multihash).toString() return this.getByB58String(b58multihash) } - this.removeByB58String = (b58String) => { - if (peers[b58String]) { - delete peers[b58String] + removeByB58String (b58String) { + if (this._peers[b58String]) { + delete this._peers[b58String] } } - this.removeByMultihash = (multihash) => { + removeByMultihash (multihash) { const b58multihash = bs58.encode(multihash).toString() this.removeByB58String(b58multihash) } @@ -63,10 +69,10 @@ function PeerBook () { * @param {PeerId} id * @returns {Array} */ - this.getAddrs = (id) => { + getAddrs (id) { const info = this.get(id) return info.multiaddrs } - - // TODO serialize PeerBook into MerkleDAG Objects } + +module.exports = PeerBook diff --git a/test/peer-book.spec.js b/test/peer-book.spec.js index 70023ea..956226c 100644 --- a/test/peer-book.spec.js +++ b/test/peer-book.spec.js @@ -57,13 +57,13 @@ describe('peer-book', function () { it('get', () => { const peer = pb.get(p1.id) - expect(peer).to.deep.equal(p1) + expect(peer).to.eql(p1) }) it('getByB58String', () => { const p1Id = p1.id.toB58String() const peer = pb.getByB58String(p1Id) - expect(peer).to.deep.equal(p1) + expect(peer).to.eql(p1) }) it('getByB58String non existent', (done) => { @@ -114,15 +114,15 @@ describe('peer-book', function () { it('add repeated Id, merge info', () => { const peerA = new PeerInfo(p3.id) - peerA.multiaddr.add(new Multiaddr('/ip4/127.0.0.1/tcp/4001')) + peerA.multiaddrs.add(new Multiaddr('/ip4/127.0.0.1/tcp/4001')) pb.put(peerA) const peerB = pb.getByB58String(p3.id.toB58String()) - expect(peerA).to.deep.equal(peerB) + expect(peerA).to.eql(peerB) }) it('add repeated Id, replace info', () => { const peerA = new PeerInfo(p3.id) - peerA.multiaddr.add(new Multiaddr('/ip4/188.0.0.1/tcp/5001')) + peerA.multiaddrs.add(new Multiaddr('/ip4/188.0.0.1/tcp/5001')) pb.put(peerA, true) const peerB = pb.getByB58String(p3.id.toB58String()) expect(peerA).to.deep.equal(peerB) @@ -131,7 +131,7 @@ describe('peer-book', function () { it('getAddrs', () => { const pb = new PeerBook() const peer = new PeerInfo(p3.id) - peer.multiaddr.add(new Multiaddr('/ip4/127.0.0.1/tcp/1234')) + peer.multiaddrs.add(new Multiaddr('/ip4/127.0.0.1/tcp/1234')) pb.put(peer) expect(pb.getAddrs(p3.id)).to.be.eql(peer.multiaddrs) }) From d82da995acc42deaa13886ff4ba4a1026ac285cd Mon Sep 17 00:00:00 2001 From: David Dias Date: Fri, 31 Mar 2017 10:16:51 +0100 Subject: [PATCH 2/2] feat: all new shiny api --- package.json | 13 +++-- src/index.js | 105 ++++++++++++++++++++++++----------- test/peer-book.spec.js | 121 +++++++++++++++++++++++------------------ test/utils.js | 32 +++++++++++ 4 files changed, 180 insertions(+), 91 deletions(-) create mode 100644 test/utils.js diff --git a/package.json b/package.json index f750860..eb3d5ba 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/diasdavid/js-peer-book.git" + "url": "git+https://github.com/libp2p/js-peer-book.git" }, "pre-commit": [ "lint", @@ -33,11 +33,13 @@ "author": "David Dias ", "license": "MIT", "bugs": { - "url": "https://github.com/diasdavid/js-peer-book/issues" + "url": "https://github.com/libp2p/js-peer-book/issues" }, - "homepage": "https://github.com/diasdavid/js-peer-book#readme", + "homepage": "https://github.com/libp2p/js-peer-book#readme", "dependencies": { - "bs58": "^4.0.0" + "bs58": "^4.0.0", + "peer-id": "^0.8.6", + "peer-info": "^0.9.1" }, "devDependencies": { "aegir": "^11.0.1", @@ -45,7 +47,6 @@ "chai": "^3.5.0", "dirty-chai": "^1.2.2", "multiaddr": "^2.3.0", - "peer-info": "~0.9.0", "pre-commit": "^1.2.2" }, "contributors": [ @@ -54,4 +55,4 @@ "greenkeeperio-bot ", "npmcdn-to-unpkg-bot " ] -} \ No newline at end of file +} diff --git a/src/index.js b/src/index.js index 103e2a0..206c558 100644 --- a/src/index.js +++ b/src/index.js @@ -1,45 +1,88 @@ 'use strict' const bs58 = require('bs58') +const PeerId = require('peer-id') +const PeerInfo = require('peer-info') + +function getB58Str (peer) { + let b58Str + + if (typeof peer === 'string') { + b58Str = peer + } else if (Buffer.isBuffer(peer)) { + b58Str = bs58.encode(peer).toString() + } else if (PeerId.isPeerId(peer)) { + b58Str = peer.toB58String() + } else if (PeerInfo.isPeerInfo(peer)) { + b58Str = peer.id.toB58String() + } else { + throw new Error('not valid PeerId or PeerInfo, or B58Str') + } + + return b58Str +} class PeerBook { constructor () { this._peers = {} } + // checks if peer exists + // peer can be PeerId, b58String or PeerInfo + has (peer) { + const b58Str = getB58Str(peer) + return Boolean(this._peers[b58Str]) + } + /** - * Stores a peerInfo, if already exist, only adds the multiaddrs + * Stores a peerInfo, if already exist, merges the new into the old. * * @param {PeerInfo} peerInfo * @param {replace} boolean - * @returns {null} + * @returns {PeerInfo} */ put (peerInfo, replace) { - if (this._peers[peerInfo.id.toB58String()] && !replace) { - // peerInfo.replace merges by default if none to replace are passed - this._peers[peerInfo.id.toB58String()] - .multiaddrs.replace([], peerInfo.multiaddrs.toArray()) + const localPeerInfo = this._peers[peerInfo.id.toB58String()] + + // insert if doesn't exist or replace if replace flag is true + if (!localPeerInfo || replace) { + this._peers[peerInfo.id.toB58String()] = peerInfo + return peerInfo } - this._peers[peerInfo.id.toB58String()] = peerInfo - } + // peerInfo.replace merges by default if none to replace are passed + peerInfo.multiaddrs.forEach((ma) => localPeerInfo.multiaddrs.add(ma)) - getAll () { - return this._peers + // pass active connection state + const ma = peerInfo.isConnected() + if (ma) { + localPeerInfo.connect(ma) + } + + // pass known protocols + peerInfo.protocols.forEach((p) => localPeerInfo.protocols.add(p)) + + if (!localPeerInfo.id.privKey && peerInfo.id.privKey) { + localPeerInfo.id.privKey = peerInfo.id.privKey + } + + if (!localPeerInfo.id.pubKey && peerInfo.id.pubKey) { + localPeerInfo.id.pubKey = peerInfo.id.pubKey + } + + return localPeerInfo } /** - * Get the info to the given PeerId. + * Get the info to the given PeerId, PeerInfo or b58Str id * * @param {PeerId} id * @returns {PeerInfo} */ - get (id) { - return this.getByB58String(id.toB58String()) - } + get (peer) { + const b58Str = getB58Str(peer) - getByB58String (b58String) { - const peerInfo = this._peers[b58String] + const peerInfo = this._peers[b58Str] if (peerInfo) { return peerInfo @@ -47,32 +90,32 @@ class PeerBook { throw new Error('PeerInfo not found') } - getByMultihash (multihash) { - const b58multihash = bs58.encode(multihash).toString() - return this.getByB58String(b58multihash) - } - - removeByB58String (b58String) { - if (this._peers[b58String]) { - delete this._peers[b58String] - } + getAll () { + return this._peers } - removeByMultihash (multihash) { - const b58multihash = bs58.encode(multihash).toString() - this.removeByB58String(b58multihash) + getAllArray () { + return Object.keys(this._peers).map((b58Str) => this._peers[b58Str]) } /** * Return all multiaddrs for a given PeerId. * - * @param {PeerId} id + * @param {PeerId, PeerInfo, Multihash, B58Str} id * @returns {Array} */ - getAddrs (id) { - const info = this.get(id) + getMultiaddrs (peer) { + const info = this.get(peer) return info.multiaddrs } + + remove (peer) { + const b58Str = getB58Str(peer) + + if (this._peers[b58Str]) { + delete this._peers[b58Str] + } + } } module.exports = PeerBook diff --git a/test/peer-book.spec.js b/test/peer-book.spec.js index 956226c..c1a4aab 100644 --- a/test/peer-book.spec.js +++ b/test/peer-book.spec.js @@ -8,11 +8,12 @@ chai.use(dirtyChai) const Multiaddr = require('multiaddr') const PeerInfo = require('peer-info') const async = require('async') +const utils = require('./utils') +const createPeerInfo = utils.createPeerInfo const PeerBook = require('../src') -describe('peer-book', function () { - this.timeout(50000) +describe('peer-book', () => { let pb let p1 let p2 @@ -21,10 +22,22 @@ describe('peer-book', function () { before((done) => { async.parallel([ - (cb) => PeerInfo.create(cb), - (cb) => PeerInfo.create(cb), - (cb) => PeerInfo.create(cb), - (cb) => PeerInfo.create(cb) + (cb) => createPeerInfo([ + '/tcp/1000', + '/tcp/1001' + ], cb), + (cb) => createPeerInfo([ + '/tcp/2000', + '/tcp/2001' + ], cb), + (cb) => createPeerInfo([ + '/tcp/3000', + '/tcp/3001' + ], cb), + (cb) => createPeerInfo([ + '/tcp/4000', + '/tcp/4001' + ], cb) ], (err, infos) => { if (err) { return done(err) @@ -44,44 +57,48 @@ describe('peer-book', function () { expect(pb).to.exist() }) - it('put peerInfo', () => { - pb.put(p1) - pb.put(p2) - pb.put(p3) + it('.put', () => { + expect(pb.put(p1)).to.eql(p1) + expect(pb.put(p2)).to.eql(p2) + expect(pb.put(p3)).to.eql(p3) }) - it('get all peerInfo', () => { + it('.getAll', () => { const peers = pb.getAll() expect(Object.keys(peers).length).to.equal(3) }) - it('get', () => { + it('.getAllArray', () => { + expect(pb.getAllArray()).to.have.length(3) + }) + + it('.get by PeerId', () => { const peer = pb.get(p1.id) expect(peer).to.eql(p1) }) - it('getByB58String', () => { - const p1Id = p1.id.toB58String() - const peer = pb.getByB58String(p1Id) + it('.get by B58String ', () => { + const b58Str = p1.id.toB58String() + const peer = pb.get(b58Str) expect(peer).to.eql(p1) }) - it('getByB58String non existent', (done) => { + it('.get by B58String non existent', (done) => { try { - pb.getByB58String(p4.id.toB58String()) + pb.get(p4.id.toB58String()) } catch (err) { expect(err).to.exist() done() } }) - it('getByMultihash', () => { - const p1Id = p1.id.toBytes() - const peer = pb.getByMultihash(p1Id) - expect(peer).to.deep.equal(p1) + it('.get by Multihash', () => { + const mh = p1.id.toBytes() + const peer = pb.get(mh) + expect(peer).to.eql(p1) }) - it('getByMultihash non existent', (done) => { + it('.get by Multihash non existent', (done) => { try { pb.getByMultihash(p4.id.toBytes()) } catch (err) { @@ -90,49 +107,45 @@ describe('peer-book', function () { } }) - it('removeByB58String', (done) => { - const p1Id = p1.id.toB58String() - pb.removeByB58String(p1Id) - try { - pb.getByB58String(p1Id) - } catch (err) { - expect(err).to.exist() - done() - } + it('.remove by B58String', () => { + const b58Str = p1.id.toB58String() + + pb.remove(b58Str) + expect(pb.has(b58Str)).to.equal(false) }) - it('removeByMultihash', (done) => { - const p1Id = p1.id.toBytes() - pb.removeByMultihash(p1Id) - try { - pb.getByMultihash(p1Id) - } catch (err) { - expect(err).to.exist() - done() - } + it('.remove by Multihash', () => { + const mh = p1.id.toBytes() + + pb.remove(mh) + expect(pb.has(mh)).to.equal(false) }) - it('add repeated Id, merge info', () => { - const peerA = new PeerInfo(p3.id) - peerA.multiaddrs.add(new Multiaddr('/ip4/127.0.0.1/tcp/4001')) - pb.put(peerA) - const peerB = pb.getByB58String(p3.id.toB58String()) - expect(peerA).to.eql(peerB) + it('.put repeated Id, merge info', () => { + const peer3A = new PeerInfo(p3.id) + peer3A.multiaddrs.add(new Multiaddr('/ip4/127.0.0.1/tcp/4001')) + + pb.put(peer3A) + const peer3B = pb.get(p3.id.toBytes()) + + expect(peer3B.multiaddrs.toArray()).to.have.length(3) }) - it('add repeated Id, replace info', () => { - const peerA = new PeerInfo(p3.id) - peerA.multiaddrs.add(new Multiaddr('/ip4/188.0.0.1/tcp/5001')) - pb.put(peerA, true) - const peerB = pb.getByB58String(p3.id.toB58String()) - expect(peerA).to.deep.equal(peerB) + it('.put repeated Id, replace info', () => { + const peer3A = new PeerInfo(p3.id) + peer3A.multiaddrs.add(new Multiaddr('/ip4/188.0.0.1/tcp/5001')) + + pb.put(peer3A, true) + const peer3B = pb.get(p3.id.toB58String()) + expect(peer3A.multiaddrs.toArray()).to.eql(peer3B.multiaddrs.toArray()) }) - it('getAddrs', () => { + it('.getMultiaddrs', () => { const pb = new PeerBook() const peer = new PeerInfo(p3.id) peer.multiaddrs.add(new Multiaddr('/ip4/127.0.0.1/tcp/1234')) + pb.put(peer) - expect(pb.getAddrs(p3.id)).to.be.eql(peer.multiaddrs) + expect(pb.getMultiaddrs(p3.id)).to.be.eql(peer.multiaddrs) }) }) diff --git a/test/utils.js b/test/utils.js new file mode 100644 index 0000000..409580b --- /dev/null +++ b/test/utils.js @@ -0,0 +1,32 @@ +/* eslint-env mocha */ +'use strict' + +const chai = require('chai') +chai.use(require('dirty-chai')) +const PeerInfo = require('peer-info') +const PeerId = require('peer-id') +const waterfall = require('async/waterfall') + +function createPeerInfo (multiaddrs, options, callback) { + if (typeof options === 'function') { + callback = options + options = {} + } + + if (!Array.isArray(multiaddrs)) { + multiaddrs = [multiaddrs] + } + + waterfall([ + (cb) => PeerId.create({ bits: 1024 }, cb), + (peerId, cb) => PeerInfo.create(peerId, cb), + (peerInfo, cb) => { + multiaddrs.map((ma) => peerInfo.multiaddrs.add(ma)) + cb(null, peerInfo) + } + ], callback) +} + +module.exports = { + createPeerInfo: createPeerInfo +}