add noBalance options + mempoolAddressIndex

This commit is contained in:
Matias Alejo Garcia 2016-02-08 12:41:49 -05:00
parent 6a899e4b9c
commit e7e33313cf
2 changed files with 106 additions and 77 deletions

View File

@ -44,6 +44,7 @@ function AddressHistory(args) {
AddressHistory.prototype._mergeAndSortTxids = function(summaries) { AddressHistory.prototype._mergeAndSortTxids = function(summaries) {
var appearanceIds = {}; var appearanceIds = {};
var unconfirmedAppearanceIds = {}; var unconfirmedAppearanceIds = {};
for (var i = 0; i < summaries.length; i++) { for (var i = 0; i < summaries.length; i++) {
var summary = summaries[i]; var summary = summaries[i];
for (var key in summary.appearanceIds) { for (var key in summary.appearanceIds) {
@ -79,6 +80,8 @@ AddressHistory.prototype.get = function(callback) {
return callback(new TypeError('Maximum number of addresses (' + this.maxAddressesQuery + ') exceeded')); return callback(new TypeError('Maximum number of addresses (' + this.maxAddressesQuery + ') exceeded'));
} }
this.options.noBalance = true;
if (this.addresses.length === 1) { if (this.addresses.length === 1) {
var address = this.addresses[0]; var address = this.addresses[0];
self.node.services.address.getAddressSummary(address, this.options, function(err, summary) { self.node.services.address.getAddressSummary(address, this.options, function(err, summary) {
@ -89,10 +92,11 @@ AddressHistory.prototype.get = function(callback) {
}); });
} else { } else {
var opts = _.clone(this.options); var opts = _.clone(this.options);
opts.fullTxList = true; opts.fullTxList = true;
async.mapLimit( async.mapLimit(
self.addresses, self.addresses,
self.maxAddressesLimit, self.maxaddressesLimit,
function(address, next) { function(address, next) {
self.node.services.address.getAddressSummary(address, opts, next); self.node.services.address.getAddressSummary(address, opts, next);
}, },

View File

@ -57,6 +57,7 @@ var AddressService = function(options) {
} }
this.mempoolIndex = null; // Used for larger mempool indexes this.mempoolIndex = null; // Used for larger mempool indexes
this.mempoolSpentIndex = {}; // Used for small quick synchronous lookups this.mempoolSpentIndex = {}; // Used for small quick synchronous lookups
this.mempoolAddressIndex = {}; // Used to check if an address is on the spend pool
}; };
inherits(AddressService, BaseService); inherits(AddressService, BaseService);
@ -70,6 +71,7 @@ AddressService.prototype.start = function(callback) {
var self = this; var self = this;
async.series([ async.series([
function(next) { function(next) {
// Flush any existing mempool index // Flush any existing mempool index
if (fs.existsSync(self.mempoolIndexPath)) { if (fs.existsSync(self.mempoolIndexPath)) {
@ -88,8 +90,7 @@ AddressService.prototype.start = function(callback) {
}, },
function(next) { function(next) {
self.mempoolIndex = levelup( self.mempoolIndex = levelup(
self.mempoolIndexPath, self.mempoolIndexPath, {
{
db: self.levelupStore, db: self.levelupStore,
keyEncoding: 'binary', keyEncoding: 'binary',
valueEncoding: 'binary', valueEncoding: 'binary',
@ -154,20 +155,17 @@ AddressService.prototype.getAPIMethods = function() {
* Called by the Bus to get the available events for this service. * Called by the Bus to get the available events for this service.
*/ */
AddressService.prototype.getPublishEvents = function() { AddressService.prototype.getPublishEvents = function() {
return [ return [{
{
name: 'address/transaction', name: 'address/transaction',
scope: this, scope: this,
subscribe: this.subscribe.bind(this, 'address/transaction'), subscribe: this.subscribe.bind(this, 'address/transaction'),
unsubscribe: this.unsubscribe.bind(this, 'address/transaction') unsubscribe: this.unsubscribe.bind(this, 'address/transaction')
}, }, {
{
name: 'address/balance', name: 'address/balance',
scope: this, scope: this,
subscribe: this.subscribe.bind(this, 'address/balance'), subscribe: this.subscribe.bind(this, 'address/balance'),
unsubscribe: this.unsubscribe.bind(this, 'address/balance') unsubscribe: this.unsubscribe.bind(this, 'address/balance')
} }];
];
}; };
/** /**
@ -305,6 +303,14 @@ AddressService.prototype.updateMempoolIndex = function(tx, add, callback) {
continue; continue;
} }
var hashBufferHex = addressInfo.hashBuffer.toString('hex');
if (add) {
this.mempoolAddressIndex[hashBufferHex] = true;
} else {
delete this.mempoolAddressIndex[hashBufferHex];
}
// Update output index // Update output index
var outputIndexBuffer = new Buffer(4); var outputIndexBuffer = new Buffer(4);
outputIndexBuffer.writeUInt32BE(outputIndex); outputIndexBuffer.writeUInt32BE(outputIndex);
@ -397,6 +403,12 @@ AddressService.prototype.updateMempoolIndex = function(tx, add, callback) {
value: inputValue value: inputValue
}); });
var inputHashBufferHex = inputHashBuffer.toString('hex');
if (add) {
this.mempoolAddressIndex[inputHashBufferHex] = true;
} else {
delete this.mempoolAddressIndex[inputHashBufferHex];
}
} }
if (!callback) { if (!callback) {
@ -1208,7 +1220,9 @@ AddressService.prototype.getUnspentOutputsForAddress = function(address, queryMe
var self = this; var self = this;
this.getOutputs(address, {queryMempool: queryMempool}, function(err, outputs) { this.getOutputs(address, {
queryMempool: queryMempool
}, function(err, outputs) {
if (err) { if (err) {
return callback(err); return callback(err);
} else if (!outputs.length) { } else if (!outputs.length) {
@ -1336,6 +1350,7 @@ AddressService.prototype.getAddressSummary = function(addressArg, options, callb
} }
async.waterfall([ async.waterfall([
function(next) { function(next) {
self._getAddressConfirmedSummary(address, options, next); self._getAddressConfirmedSummary(address, options, next);
}, },
@ -1357,9 +1372,7 @@ AddressService.prototype.getAddressSummary = function(addressArg, options, callb
var seconds = Math.round(timeDelta / 1000); var seconds = Math.round(timeDelta / 1000);
log.warn('Slow (' + seconds + 's) getAddressSummary request for address: ' + address.toString()); log.warn('Slow (' + seconds + 's) getAddressSummary request for address: ' + address.toString());
} }
callback(null, summary); callback(null, summary);
}); });
}; };
@ -1375,6 +1388,7 @@ AddressService.prototype._getAddressConfirmedSummary = function(address, options
}; };
async.waterfall([ async.waterfall([
function(next) { function(next) {
self._getAddressConfirmedInputsSummary(address, baseResult, options, next); self._getAddressConfirmedInputsSummary(address, baseResult, options, next);
}, },
@ -1434,6 +1448,7 @@ AddressService.prototype._getAddressConfirmedOutputsSummary = function(address,
var txid = output.txid; var txid = output.txid;
var outputIndex = output.outputIndex; var outputIndex = output.outputIndex;
if (!options.noBalance) {
// Bitcoind's isSpent only works for confirmed transactions // Bitcoind's isSpent only works for confirmed transactions
var spentDB = self.node.services.bitcoind.isSpent(txid, outputIndex); var spentDB = self.node.services.bitcoind.isSpent(txid, outputIndex);
result.totalReceived += output.satoshis; result.totalReceived += output.satoshis;
@ -1455,6 +1470,7 @@ AddressService.prototype._getAddressConfirmedOutputsSummary = function(address,
result.unconfirmedBalance -= output.satoshis; result.unconfirmedBalance -= output.satoshis;
} }
} }
}
count++; count++;
@ -1504,8 +1520,14 @@ AddressService.prototype._getAddressMempoolSummary = function(address, options,
var addressStr = address.toString(); var addressStr = address.toString();
var hashBuffer = address.hashBuffer; var hashBuffer = address.hashBuffer;
var hashTypeBuffer = constants.HASH_TYPES_MAP[address.type]; var hashTypeBuffer = constants.HASH_TYPES_MAP[address.type];
var hashBufferHex = hashBuffer.toString('hex');
if (!this.mempoolAddressIndex[hashBufferHex]) {
return callback(null, result);
}
async.waterfall([ async.waterfall([
function(next) { function(next) {
self._getInputsMempool(addressStr, hashBuffer, hashTypeBuffer, function(err, mempoolInputs) { self._getInputsMempool(addressStr, hashBuffer, hashTypeBuffer, function(err, mempoolInputs) {
if (err) { if (err) {
@ -1518,11 +1540,13 @@ AddressService.prototype._getAddressMempoolSummary = function(address, options,
next(null, result); next(null, result);
}); });
}, function(result, next) { },
function(result, next) {
self._getOutputsMempool(addressStr, hashBuffer, hashTypeBuffer, function(err, mempoolOutputs) { self._getOutputsMempool(addressStr, hashBuffer, hashTypeBuffer, function(err, mempoolOutputs) {
if (err) { if (err) {
return next(err); return next(err);
} }
if (!options.noBalance) {
for (var i = 0; i < mempoolOutputs.length; i++) { for (var i = 0; i < mempoolOutputs.length; i++) {
var output = mempoolOutputs[i]; var output = mempoolOutputs[i];
@ -1538,6 +1562,7 @@ AddressService.prototype._getAddressMempoolSummary = function(address, options,
result.unconfirmedBalance += output.satoshis; result.unconfirmedBalance += output.satoshis;
} }
} }
}
next(null, result); next(null, result);
}); });
} }