Skip to content
This repository was archived by the owner on Apr 3, 2019. It is now read-only.

Commit 68ec16d

Browse files
committed
Merge pull request #484 from isocolsky/fix/utxo-selection
Add threshold for change creation when selecting UTXOs
2 parents d93630b + 37ee40f commit 68ec16d

File tree

3 files changed

+13
-8
lines changed

3 files changed

+13
-8
lines changed

lib/common/defaults.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,7 @@ Defaults.UTXO_SELECTION_MAX_FEE_VS_TX_AMOUNT_FACTOR = 0.05;
6363
// when fees are significant (proportional to how much we would pay for using that big input only).
6464
Defaults.UTXO_SELECTION_MAX_FEE_VS_SINGLE_UTXO_FEE_FACTOR = 5;
6565

66+
// Do not generate change for less than the specified amount
67+
Defaults.UTXO_SELECTION_MIN_CHANGE_AMOUNT = 5000;
68+
6669
module.exports = Defaults;

lib/server.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,8 +1480,9 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) {
14801480
var changeAmount = Math.round(total - txpAmount - fee);
14811481
log.debug('Tx change: ', Utils.formatAmountInBtc(changeAmount));
14821482

1483-
if (changeAmount > 0 && changeAmount <= Bitcore.Transaction.DUST_AMOUNT) {
1484-
log.debug('Change below dust amount (' + Utils.formatAmountInBtc(Bitcore.Transaction.DUST_AMOUNT) + ')');
1483+
var smallChangeThreshold = Math.max(Defaults.UTXO_SELECTION_MIN_CHANGE_AMOUNT, Bitcore.Transaction.DUST_AMOUNT);
1484+
if (changeAmount > 0 && changeAmount <= smallChangeThreshold) {
1485+
log.debug('Change below threshold (' + Utils.formatAmountInBtc(smallChangeThreshold) + '). Incrementing fee to remove change.');
14851486
// Remove dust change by incrementing fee
14861487
fee += changeAmount;
14871488
}

test/integration/server.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2326,18 +2326,18 @@ describe('Wallet service', function() {
23262326

23272327
it('should be possible to use a smaller fee', function(done) {
23282328
helpers.stubUtxos(server, wallet, 1, function() {
2329-
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.99995, TestData.copayers[0].privKey_1H_0, {
2329+
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.9999, TestData.copayers[0].privKey_1H_0, {
23302330
feePerKb: 80000
23312331
});
23322332
server.createTxLegacy(txOpts, function(err, tx) {
23332333
should.exist(err);
23342334
err.code.should.equal('INSUFFICIENT_FUNDS_FOR_FEE');
2335-
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.99995, TestData.copayers[0].privKey_1H_0, {
2335+
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.9999, TestData.copayers[0].privKey_1H_0, {
23362336
feePerKb: 5000
23372337
});
23382338
server.createTxLegacy(txOpts, function(err, tx) {
23392339
should.not.exist(err);
2340-
var estimatedFee = 5000 * 400 / 1000; // fully signed tx should have about 400 bytes
2340+
var estimatedFee = 5000 * 410 / 1000; // fully signed tx should have about 410 bytes
23412341
tx.fee.should.be.within(0.9 * estimatedFee, 1.1 * estimatedFee);
23422342

23432343
// Sign it to make sure Bitcore doesn't complain about the fees
@@ -3597,17 +3597,18 @@ describe('Wallet service', function() {
35973597
});
35983598
});
35993599
});
3600-
it('should correct fee if resulting change would be below dust', function(done) {
3600+
it('should correct fee if resulting change would be below threshold', function(done) {
36013601
helpers.stubUtxos(server, wallet, ['200bit', '500sat'], function() {
36023602
var txOpts = {
36033603
outputs: [{
36043604
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
3605-
amount: 200e2,
3605+
amount: 150e2,
36063606
}],
3607-
feePerKb: 400,
3607+
feePerKb: 100e2,
36083608
};
36093609
server.createTx(txOpts, function(err, txp) {
36103610
should.not.exist(err);
3611+
txp.inputs.length.should.equal(1);
36113612
(_.sum(txp.inputs, 'satoshis') - txp.outputs[0].amount - txp.fee).should.equal(0);
36123613
var changeOutput = txp.getBitcoreTx().getChangeOutput();
36133614
should.not.exist(changeOutput);

0 commit comments

Comments
 (0)