replace old utxo selection algo
This commit is contained in:
parent
504b52d695
commit
680516da70
123
lib/server.js
123
lib/server.js
|
@ -1267,90 +1267,6 @@ WalletService.prototype._checkTxAndEstimateFee = function(txp) {
|
|||
|
||||
WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) {
|
||||
var self = this;
|
||||
//todo: check inputs are ours and has enough value
|
||||
if (txp.inputs && txp.inputs.length > 0) {
|
||||
return cb(self._checkTxAndEstimateFee(txp));
|
||||
}
|
||||
|
||||
function sortUtxos(utxos) {
|
||||
var list = _.map(utxos, function(utxo) {
|
||||
var order;
|
||||
if (utxo.confirmations == 0) {
|
||||
order = 0;
|
||||
} else if (utxo.confirmations < 6) {
|
||||
order = -1;
|
||||
} else {
|
||||
order = -2;
|
||||
}
|
||||
return {
|
||||
order: order,
|
||||
utxo: utxo
|
||||
};
|
||||
});
|
||||
return _.pluck(_.sortBy(list, 'order'), 'utxo');
|
||||
};
|
||||
|
||||
self._getUtxosForCurrentWallet(null, function(err, utxos) {
|
||||
if (err) return cb(err);
|
||||
|
||||
var excludeIndex = _.reduce(utxosToExclude, function(res, val) {
|
||||
res[val] = val;
|
||||
return res;
|
||||
}, {});
|
||||
|
||||
utxos = _.reject(utxos, function(utxo) {
|
||||
return excludeIndex[utxo.txid + ":" + utxo.vout];
|
||||
});
|
||||
|
||||
var totalAmount;
|
||||
var availableAmount;
|
||||
|
||||
var balance = self._totalizeUtxos(utxos);
|
||||
if (txp.excludeUnconfirmedUtxos) {
|
||||
totalAmount = balance.totalConfirmedAmount;
|
||||
availableAmount = balance.availableConfirmedAmount;
|
||||
} else {
|
||||
totalAmount = balance.totalAmount;
|
||||
availableAmount = balance.availableAmount;
|
||||
}
|
||||
|
||||
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');
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
var total = 0;
|
||||
var selected = [];
|
||||
var inputs = sortUtxos(utxos);
|
||||
|
||||
var bitcoreTx, bitcoreError;
|
||||
|
||||
function select() {
|
||||
if (i >= inputs.length) return cb(bitcoreError || new Error('Could not select tx inputs'));
|
||||
|
||||
var input = inputs[i++];
|
||||
selected.push(input);
|
||||
total += input.satoshis;
|
||||
if (total >= txp.getTotalAmount()) {
|
||||
txp.setInputs(selected);
|
||||
bitcoreError = self._checkTxAndEstimateFee(txp);
|
||||
if (!bitcoreError) return cb();
|
||||
}
|
||||
setTimeout(select, 0);
|
||||
};
|
||||
|
||||
select();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
WalletService.prototype._selectTxInputs2 = function(txp, utxosToExclude, cb) {
|
||||
var self = this;
|
||||
|
||||
//todo: check inputs are ours and has enough value
|
||||
if (txp.inputs && txp.inputs.length > 0) {
|
||||
|
@ -1796,22 +1712,6 @@ WalletService.prototype.createTxLegacy = function(opts, cb) {
|
|||
WalletService.prototype.createTx = function(opts, cb) {
|
||||
var self = this;
|
||||
|
||||
function logStatistics(prefix, txp) {
|
||||
var totalAmount = txp.getTotalAmount();
|
||||
var inputs = _.sortBy(_.map(txp.inputs, function(input) {
|
||||
return _.pick(input, 'satoshis', 'confirmations');
|
||||
}), 'satoshis');
|
||||
var totalLocked = _.sum(inputs, 'satoshis');
|
||||
var overhead = totalLocked - totalAmount;
|
||||
|
||||
log.info(prefix, 'TXP ID: ' + txp.id);
|
||||
log.info(prefix, 'Total amount: ' + Utils.formatAmountInBtc(totalAmount));
|
||||
log.info(prefix, 'Fee: ' + Utils.formatAmountInBtc(txp.fee) + ' (per KB: ' + Utils.formatAmountInBtc(txp.feePerKb) + ')');
|
||||
log.info(prefix, 'Exclude unconfirmed: ' + txp.excludeUnconfirmedUtxos);
|
||||
log.info(prefix, 'Total locked: ' + Utils.formatAmountInBtc(totalLocked) + ', Overhead: ' + Utils.formatAmountInBtc(overhead) + ' (' + Utils.formatRatio(overhead / totalAmount) + ')');
|
||||
log.info(prefix, 'Inputs: ', Utils.formatUtxos(inputs));
|
||||
};
|
||||
|
||||
if (!Utils.checkRequired(opts, ['outputs', 'feePerKb']))
|
||||
return cb(new ClientError('Required argument missing'));
|
||||
|
||||
|
@ -1853,28 +1753,15 @@ WalletService.prototype.createTx = function(opts, cb) {
|
|||
|
||||
var txp = Model.TxProposal.create(txOpts);
|
||||
|
||||
self._selectTxInputs2(txp, opts.utxosToExclude, function(err) {
|
||||
if (err) {
|
||||
log.error('Could not select inputs using new algorithm', err);
|
||||
} else {
|
||||
logStatistics('NEW_UTXO_SEL', txp);
|
||||
}
|
||||
self._selectTxInputs(txp, opts.utxosToExclude, function(err) {
|
||||
if (err) return cb(err);
|
||||
|
||||
txp.setInputs([]);
|
||||
txp.fee = null;
|
||||
|
||||
self._selectTxInputs(txp, opts.utxosToExclude, function(err) {
|
||||
self.storage.storeAddressAndWallet(wallet, txp.changeAddress, function(err) {
|
||||
if (err) return cb(err);
|
||||
|
||||
logStatistics('OLD_UTXO_SEL', txp);
|
||||
|
||||
self.storage.storeAddressAndWallet(wallet, txp.changeAddress, function(err) {
|
||||
self.storage.storeTx(wallet.id, txp, function(err) {
|
||||
if (err) return cb(err);
|
||||
|
||||
self.storage.storeTx(wallet.id, txp, function(err) {
|
||||
if (err) return cb(err);
|
||||
return cb(null, txp);
|
||||
});
|
||||
return cb(null, txp);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3169,7 +3169,7 @@ describe('Wallet service', function() {
|
|||
});
|
||||
});
|
||||
|
||||
describe.skip('UTXO Selection', function() {
|
||||
describe('UTXO Selection', function() {
|
||||
var server, wallet;
|
||||
beforeEach(function(done) {
|
||||
helpers.createAndJoinWallet(2, 3, function(s, w) {
|
||||
|
|
Loading…
Reference in New Issue