From b901e10c9d7403a7fa5581b6d89a8f18980ae668 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Thu, 21 Apr 2016 17:13:24 -0400 Subject: [PATCH] bitcoind: update unspentoutputs with mempool --- lib/services/bitcoind.js | 75 ++++++++++++++++++++++++++++++---- scripts/install | 2 +- test/services/bitcoind.unit.js | 12 ++++-- 3 files changed, 77 insertions(+), 12 deletions(-) diff --git a/lib/services/bitcoind.js b/lib/services/bitcoind.js index db33350d..59f20cf1 100644 --- a/lib/services/bitcoind.js +++ b/lib/services/bitcoind.js @@ -822,22 +822,81 @@ Bitcoin.prototype.getAddressBalance = function(addressArg, options, callback) { */ Bitcoin.prototype.getAddressUnspentOutputs = function(addressArg, options, callback) { var self = this; + var queryMempool = _.isUndefined(options.queryMempool) ? true : options.queryMempool; var addresses = self._normalizeAddressArg(addressArg); var cacheKey = addresses.join(''); var utxos = self.utxosCache.get(cacheKey); - if (utxos) { - return setImmediate(function() { - callback(null, utxos); - }); - } else { - self.client.getAddressUtxos({addresses: addresses}, function(err, response) { + + function transformUnspentOutput(delta) { + var script = bitcore.Script.fromAddress(delta.address); + return { + address: delta.address, + txid: delta.txid, + height: -1, // unconfirmed + outputIndex: delta.index, + script: script.toHex(), + satoshis: delta.satoshis + }; + } + + function updateWithMempool(utxos, mempoolDeltas) { + if (!mempoolDeltas || !mempoolDeltas.length) { + return utxos; + } + var isSpentOutputs = false; + var spentOutputs = []; + for (var i = 0; i < mempoolDeltas.length; i++) { + var delta = mempoolDeltas[i]; + if (delta.satoshis > 0) { + utxos.push(transformUnspentOutput(delta)); + } else if (delta.satoshis < 0) { + if (!spentOutputs[delta.prevtxid]) { + spentOutputs[delta.prevtxid] = [delta.prevout]; + } else { + spentOutputs[delta.prevtxid].push(delta.prevout); + } + isSpentOutputs = true; + } + } + if (isSpentOutputs) { + return utxos.filter(function(utxo) { + if (!spentOutputs[utxo.txid]) { + return true; + } else { + return (spentOutputs[utxo.txid].indexOf(utxo.outputIndex) === -1); + } + }); + } + return utxos; + } + + function finish(mempoolDeltas) { + if (utxos) { + return setImmediate(function() { + callback(null, updateWithMempool(utxos, mempoolDeltas).reverse()); + }); + } else { + self.client.getAddressUtxos({addresses: addresses}, function(err, response) { + if (err) { + return callback(self._wrapRPCError(err)); + } + self.utxosCache.set(cacheKey, response.result); + callback(null, updateWithMempool(response.result, mempoolDeltas).reverse()); + }); + } + } + + if (queryMempool) { + self.client.getAddressMempool({addresses: addresses}, function(err, response) { if (err) { return callback(self._wrapRPCError(err)); } - self.utxosCache.set(cacheKey, response.result); - callback(null, response.result); + finish(response.result); }); + } else { + finish(); } + }; Bitcoin.prototype._getBalanceFromMempool = function(deltas) { diff --git a/scripts/install b/scripts/install index f1f7bd9d..aa76aed6 100755 --- a/scripts/install +++ b/scripts/install @@ -5,7 +5,7 @@ platform=`uname -a | awk '{print tolower($1)}'` arch=`uname -m` version="0.12.0" url="https://github.com/braydonf/bitcoin/releases/download" -tag="v0.12.0-bitcore-beta3" +tag="v0.12.0-bitcore-beta4" cd "${root_dir}/bin" diff --git a/test/services/bitcoind.unit.js b/test/services/bitcoind.unit.js index 80df5fc0..e5532a06 100644 --- a/test/services/bitcoind.unit.js +++ b/test/services/bitcoind.unit.js @@ -1381,7 +1381,9 @@ describe('Bitcoin Service', function() { getAddressUtxos: sinon.stub().callsArgWith(1, {code: -1, message: 'Test error'}) } }); - var options = {}; + var options = { + queryMempool: false + }; var address = '1Cj4UZWnGWAJH1CweTMgPLQMn26WRMfXmo'; bitcoind.getAddressUnspentOutputs(address, options, function(err) { should.exist(err); @@ -1408,7 +1410,9 @@ describe('Bitcoin Service', function() { }) } }); - var options = {}; + var options = { + queryMempool: false + }; var address = '1Cj4UZWnGWAJH1CweTMgPLQMn26WRMfXmo'; bitcoind.getAddressUnspentOutputs(address, options, function(err, utxos) { if (err) { @@ -1439,7 +1443,9 @@ describe('Bitcoin Service', function() { getAddressUtxos: getAddressUtxos } }); - var options = {}; + var options = { + queryMempool: false + }; var address = '1Cj4UZWnGWAJH1CweTMgPLQMn26WRMfXmo'; bitcoind.getAddressUnspentOutputs(address, options, function(err, utxos) { if (err) {