diff --git a/docs/pool.md b/docs/pool.md index 610b046..13c1314 100644 --- a/docs/pool.md +++ b/docs/pool.md @@ -28,3 +28,25 @@ pool.disconnect() ``` For more information about Peer events please read the [Peer](peer.md) documentation. Peer events are relayed to the pool, a peer event `inv` in the pool would be `peerinv`. When a peer is disconnected the pool will try to connect to the list of known addresses to maintain connection. + +## Trusted Peers + +By default, peers will be added via DNS discovery and as peers are announced in the network. To connect only to specific trusted peers, configurations options can be included: + +```javascript + +var pool = new Pool(Networks.livenet, { + discover: false, + listenAddr: false, + addrs: [ + { + ip: { + v4: '127.0.0.1' + } + } + ] +}); + +pool.connect(); + +``` diff --git a/lib/pool.js b/lib/pool.js index 56fdcd7..24c9fca 100644 --- a/lib/pool.js +++ b/lib/pool.js @@ -33,27 +33,48 @@ function now() { * @returns {Pool} * @constructor */ -function Pool(network) { +function Pool(network, options) { var self = this; this.network = Networks.get(network) || Networks.defaultNetwork; this.keepalive = false; + this._connectedPeers = {}; this._addrs = []; - this.on('peeraddr', function peerAddrEvent(peer, message) { - var addrs = message.addresses; - var length = addrs.length; - for (var i = 0; i < length; i++) { - var addr = addrs[i]; - // In case of an invalid time, assume "5 days ago" - if (addr.time <= 100000000 || addr.time > (now() + 10 * 60)) { - addr.time = now() - 5 * 24 * 60 * 60; - } - this._addAddr(addr); + this.listenAddr = true; + this.discover = true; + + // define configuration options + if (options) { + if (options.listenAddr === false) { + this.listenAddr = false; } - }); + if (options.discover === false) { + this.discover = false; + } + if (options.addrs) { + for(var i = 0; i < options.addrs.length; i++) { + this._addAddr(options.addrs[i]); + } + } + } + + if (this.listenAddr) { + this.on('peeraddr', function peerAddrEvent(peer, message) { + var addrs = message.addresses; + var length = addrs.length; + for (var i = 0; i < length; i++) { + var addr = addrs[i]; + // In case of an invalid time, assume "5 days ago" + if (addr.time <= 100000000 || addr.time > (now() + 10 * 60)) { + addr.time = now() - 5 * 24 * 60 * 60; + } + this._addAddr(addr); + } + }); + } this.on('seed', function seedEvent(ips) { ips.forEach(function(ip) { @@ -98,7 +119,7 @@ Pool.PeerEvents = ['version', 'inv', 'getdata', 'ping', 'pong', 'addr', Pool.prototype.connect = function connect() { this.keepalive = true; var self = this; - if (self._addrs.length === 0) { + if (this.discover) { self._addAddrsFromSeeds(); } else { self._fillConnections(); diff --git a/test/pool.js b/test/pool.js index fb5e13b..9562f0b 100644 --- a/test/pool.js +++ b/test/pool.js @@ -43,16 +43,45 @@ describe('Pool', function() { stub.restore(); }); - it('should not discover peers via dns', function() { - var pool = new Pool(); - pool._addAddr({ - ip: { - v4: '10.10.10.1' - } + it('can optionally connect without dns seeds', function() { + var stub = sinon.stub(dns, 'resolve', function(seed, callback) { + throw new Error('DNS should not be called'); }); + var options = { + discover: false, + addrs: [ + { + ip: { + v4: '10.10.10.1' + } + } + ] + }; + var pool = new Pool(Networks.livenet, options); pool.connect(); pool.disconnect(); pool._addrs.length.should.equal(1); + stub.restore(); + }); + + it('will add addrs via options argument', function() { + var options = { + discover: false, + addrs: [ + { + ip: { + v4: '10.10.10.1' + } + }, + { + ip: { + v4: '10.10.10.245' + } + } + ] + }; + var pool = new Pool(Networks.livenet, options); + pool._addrs.length.should.equal(2); }); it('should add new addrs as they are announced over the network', function(done) { @@ -70,13 +99,18 @@ describe('Pool', function() { this.emit(message.command, message); }); - var pool = new Pool(); + var options = { + discover: false, + addrs: [ + { + ip: { + v4: 'localhost' + } + } + ] + }; - pool._addAddr({ - ip: { - v4: 'localhost' - } - }); + var pool = new Pool(Networks.testnet, options); // listen for the event pool.on('peeraddr', function(peer, message) { @@ -100,4 +134,55 @@ describe('Pool', function() { }); + it('can optionally not listen to new addrs messages', function(done) { + + // only emit an event, no need to connect + var peerConnectStub = sinon.stub(Peer.prototype, 'connect', function() { + this._readMessage(); + this.emit('ready'); + }); + + // mock a addr peer event + var peerMessageStub = sinon.stub(Peer.prototype, '_readMessage', function() { + var payload = new Buffer(MessagesData.ADDR.payload, 'hex'); + var message = new Messages.Addresses().fromBuffer(payload); + this.emit(message.command, message); + }); + + var options = { + discover: false, + listenAddr: false, + addrs: [ + { + ip: { + v4: 'localhost' + } + } + ] + }; + + var pool = new Pool(Networks.testnet, options); + + // listen for the event + pool.on('peeraddr', function(peer, message) { + pool._addrs.length.should.equal(1); + + // restore stubs + peerConnectStub.restore(); + peerMessageStub.restore(); + + for (var i = 0; i < pool._addrs.length; i++) { + should.exist(pool._addrs[i].hash); + should.exist(pool._addrs[i].ip); + should.exist(pool._addrs[i].ip.v4); + } + + // done + done(); + }); + + pool.connect(); + + }); + });