From 62c0fb06efe40f8227c8406b668d8f8e5e75c8f5 Mon Sep 17 00:00:00 2001 From: Ivan Socolsky Date: Wed, 2 Mar 2016 16:44:38 -0300 Subject: [PATCH] test utxo confirmation priority --- lib/server.js | 9 +++- test/integration/server.js | 94 +++++++++++++++++++++++++++++++++----- 2 files changed, 89 insertions(+), 14 deletions(-) diff --git a/lib/server.js b/lib/server.js index 2c9a822..718e276 100644 --- a/lib/server.js +++ b/lib/server.js @@ -1376,7 +1376,6 @@ WalletService.prototype._selectTxInputs2 = function(txp, utxosToExclude, cb) { }; function select(utxos) { - var txpAmount = txp.getTotalAmount(); var i = 0; var total = 0; var selected = []; @@ -1384,12 +1383,18 @@ WalletService.prototype._selectTxInputs2 = function(txp, utxosToExclude, cb) { console.log('*** [server.js ln1362] ----------------------- select for amount of:', txpAmount); // TODO // TODO: fix for when fee is specified instead of feePerKb + var txpAmount = txp.getTotalAmount(); var baseTxpSize = txp.getEstimatedSize(); var baseTxpFee = baseTxpSize * txp.feePerKb / 1000.; var sizePerInput = txp.getEstimatedSizeForSingleInput(); var feePerInput = sizePerInput * txp.feePerKb / 1000.; - console.log('*** [server.js ln1375] feePerInput:', feePerInput); // TODO + var totalValueInUtxos = _.sum(utxos, 'satoshis') - baseTxpFee - (utxos.length * feePerInput); + if (totalValueInUtxos < txpAmount) { + console.log('*** [server.js ln1380] value in all utxos:', totalValueInUtxos, ' is inusfficient to cover for txp amount:', txpAmount); // TODO + + return false; + } var partitions = _.partition(utxos, function(utxo) { return utxo.satoshis > txpAmount * Defaults.UTXO_SELECTION_MAX_SINGLE_UTXO_FACTOR; diff --git a/test/integration/server.js b/test/integration/server.js index 0039270..bc1c2b2 100644 --- a/test/integration/server.js +++ b/test/integration/server.js @@ -5746,9 +5746,9 @@ describe('Wallet service', function() { var txOpts = { outputs: [{ toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', - amount: 20000, + amount: 200e2, }], - feePerKb: 1000, + feePerKb: 10e2, }; server.createTx(txOpts, function(err, txp) { should.not.exist(err); @@ -5775,7 +5775,7 @@ describe('Wallet service', function() { should.exist(txp); txp.inputs.length.should.equal(3); _.all(txp.inputs, function(input) { - return input == 10000; + return input == 100e2; }); done(); }); @@ -5786,9 +5786,9 @@ describe('Wallet service', function() { var txOpts = { outputs: [{ toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', - amount: 30000, + amount: 300e2, }], - feePerKb: 1000, + feePerKb: 10e2, }; server.createTx(txOpts, function(err, txp) { should.not.exist(err); @@ -5811,12 +5811,8 @@ describe('Wallet service', function() { feePerKb: 20e2, }; server.createTx(txOpts, function(err, txp) { - console.log('*** [server.js ln5790] err:', err); // TODO - should.not.exist(err); should.exist(txp); - console.log('*** [server.js ln5792] txp.fee:', txp.fee); // TODO - txp.inputs.length.should.equal(1); txp.inputs[0].satoshis.should.equal(1e8); @@ -5872,15 +5868,15 @@ describe('Wallet service', function() { var txOpts = { outputs: [{ toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', - amount: 20000, + amount: 200e2, }], - feePerKb: 8000, + feePerKb: 80e2, }; server.createTx(txOpts, function(err, txp) { should.not.exist(err); should.exist(txp); txp.inputs.length.should.equal(3); - txOpts.feePerKb = 12000; + txOpts.feePerKb = 120e2; server.createTx(txOpts, function(err, txp) { should.exist(err); should.not.exist(txp); @@ -5889,6 +5885,80 @@ describe('Wallet service', function() { }); }); }); + it('should fail to select utxos if not enough to cover tx amount', function(done) { + helpers.stubUtxos(server, wallet, ['100bit', '100bit', '100bit'], function() { + var txOpts = { + outputs: [{ + toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', + amount: 400e2, + }], + feePerKb: 10e2, + }; + server.createTx(txOpts, function(err, txp) { + should.exist(err); + should.not.exist(txp); + err.code.should.equal('INSUFFICIENT_FUNDS'); + done(); + }); + }); + }); + it('should fail to select utxos if not enough to cover fees', function(done) { + helpers.stubUtxos(server, wallet, ['100bit', '100bit', '100bit'], function() { + var txOpts = { + outputs: [{ + toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', + amount: 299e2, + }], + feePerKb: 10e2, + }; + server.createTx(txOpts, function(err, txp) { + should.exist(err); + should.not.exist(txp); + err.code.should.equal('INSUFFICIENT_FUNDS_FOR_FEE'); + done(); + }); + }); + }); + it('should prefer a higher fee (breaking all limits) if inputs have 6+ confirmations', function(done) { + helpers.stubUtxos(server, wallet, ['2c 2000bit'].concat(_.times(20, function() { + return '100bit'; + })), function() { + var txOpts = { + outputs: [{ + toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', + amount: 1500e2, + }], + feePerKb: 10e2, + }; + server.createTx(txOpts, function(err, txp) { + should.not.exist(err); + should.exist(txp); + _.all(txp.inputs, function(input) { + return input == 100e2; + }); + done(); + }); + }); + }); + it('should select unconfirmed utxos if not enough confirmed utxos', function(done) { + helpers.stubUtxos(server, wallet, ['u 1btc', '0.5btc'], function() { + var txOpts = { + outputs: [{ + toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', + amount: 0.8e8, + }], + feePerKb: 100e2, + }; + server.createTx(txOpts, function(err, txp) { + should.not.exist(err); + should.exist(txp); + txp.inputs.length.should.equal(1); + txp.inputs[0].satoshis.should.equal(1e8); + done(); + }); + }); + }); + }); });