handle lots of small inputs causing the total balance after fees to decrease
This commit is contained in:
parent
680516da70
commit
cbde3233df
|
@ -1273,6 +1273,12 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) {
|
|||
return cb(self._checkTxAndEstimateFee(txp));
|
||||
}
|
||||
|
||||
var txpAmount = txp.getTotalAmount();
|
||||
var baseTxpSize = txp.getEstimatedSize();
|
||||
var baseTxpFee = baseTxpSize * txp.feePerKb / 1000.;
|
||||
var sizePerInput = txp.getEstimatedSizeForSingleInput();
|
||||
var feePerInput = sizePerInput * txp.feePerKb / 1000.;
|
||||
|
||||
function excludeUtxos(utxos) {
|
||||
var excludeIndex = _.reduce(utxosToExclude, function(res, val) {
|
||||
res[val] = val;
|
||||
|
@ -1284,6 +1290,15 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) {
|
|||
});
|
||||
};
|
||||
|
||||
function sanitizeUtxos(utxos) {
|
||||
return _.filter(utxos, function(utxo) {
|
||||
if (utxo.locked) return false;
|
||||
if (utxo.satoshis <= feePerInput) return false;
|
||||
if (txp.excludeUnconfirmedUtxos && !utxo.confirmations) return false;
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
function partitionUtxos(utxos) {
|
||||
return _.groupBy(utxos, function(utxo) {
|
||||
if (utxo.confirmations == 0) return '0'
|
||||
|
@ -1293,14 +1308,9 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) {
|
|||
};
|
||||
|
||||
function select(utxos, cb) {
|
||||
var txpAmount = txp.getTotalAmount();
|
||||
var baseTxpSize = txp.getEstimatedSize();
|
||||
var baseTxpFee = baseTxpSize * txp.feePerKb / 1000.;
|
||||
var sizePerInput = txp.getEstimatedSizeForSingleInput();
|
||||
var feePerInput = sizePerInput * txp.feePerKb / 1000.;
|
||||
|
||||
var totalValueInUtxos = _.sum(utxos, 'satoshis');
|
||||
var netValueInUtxos = totalValueInUtxos - baseTxpFee - (utxos.length * feePerInput);
|
||||
|
||||
if (totalValueInUtxos < txpAmount) {
|
||||
log.debug('Total value in all utxos (' + Utils.formatAmountInBtc(totalValueInUtxos) + ') is insufficient to cover for txp amount (' + Utils.formatAmountInBtc(txpAmount) + ')');
|
||||
return cb(Errors.INSUFFICIENT_FUNDS);
|
||||
|
@ -1422,11 +1432,7 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) {
|
|||
if (totalAmount < txp.getTotalAmount()) return cb(Errors.INSUFFICIENT_FUNDS);
|
||||
if (availableAmount < txp.getTotalAmount()) return cb(Errors.LOCKED_FUNDS);
|
||||
|
||||
// Prepare UTXOs list
|
||||
utxos = _.reject(utxos, 'locked');
|
||||
if (txp.excludeUnconfirmedUtxos) {
|
||||
utxos = _.filter(utxos, 'confirmations');
|
||||
}
|
||||
utxos = sanitizeUtxos(utxos);
|
||||
|
||||
log.debug('Considering ' + utxos.length + ' utxos (' + Utils.formatUtxos(utxos) + ')');
|
||||
|
||||
|
|
|
@ -3412,8 +3412,6 @@ describe('Wallet service', function() {
|
|||
feePerKb: 100e2,
|
||||
};
|
||||
server.createTx(txOpts, function(err, txp) {
|
||||
console.log('*** [server.js ln3417] err:', err); // TODO
|
||||
|
||||
should.not.exist(err);
|
||||
should.exist(txp);
|
||||
txp.inputs.length.should.equal(1);
|
||||
|
@ -3422,6 +3420,25 @@ describe('Wallet service', function() {
|
|||
});
|
||||
});
|
||||
});
|
||||
it('should ignore utxos too small to pay for fee', function(done) {
|
||||
helpers.stubUtxos(server, wallet, ['1c200bit', '200bit'].concat(_.times(20, function() {
|
||||
return '1bit';
|
||||
})), function() {
|
||||
var txOpts = {
|
||||
outputs: [{
|
||||
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
|
||||
amount: 200e2,
|
||||
}],
|
||||
feePerKb: 90e2,
|
||||
};
|
||||
server.createTx(txOpts, function(err, txp) {
|
||||
should.not.exist(err);
|
||||
should.exist(txp);
|
||||
txp.inputs.length.should.equal(2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue