fix confirmations

Conflicts:
	test/integration/server.js
This commit is contained in:
Ivan Socolsky 2016-08-05 22:34:49 -03:00
parent 8342d22041
commit 2b2c945339
No known key found for this signature in database
GPG Key ID: FAECE6A05FAA4F56
3 changed files with 129 additions and 17 deletions

View File

@ -2617,6 +2617,7 @@ WalletService.prototype._normalizeTxHistory = function(txs) {
return { return {
txid: tx.txid, txid: tx.txid,
confirmations: tx.confirmations, confirmations: tx.confirmations,
blockheight: tx.blockheight,
fees: parseInt((tx.fees * 1e8).toFixed(0)), fees: parseInt((tx.fees * 1e8).toFixed(0)),
time: t, time: t,
inputs: inputs, inputs: inputs,
@ -2625,6 +2626,19 @@ WalletService.prototype._normalizeTxHistory = function(txs) {
}); });
}; };
var _lastKnownBlockchainHeight;
WalletService.prototype._getLastKnownBlockchainHeight = function(network, cb) {
var self = this;
var bc = self._getBlockchainExplorer(network);
bc.getBlockchainHeight(function(err, height) {
if (!err && height > 0) {
_lastKnownBlockchainHeight = height;
}
return cb(null, _lastKnownBlockchainHeight);
});
};
/** /**
* Retrieves all transactions (incoming & outgoing) * Retrieves all transactions (incoming & outgoing)
* Times are in UNIX EPOCH * Times are in UNIX EPOCH
@ -2774,6 +2788,7 @@ WalletService.prototype.getTxHistory = function(opts, cb) {
function getNormalizedTxs(addresses, from, to, cb) { function getNormalizedTxs(addresses, from, to, cb) {
var txs, fromCache, totalItems; var txs, fromCache, totalItems;
var useCache = addresses.length >= Defaults.HISTORY_CACHE_ADDRESS_THRESOLD; var useCache = addresses.length >= Defaults.HISTORY_CACHE_ADDRESS_THRESOLD;
var network = Bitcore.Address(addresses[0].address).toObject().network;
async.series([ async.series([
@ -2794,10 +2809,9 @@ WalletService.prototype.getTxHistory = function(opts, cb) {
if (txs) return next(); if (txs) return next();
var addressStrs = _.pluck(addresses, 'address'); var addressStrs = _.pluck(addresses, 'address');
var network = Bitcore.Address(addressStrs[0]).toObject().network;
var bc = self._getBlockchainExplorer(network); var bc = self._getBlockchainExplorer(network);
bc.getTransactions(addressStrs, from, to, function(err, rawTxs, total) { bc.getTransactions(addressStrs, from, to, function(err, rawTxs, total) {
if (err) return cb(err); if (err) return next(err);
txs = self._normalizeTxHistory(rawTxs); txs = self._normalizeTxHistory(rawTxs);
totalItems = total; totalItems = total;
return next(); return next();
@ -2815,9 +2829,24 @@ WalletService.prototype.getTxHistory = function(opts, cb) {
var fwdIndex = totalItems - to; var fwdIndex = totalItems - to;
if (fwdIndex < 0) fwdIndex = 0; if (fwdIndex < 0) fwdIndex = 0;
self.storage.storeTxHistoryCache(self.walletId, totalItems, fwdIndex, txsToCache, next); self.storage.storeTxHistoryCache(self.walletId, totalItems, fwdIndex, txsToCache, next);
} },
function(next) {
if (!txs) return next();
// Fix tx confirmations
self._getLastKnownBlockchainHeight(network, function(err, height) {
if (err || !height) return next(err);
_.each(txs, function(tx) {
if (tx.blockheight >= 0) {
tx.confirmations = height - tx.blockheight;
}
});
next();
});
},
], function(err) { ], function(err) {
if (err) return cb(err); if (err) return cb(err);
return cb(null, { return cb(null, {
items: txs, items: txs,
fromCache: fromCache fromCache: fromCache

View File

@ -233,9 +233,9 @@ helpers._parseAmount = function(str) {
switch (match[3]) { switch (match[3]) {
default: default:
case 'btc': case 'btc':
result.amount = Utils.strip(+match[2] * 1e8); result.amount = Utils.strip(+match[2] * 1e8);
break; break;
case 'bit': case 'bit':
result.amount = Utils.strip(+match[2] * 1e2); result.amount = Utils.strip(+match[2] * 1e2);
break break
@ -541,6 +541,7 @@ helpers.historyCacheTest = function(items) {
} }
}], }],
confirmations: 1, confirmations: 1,
blockheight: 423499,
time: 1424472242, time: 1424472242,
blocktime: 1424472242, blocktime: 1424472242,
valueOut: 0.00031454, valueOut: 0.00031454,
@ -553,6 +554,7 @@ helpers.historyCacheTest = function(items) {
var t = _.clone(template); var t = _.clone(template);
t.txid = 'txid:' + i; t.txid = 'txid:' + i;
t.confirmations = items - i - 1; t.confirmations = items - i - 1;
t.blockheight = i;
t.time = t.blocktime = i; t.time = t.blocktime = i;
ret.unshift(t); ret.unshift(t);
}); });

View File

@ -4077,6 +4077,7 @@ describe('Wallet service', function() {
}); });
it('should include the note in tx history listing', function(done) { it('should include the note in tx history listing', function(done) {
helpers.createAddresses(server, wallet, 1, 1, function(mainAddresses, changeAddress) { helpers.createAddresses(server, wallet, 1, 1, function(mainAddresses, changeAddress) {
blockchainExplorer.getBlockchainHeight = sinon.stub().callsArgWith(0, null, 1000);
server._normalizeTxHistory = sinon.stub().returnsArg(0); server._normalizeTxHistory = sinon.stub().returnsArg(0);
var txs = [{ var txs = [{
txid: '123', txid: '123',
@ -4092,7 +4093,7 @@ describe('Wallet service', function() {
amount: 200, amount: 200,
}], }],
}]; }];
helpers.stubHistory(txs, 100); helpers.stubHistory(txs);
server.editTxNote({ server.editTxNote({
txid: '123', txid: '123',
body: 'just some note' body: 'just some note'
@ -5898,6 +5899,7 @@ describe('Wallet service', function() {
describe('#getTxHistory', function() { describe('#getTxHistory', function() {
var server, wallet, mainAddresses, changeAddresses; var server, wallet, mainAddresses, changeAddresses;
beforeEach(function(done) { beforeEach(function(done) {
blockchainExplorer.getBlockchainHeight = sinon.stub().callsArgWith(0, null, 1000);
helpers.createAndJoinWallet(1, 1, function(s, w) { helpers.createAndJoinWallet(1, 1, function(s, w) {
server = s; server = s;
wallet = w; wallet = w;
@ -6239,12 +6241,16 @@ describe('Wallet service', function() {
}); });
it('should store partial cache tx history from insight', function(done) { it('should store partial cache tx history from insight', function(done) {
var h = helpers.historyCacheTest(200);
helpers.stubHistory(h);
var storeTxHistoryCacheSpy = sinon.spy(server.storage, 'storeTxHistoryCache');
var skip = 31; var skip = 31;
var limit = 10; var limit = 10;
var totalItems = 200;
var currentHeight = 1000;
var h = helpers.historyCacheTest(totalItems);
helpers.stubHistory(h);
blockchainExplorer.getBlockchainHeight = sinon.stub().callsArgWith(0, null, currentHeight);
var storeTxHistoryCacheSpy = sinon.spy(server.storage, 'storeTxHistoryCache');
server.getTxHistory({ server.getTxHistory({
skip: skip, skip: skip,
@ -6259,10 +6265,13 @@ describe('Wallet service', function() {
txs.length.should.equal(limit); txs.length.should.equal(limit);
var calls = storeTxHistoryCacheSpy.getCalls(); var calls = storeTxHistoryCacheSpy.getCalls();
calls.length.should.equal(1); calls.length.should.equal(1);
calls[0].args[1].should.equal(totalItems); // total
calls[0].args[2].should.equal(totalItems - skip - limit); // position
calls[0].args[3].length.should.equal(5); // 5 txs have confirmations>= 100 calls[0].args[3].length.should.equal(5); // 5 txs have confirmations>= 100
// should be reversed! // should be reversed!
calls[0].args[3][0].confirmations.should.equal(skip + limit - 1); calls[0].args[3][0].confirmations.should.equal(currentHeight - (totalItems - (skip + limit)));
calls[0].args[3][0].txid.should.equal(h[skip + limit - 1].txid); calls[0].args[3][0].txid.should.equal(h[skip + limit - 1].txid);
server.storage.storeTxHistoryCache.restore(); server.storage.storeTxHistoryCache.restore();
done(); done();
@ -6270,9 +6279,10 @@ describe('Wallet service', function() {
}); });
it('should not cache tx history from insight', function(done) { it('should not cache tx history when requesting txs with low # of confirmations', function(done) {
var h = helpers.historyCacheTest(200); var h = helpers.historyCacheTest(200);
helpers.stubHistory(h); helpers.stubHistory(h);
blockchainExplorer.getBlockchainHeight = sinon.stub().callsArgWith(0, null, 1000);
var storeTxHistoryCacheSpy = sinon.spy(server.storage, 'storeTxHistoryCache'); var storeTxHistoryCacheSpy = sinon.spy(server.storage, 'storeTxHistoryCache');
server.getTxHistory({ server.getTxHistory({
skip: 0, skip: 0,
@ -6289,11 +6299,15 @@ describe('Wallet service', function() {
it('should store cache all tx history from insight', function(done) { it('should store cache all tx history from insight', function(done) {
var h = helpers.historyCacheTest(200);
helpers.stubHistory(h);
var storeTxHistoryCacheSpy = sinon.spy(server.storage, 'storeTxHistoryCache');
var skip = 195; var skip = 195;
var limit = 5; var limit = 5;
var totalItems = 200;
var currentHeight = 1000;
var h = helpers.historyCacheTest(totalItems);
helpers.stubHistory(h);
blockchainExplorer.getBlockchainHeight = sinon.stub().callsArgWith(0, null, currentHeight);
var storeTxHistoryCacheSpy = sinon.spy(server.storage, 'storeTxHistoryCache');
server.getTxHistory({ server.getTxHistory({
skip: skip, skip: skip,
@ -6306,19 +6320,86 @@ describe('Wallet service', function() {
var calls = storeTxHistoryCacheSpy.getCalls(); var calls = storeTxHistoryCacheSpy.getCalls();
calls.length.should.equal(1); calls.length.should.equal(1);
calls[0].args[1].should.equal(totalItems); // total
calls[0].args[2].should.equal(totalItems - skip - limit); // position
calls[0].args[3].length.should.equal(5); calls[0].args[3].length.should.equal(5);
// should be reversed! // should be reversed!
calls[0].args[3][0].confirmations.should.equal(199); calls[0].args[3][0].confirmations.should.equal(currentHeight);
calls[0].args[3][0].txid.should.equal(h[199].txid); calls[0].args[3][0].txid.should.equal(h[totalItems - 1].txid);
server.storage.storeTxHistoryCache.restore(); server.storage.storeTxHistoryCache.restore();
done(); done();
}); });
}); });
it('should get real # of confirmations based on current block height', function(done) {
var _confirmations = Defaults.CONFIRMATIONS_TO_START_CACHING;
Defaults.CONFIRMATIONS_TO_START_CACHING = 6;
var h = helpers.historyCacheTest(20);
helpers.stubHistory(h);
var storeTxHistoryCacheSpy = sinon.spy(server.storage, 'storeTxHistoryCache');
var skip = 0;
var limit = 20;
blockchainExplorer.getBlockchainHeight = sinon.stub().callsArgWith(0, null, 100);
server.getTxHistory({
skip: skip,
limit: limit,
}, function(err, txs) {
should.not.exist(err);
should.exist(txs);
txs.length.should.equal(limit);
var calls = storeTxHistoryCacheSpy.getCalls();
calls.length.should.equal(1);
_.first(txs).confirmations.should.equal(81);
_.last(txs).confirmations.should.equal(100);
server.storage.storeTxHistoryCache.restore();
Defaults.CONFIRMATIONS_TO_START_CACHING = _confirmations;
done();
});
});
it('should get cached # of confirmations if current height unknown', function(done) {
var _confirmations = Defaults.CONFIRMATIONS_TO_START_CACHING;
Defaults.CONFIRMATIONS_TO_START_CACHING = 6;
var h = helpers.historyCacheTest(20);
helpers.stubHistory(h);
var storeTxHistoryCacheSpy = sinon.spy(server.storage, 'storeTxHistoryCache');
var skip = 0;
var limit = 20;
var _getLastKnownBlockchainHeight = server._getLastKnownBlockchainHeight;
server._getLastKnownBlockchainHeight = sinon.stub().callsArgWith(1, null, null);
server.getTxHistory({
skip: skip,
limit: limit,
}, function(err, txs) {
should.not.exist(err);
should.exist(txs);
txs.length.should.equal(limit);
var calls = storeTxHistoryCacheSpy.getCalls();
calls.length.should.equal(1);
_.first(txs).confirmations.should.equal(0);
_.last(txs).confirmations.should.equal(19);
server.storage.storeTxHistoryCache.restore();
Defaults.CONFIRMATIONS_TO_START_CACHING = _confirmations;
server._getLastKnownBlockchainHeight = _getLastKnownBlockchainHeight;
done();
});
});
describe('Downloading history', function() { describe('Downloading history', function() {
var h; var h;
beforeEach(function(done) { beforeEach(function(done) {
blockchainExplorer.getBlockchainHeight = sinon.stub().callsArgWith(0, null, 1000);
h = helpers.historyCacheTest(200); h = helpers.historyCacheTest(200);
helpers.stubHistory(h); helpers.stubHistory(h);
server.storage.clearTxHistoryCache(server.walletId, function() { server.storage.clearTxHistoryCache(server.walletId, function() {