Fixed progress bar and added tests for getTransaction in

TransactionService.
This commit is contained in:
Chris Kleeschulte 2017-05-15 15:05:41 -04:00
parent 6d95cd0302
commit b6f56fb02b
6 changed files with 130 additions and 43 deletions

View File

@ -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();
});

View File

@ -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);
}
};

View File

@ -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);
};

View File

@ -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",

View File

@ -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';

View File

@ -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();
});
});
});
});