diff --git a/lib/services/db/index.js b/lib/services/db/index.js index 2006f3ec..027ca1ea 100644 --- a/lib/services/db/index.js +++ b/lib/services/db/index.js @@ -320,7 +320,7 @@ DB.prototype.loadTips = function(callback) { } self[tip] = block; - log.info('loaded tip, hash: ' + block.hash + ' height: ' + block.__height); + log.info('loaded ' + tip + ', hash: ' + block.hash + ' height: ' + block.__height); next(); }); diff --git a/lib/services/db/sync.js b/lib/services/db/sync.js index b1137bb1..fa72cc6c 100644 --- a/lib/services/db/sync.js +++ b/lib/services/db/sync.js @@ -7,7 +7,6 @@ var EventEmitter = require('events').EventEmitter; var async = require('async'); var bitcore = require('bitcore-lib'); var Block = bitcore.Block; -var ProgressBar = require('progress'); var index = require('../../index'); var log = index.log; @@ -66,8 +65,7 @@ function Sync(node, db) { this.syncing = false; this.paused = false; //we can't sync while one of our indexes is reading/writing separate from us this.highWaterMark = 10; - this.progressBar = null; - this.lastReportedBlock = 0; + this._lastReportedTime = Date.now(); } inherits(Sync, EventEmitter); @@ -98,16 +96,6 @@ Sync.prototype.sync = function() { blockStream .pipe(processSerial); - self.lastReportedBlock = self.db.tip.__height; - - self.progressBar = new ProgressBar('[:bar] :percent :current blks, :blockspersec blks/sec', { - curr: self.lastReportedBlock, - total: self.node.services.bitcoind.height, - clear: true - }); - - self.progressBarTimer = setInterval(self.reportStatus.bind(self), 1000); - processSerial.on('finish', self._onFinish.bind(self)); }; @@ -117,14 +105,6 @@ Sync.prototype._onFinish = function() { var self = this; self.syncing = false; - if (self.progressBar) { - self.progressBar.terminate(); - } - - if (self.progressBarTimer) { - clearInterval(self.progressBarTimer); - } - if (self.forkBlock) { self.db.handleReorg(self.forkBlock, function() { self.forkBlock = null; @@ -134,6 +114,7 @@ Sync.prototype._onFinish = function() { } self._startSubscriptions(); + self._reportStatus(true); self.emit('synced'); }; @@ -148,6 +129,7 @@ Sync.prototype._startSubscriptions = function() { self.bus = self.node.openBus({remoteAddress: 'localhost'}); self.bus.on('bitcoind/hashblock', function() { + self._reportStatus(); self.sync(); }); @@ -156,12 +138,9 @@ Sync.prototype._startSubscriptions = function() { }; -Sync.prototype.reportStatus = function() { - if (process.stderr.isTTY) { - var tick = this.db.tip.__height - this.lastReportedBlock; - this.progressBar.tick(tick, { blockspersec: tick }); - this.lastReportedBlock = this.db.tip.__height; - } else { +Sync.prototype._reportStatus = function(override) { + if (((Date.now() - this._lastReportedTime) > 1000) || override) { + this._lastReportedTime = Date.now(); log.info('Sync: current height is: ' + this.db.tip.__height); } }; diff --git a/lib/services/transaction/index.js b/lib/services/transaction/index.js index 064e8187..fbaf9912 100644 --- a/lib/services/transaction/index.js +++ b/lib/services/transaction/index.js @@ -160,6 +160,7 @@ TransactionService.prototype.getTransaction = function(txid, options, callback) }); } + txid = txid.toString('hex'); var key = self.encoding.encodeTransactionKey(txid); async.waterfall([ @@ -178,22 +179,16 @@ TransactionService.prototype.getTransaction = function(txid, options, callback) return next(null, tx); } if (!options || !options.queryMempool) { - return next(); + return next(new Error('Transaction: ' + txid + ' not found in index')); } self.node.services.mempool.getTransaction(txid, function(err, tx) { - if(err) { - return next(err); - } - if (!tx) { - return next(); - } - self._getMissingInputValues(tx, next); + if (err instanceof levelup.errors.NotFoundError) { + return callback(new Error('Transaction: ' + txid + ' not found in index or mempool')); + } else if (err) { + return callback(err); + } + self._getMissingInputValues(tx, next); }); - }, function(tx, next) { - if (tx) { - return next(null, tx); - } - self.node.services.bitcoind.getTransaction(txid, next); }], callback); }; diff --git a/package.json b/package.json index fc90cb53..1276cab2 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,6 @@ "mkdirp": "0.5.0", "multer": "^1.2.1", "path-is-absolute": "^1.0.0", - "progress": "kleetus/node-progress#master", "semver": "^5.0.1", "socket.io": "^1.4.5", "socket.io-client": "^1.4.5", diff --git a/regtest/wallet.js b/regtest/wallet.js index 867ed061..4bec09d6 100644 --- a/regtest/wallet.js +++ b/regtest/wallet.js @@ -8,7 +8,7 @@ var path = require('path'); var utils = require('./utils'); var crypto = require('crypto'); -var debug = false; +var debug = true; var bitcoreDataDir = '/tmp/bitcore'; var bitcoinDataDir = '/tmp/bitcoin'; diff --git a/test/services/transaction/index.unit.js b/test/services/transaction/index.unit.js new file mode 100644 index 00000000..29d21fd7 --- /dev/null +++ b/test/services/transaction/index.unit.js @@ -0,0 +1,114 @@ +'use strict'; + +var should = require('chai').should(); +var sinon = require('sinon'); +var TransactionService = require('../../../lib/services/transaction'); +var levelup = require('levelup'); + +describe('Transaction Index', function() { + + describe('Failures', function() { + //if we miss indexing a tx, then this is very bad news. We have no good way of + //recursively retrieving inputValues, timestamp of its block, and block's height + it('should throw error if a transaction is not in the index', function(done) { + var services = { + db: { + store: { + get: sinon.stub().callsArgWith(1, new levelup.errors.NotFoundError()) + } + } + }; + var node = { node: { services: services }}; + var service = new TransactionService(node); + + service.encoding = { encodeTransactionKey: function() { return 'key'; }}; + var tx = service.getTransaction('1234', {}, function(err, res) { + err.should.be.an.instanceof(Error); + err.message.should.equal('Transaction: 1234 not found in index'); + done(); + }); + }); + + it('should search the mempool if opted for', function(done) { + var getTransaction = sinon.stub().callsArgWith(1, new levelup.errors.NotFoundError()); + var services = { + db: { + store: { + get: sinon.stub().callsArgWith(1, new levelup.errors.NotFoundError()) + } + }, + mempool: { + getTransaction: getTransaction + } + }; + var node = { node: { services: services }}; + var service = new TransactionService(node); + + service.encoding = { encodeTransactionKey: function() { return 'key'; }}; + var tx = service.getTransaction('1234', { queryMempool: true }, function(err, res) { + err.should.be.an.instanceof(Error); + err.message.should.equal('Transaction: 1234 not found in index or mempool'); + done(); + }); + + }); + }); + + describe('Success', function() { + it('should search main index', function(done) { + var services = { + db: { + store: { + get: sinon.stub().callsArgWith(1, null, 'tx') + } + } + }; + var node = { node: { services: services }}; + var service = new TransactionService(node); + + service.encoding = { + encodeTransactionKey: function() { return 'key'; }, + decodeTransactionValue: function() { return 'value'; } + }; + var tx = service.getTransaction('1234', {}, function(err, res) { + if(err) { + return done(err); + } + res.should.equal('value'); + done(); + }); + + }); + + it('should search mempool', function(done) { + var missingInputs = sinon.stub().callsArgWith(1, null, 'tx'); + var getTransaction = sinon.stub().callsArgWith(1, null, 'tx'); + var services = { + db: { + store: { + get: sinon.stub().callsArgWith(1, new levelup.errors.NotFoundError()) + } + }, + mempool: { + getTransaction: getTransaction + } + }; + var node = { node: { services: services }}; + var service = new TransactionService(node); + + service.encoding = { + encodeTransactionKey: function() { return 'key'; } + }; + service._getMissingInputValues = missingInputs; + var tx = service.getTransaction('1234', { queryMempool: true }, function(err, res) { + if(err) { + return done(err); + } + missingInputs.callCount.should.equal(1); + res.should.equal('tx'); + done(); + }); + }); + }); +}); +