From 9ed48f1e77a1c971c6cd23f625c0cae19440ebc2 Mon Sep 17 00:00:00 2001 From: Ivan Socolsky Date: Tue, 8 Mar 2016 10:55:32 -0300 Subject: [PATCH] keep adding utxos to raise change above dust --- lib/common/utils.js | 1 + lib/server.js | 16 +++++++++++++--- test/integration/server.js | 31 ++++++++++++++++++++++++++++--- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/lib/common/utils.js b/lib/common/utils.js index bd749fd..72846bf 100644 --- a/lib/common/utils.js +++ b/lib/common/utils.js @@ -23,6 +23,7 @@ Utils.checkRequired = function(obj, args) { * @return {number} */ Utils.strip = function(number) { + return parseFloat(number); return (parseFloat(number.toPrecision(12))); } diff --git a/lib/server.js b/lib/server.js index e77f6e3..bfdae8c 100644 --- a/lib/server.js +++ b/lib/server.js @@ -1347,6 +1347,7 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) { selected.push(input); + total += inputAmount; var txpSize = baseTxpSize + selected.length * sizePerInput; var txpFee = baseTxpFee + selected.length * feePerInput; @@ -1379,10 +1380,19 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) { } } - total += inputAmount; log.debug('Cumuled total so far: ' + Utils.formatAmountInBtc(total)); - if (total >= txpAmount) return false; + if (total >= txpAmount) { + var changeAmount = total - txpAmount - txpFee; + log.debug('Tx change: ', Utils.formatAmountInBtc(changeAmount)); + + if (changeAmount <= Bitcore.Transaction.DUST_AMOUNT) { + log.debug('Change (' + Utils.formatAmountInBtc(changeAmount) + ') below dust amount (' + Utils.formatAmountInBtc(Bitcore.Transaction.DUST_AMOUNT) + ')'); + return; + } + + return false; + } }); if (total < txpAmount) { @@ -1479,7 +1489,7 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) { var err = self._checkTxAndEstimateFee(txp); if (!err) { - log.debug('Successfully built transaction. Total fees: ', Utils.formatAmountInBtc(txp.fee)); + log.debug('Successfully built transaction. Total fees: ' + Utils.formatAmountInBtc(txp.fee) + ', total change: ' + Utils.formatAmountInBtc(_.sum(txp.inputs, 'satoshis') - txp.fee)); } else { log.warn('Error building transaction', err); } diff --git a/test/integration/server.js b/test/integration/server.js index 4b6f18d..de1d1df 100644 --- a/test/integration/server.js +++ b/test/integration/server.js @@ -3199,7 +3199,7 @@ describe('Wallet service', function() { }); }); }); - it('should select a confirmed utxos if within thresholds relative to tx amount', function(done) { + it('should select a confirmed utxos if within thresholds relative to tx amount', function(done) { helpers.stubUtxos(server, wallet, [1, 'u 350bit', '100bit', '100bit', '100bit'], function() { var txOpts = { outputs: [{ @@ -3218,7 +3218,7 @@ describe('Wallet service', function() { }); }); }); - + it('should select smaller utxos if within fee constraints', function(done) { helpers.stubUtxos(server, wallet, [1, '800bit', '800bit', '800bit'], function() { var txOpts = { @@ -3479,7 +3479,32 @@ describe('Wallet service', function() { }); }); }); - it.only('should ignore small utxos if fee is higher', function(done) { + it('should keep adding utxos while change is below dust', function(done) { + helpers.stubUtxos(server, wallet, ['200bit', '500sat'], function() { + var txOpts = { + outputs: [{ + toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', + amount: 200e2, + }], + feePerKb: 400, + }; + server.createTx(txOpts, function(err, txp) { + should.exist(err); + err.code.should.equal('DUST_AMOUNT'); + helpers.stubUtxos(server, wallet, ['200bit'].concat(_.times(10, function() { + return '500sat'; + })), function() { + server.createTx(txOpts, function(err, txp) { + should.not.exist(err); + txp.inputs[0].satoshis.should.equal(200e2); + (_.sum(txp.inputs, 'satoshis') - txp.outputs[0].amount - txp.fee).should.be.above(Bitcore.Transaction.DUST_AMOUNT); + done(); + }); + }); + }); + }); + }); + it.skip('should ignore small utxos if fee is higher', function(done) { helpers.stubUtxos(server, wallet, [].concat(_.times(10, function() { return '30bit'; })), function() {