diff --git a/.gitignore b/.gitignore index a477a2de..0a15690c 100644 --- a/.gitignore +++ b/.gitignore @@ -29,16 +29,10 @@ npm-debug.log .nodemonignore .DS_Store -db/txs/* -db/txs -db/testnet/txs/* -db/testnet/txs -db/blocks/* -db/blocks -db/testnet/blocks/* -db/testnet/blocks -db/* +db/ db-test/ +testnet-db/ +db.bkp/ README.html public diff --git a/api/config/default.yml b/api/config/default.yml index 1ba65a51..7d5332ac 100644 --- a/api/config/default.yml +++ b/api/config/default.yml @@ -2,7 +2,15 @@ BitcoreHTTP: port: 8080 logging: true BitcoreNode: + LevelUp: ./testnet-db + network: testnet NetworkMonitor: - network: livenet host: localhost - port: 8333 + port: 18333 + Reporter: none # none, simple, matrix + RPC: + user: user + pass: password + protocol: http + host: 127.0.0.1 + port: 18332 diff --git a/api/config/livenet.yml b/api/config/livenet.yml new file mode 100644 index 00000000..1ba65a51 --- /dev/null +++ b/api/config/livenet.yml @@ -0,0 +1,8 @@ +BitcoreHTTP: + port: 8080 + logging: true + BitcoreNode: + NetworkMonitor: + network: livenet + host: localhost + port: 8333 diff --git a/api/config/testnet.yml b/api/config/testnet.yml new file mode 100644 index 00000000..1ba65a51 --- /dev/null +++ b/api/config/testnet.yml @@ -0,0 +1,8 @@ +BitcoreHTTP: + port: 8080 + logging: true + BitcoreNode: + NetworkMonitor: + network: livenet + host: localhost + port: 8333 diff --git a/api/lib/http.js b/api/lib/http.js index 686acdb6..e56b61f8 100644 --- a/api/lib/http.js +++ b/api/lib/http.js @@ -98,6 +98,7 @@ BitcoreHTTP.prototype.onListening = function() { BitcoreHTTP.prototype.start = function() { + this.node.start(); this.server.listen(this.port); }; diff --git a/api/test/http.js b/api/test/http.js index 2bcac25c..2b70bf48 100644 --- a/api/test/http.js +++ b/api/test/http.js @@ -2,6 +2,7 @@ var chai = require('chai'); var should = chai.should(); +var sinon = require('sinon'); var EventEmitter = require('eventemitter2').EventEmitter2; @@ -19,6 +20,7 @@ describe('BitcoreHTTP', function() { var nodeMock; beforeEach(function() { nodeMock = new EventEmitter(); + nodeMock.start = sinon.spy(); }); describe('instantiates', function() { it('from constructor', function() { diff --git a/api/test/v1/node.js b/api/test/v1/node.js index 16a5a375..ff45b99c 100644 --- a/api/test/v1/node.js +++ b/api/test/v1/node.js @@ -18,7 +18,7 @@ describe('BitcoreHTTP v1 node routes', function() { nodeMock = new EventEmitter(); nodeMock.status = { sync: 0.75, - peer_count: 8, + peerCount: 8, version: 'test' }; nodeMock.getStatus = function() { diff --git a/config/default.yml b/config/default.yml index 48ddb954..564f1073 100644 --- a/config/default.yml +++ b/config/default.yml @@ -5,9 +5,6 @@ BitcoreNode: host: localhost port: 8333 Reporter: none # none, simple, matrix -BitcoreHTTP: - host: localhost - port: 8080 RPC: user: user pass: password diff --git a/config/livenet.yml b/config/livenet.yml index 48ddb954..564f1073 100644 --- a/config/livenet.yml +++ b/config/livenet.yml @@ -5,9 +5,6 @@ BitcoreNode: host: localhost port: 8333 Reporter: none # none, simple, matrix -BitcoreHTTP: - host: localhost - port: 8080 RPC: user: user pass: password diff --git a/config/testnet.yml b/config/testnet.yml index 313e99cd..29a08192 100644 --- a/config/testnet.yml +++ b/config/testnet.yml @@ -5,9 +5,6 @@ BitcoreNode: host: localhost port: 18333 Reporter: none # none, simple, matrix -BitcoreHTTP: - host: localhost - port: 8080 RPC: user: user pass: password diff --git a/lib/blockchain.js b/lib/blockchain.js index 4de9ae4d..2ba21d43 100644 --- a/lib/blockchain.js +++ b/lib/blockchain.js @@ -159,7 +159,7 @@ BlockChain.prototype.getBlockLocator = function() { $.checkState(!_.isUndefined(this.height[this.tip])); var result = []; - var currentHeight = this.height[this.tip]; + var currentHeight = this.getCurrentHeight(); var exponentialBackOff = 1; for (var i = 0; i < 10; i++) { if (currentHeight >= 0) { @@ -174,4 +174,8 @@ BlockChain.prototype.getBlockLocator = function() { return result; }; +BlockChain.prototype.getCurrentHeight = function() { + return this.height[this.tip]; +}; + module.exports = BlockChain; diff --git a/lib/networkmonitor.js b/lib/networkmonitor.js index 6d792b9c..fa2bff76 100644 --- a/lib/networkmonitor.js +++ b/lib/networkmonitor.js @@ -38,7 +38,10 @@ NetworkMonitor.prototype.setupPeer = function(peer) { var self = this; peer.on('ready', function() { - self.emit('ready'); + self.emit('ready', self.maxHeight); + }); + peer.on('version', function(m) { + self.maxHeight = m.startHeight; }); peer.on('inv', function(m) { self.emit('inv', m.inventory); @@ -73,7 +76,6 @@ NetworkMonitor.prototype.requestBlocks = function(locator) { _.isString(locator[0]), 'start must be a block hash string array'); this.peer.sendMessage(this.messages.GetBlocks({ starts: locator, - //stop: '000000002c05cc2e78923c34df87fd108b22221ac6076c18f3ade378a4d915e9' // TODO: remove this!!! })); }; @@ -87,6 +89,11 @@ NetworkMonitor.prototype.stop = function(reason) { console.log('Stopping network, reason:', reason); }; +NetworkMonitor.prototype.getConnectedPeers = function() { + // TODO: update when using Pool instead of Peer + return this.peer.status === Peer.STATUS.READY ? 1 : 0; +}; + NetworkMonitor.prototype.abort = function(reason) { this.peer.disconnect(); if (reason) { diff --git a/lib/node.js b/lib/node.js index f692c875..14ae583d 100644 --- a/lib/node.js +++ b/lib/node.js @@ -2,6 +2,7 @@ var util = require('util'); var EventEmitter = require('eventemitter2').EventEmitter2; +var pjson = require('../package.json'); var bitcore = require('bitcore'); var _ = bitcore.deps._; @@ -36,7 +37,6 @@ var BitcoreNode = function(bus, networkMonitor, blockService, transactionService this.blockService = blockService; this.blockCache = {}; - this.inventory = {}; // blockHash -> bool (has data) this.initialize(); }; util.inherits(BitcoreNode, EventEmitter); @@ -79,7 +79,8 @@ BitcoreNode.prototype.initialize = function() { var prevHeight = 0; var statTimer = 5 * 1000; setInterval(function() { - console.log(process.memoryUsage().heapTotal / 1024 / 1024, 'mb used'); + console.log('MB used:', process.memoryUsage().heapTotal / 1024 / 1024, + 100 * self.getSyncProgress() + '% synced'); if (!self.blockchain) { // not ready yet console.log('No blockchain yet'); @@ -100,9 +101,8 @@ BitcoreNode.prototype.initialize = function() { var prevHash = bitcore.util.buffer.reverse(block.header.prevHash).toString('hex'); self.blockCache[block.hash] = block; - self.inventory[block.hash] = true; if (!self.blockchain.hasData(prevHash)) { - self.requestFromTip(); + self._requestFromTip(); return; } var blockchainChanges = self.blockchain.proposeNewBlock(block); @@ -111,8 +111,6 @@ BitcoreNode.prototype.initialize = function() { block.height = self.blockchain.height[block.id]; block.work = self.blockchain.work[block.id]; - //console.log('block', block.id, block.height); - return Promise.each(blockchainChanges.unconfirmed, function(hash) { return self.blockService.unconfirm(self.blockCache[hash]); }) @@ -128,13 +126,6 @@ BitcoreNode.prototype.initialize = function() { delete self.blockCache[deleteHash]; } }) - .then(function() { - // TODO: include this - if (false && _.size(self.inventory) && _.all(_.values(self.inventory))) { - self.inventory = {}; - self.requestFromTip(); - } - }) .catch(function(error) { self.stop(error); }); @@ -155,9 +146,7 @@ BitcoreNode.prototype.start = function() { var self = this; var genesis = bitcore.Block.fromBuffer(genesisBlocks[bitcore.Networks.defaultNetwork.name]); - console.log('getting blockchain'); this.blockService.getBlockchain().then(function(blockchain) { - console.log('got blockchain', !!blockchain); if (!blockchain) { self.blockchain = new BlockChain(); self.bus.process(genesis); @@ -173,7 +162,20 @@ BitcoreNode.prototype.stop = function(reason) { this.networkMonitor.abort(reason); }; -BitcoreNode.prototype.requestFromTip = function() { +BitcoreNode.prototype.getStatus = function() { + return Promise.resolve({ + sync: this.getSyncProgress(), + peerCount: this.networkMonitor.getConnectedPeers(), + version: pjson.version, + }); +}; + +BitcoreNode.prototype.getSyncProgress = function() { + return !_.isUndefined(this.reportedMaxHeight) ? + (this.blockchain.getCurrentHeight() / this.reportedMaxHeight) : 0; +}; + +BitcoreNode.prototype._requestFromTip = function() { var locator = this.blockchain.getBlockLocator(); //console.log('requesting blocks, locator size:', locator.length); this.networkMonitor.requestBlocks(locator); @@ -181,8 +183,9 @@ BitcoreNode.prototype.requestFromTip = function() { BitcoreNode.prototype.sync = function() { var self = this; - this.networkMonitor.on('ready', function() { - self.requestFromTip(); + this.networkMonitor.on('ready', function(reportedMaxHeight) { + self.reportedMaxHeight = reportedMaxHeight; + self._requestFromTip(); }); }; diff --git a/lib/services/block.js b/lib/services/block.js index ea57238e..d6b966e4 100644 --- a/lib/services/block.js +++ b/lib/services/block.js @@ -475,7 +475,7 @@ BlockService.prototype.getBlockchain = function() { return self._getLatestHash() .then(function(tip) { if (!tip) { - console.log('No tip found'); + console.log('No tip found, syncing blockchain from genesis block'); return null; } console.log('Tip is', tip);