improve error handling
This commit is contained in:
parent
485b98de86
commit
2581f488fa
|
@ -1243,6 +1243,9 @@ WalletService.prototype._checkTxAndEstimateFee = function(txp) {
|
|||
|
||||
txp.estimateFee();
|
||||
|
||||
if (txp.getEstimatedSize() / 1000 > Defaults.MAX_TX_SIZE_IN_KB)
|
||||
return Errors.TX_MAX_SIZE_EXCEEDED;
|
||||
|
||||
try {
|
||||
var bitcoreTx = txp.getBitcoreTx();
|
||||
bitcoreError = bitcoreTx.getSerializationError(serializationOpts);
|
||||
|
@ -1337,8 +1340,6 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) {
|
|||
txp.setInputs(selected);
|
||||
bitcoreError = self._checkTxAndEstimateFee(txp);
|
||||
if (!bitcoreError) return cb();
|
||||
if (txp.getEstimatedSize() / 1000 > Defaults.MAX_TX_SIZE_IN_KB)
|
||||
return cb(Errors.TX_MAX_SIZE_EXCEEDED);
|
||||
}
|
||||
setTimeout(select, 0);
|
||||
};
|
||||
|
@ -1404,10 +1405,15 @@ WalletService.prototype._selectTxInputs2 = function(txp, utxosToExclude, cb) {
|
|||
var sizePerInput = txp.getEstimatedSizeForSingleInput();
|
||||
var feePerInput = sizePerInput * txp.feePerKb / 1000.;
|
||||
|
||||
var totalValueInUtxos = _.sum(utxos, 'satoshis') - baseTxpFee - (utxos.length * feePerInput);
|
||||
var totalValueInUtxos = _.sum(utxos, 'satoshis');
|
||||
var netValueInUtxos = totalValueInUtxos - baseTxpFee - (utxos.length * feePerInput);
|
||||
if (totalValueInUtxos < txpAmount) {
|
||||
log.debug('Value in all utxos (' + formatAmount(totalValueInUtxos) + ') is inusufficient to cover for txp amount (' + formatAmount(txpAmount) + ')'); // TODO
|
||||
return false;
|
||||
log.debug('Total value in all utxos (' + formatAmount(totalValueInUtxos) + ') is insufficient to cover for txp amount (' + formatAmount(txpAmount) + ')'); // TODO
|
||||
return Errors.INSUFFICIENT_FUNDS;
|
||||
}
|
||||
if (netValueInUtxos < txpAmount) {
|
||||
log.debug('Value after fees in all utxos (' + formatAmount(netValueInUtxos) + ') is insufficient to cover for txp amount (' + formatAmount(txpAmount) + ')'); // TODO
|
||||
return Errors.INSUFFICIENT_FUNDS_FOR_FEE;
|
||||
}
|
||||
|
||||
var bigInputThreshold = txpAmount * Defaults.UTXO_SELECTION_MAX_SINGLE_UTXO_FACTOR + (baseTxpFee + feePerInput);
|
||||
|
@ -1427,6 +1433,7 @@ WalletService.prototype._selectTxInputs2 = function(txp, utxosToExclude, cb) {
|
|||
|
||||
var total = 0;
|
||||
var selected = [];
|
||||
var error;
|
||||
|
||||
_.each(smallInputs, function(input, i) {
|
||||
log.debug('Input #' + i + ': ' + formatInputs(input));
|
||||
|
@ -1444,6 +1451,8 @@ WalletService.prototype._selectTxInputs2 = function(txp, utxosToExclude, cb) {
|
|||
var txpSize = baseTxpSize + selected.length * sizePerInput;
|
||||
var txpFee = baseTxpFee + selected.length * feePerInput;
|
||||
|
||||
log.debug('Tx size: ' + formatSize(txpSize) + ', Tx fee: ' + formatAmount(txpFee));
|
||||
|
||||
var amountVsFeeRatio = txpFee / txpAmount;
|
||||
var singleInputFeeVsFeeRatio = txpFee / (baseTxpFee + feePerInput);
|
||||
var amountVsUtxoRatio = inputAmount / txpAmount;
|
||||
|
@ -1452,6 +1461,12 @@ WalletService.prototype._selectTxInputs2 = function(txp, utxosToExclude, cb) {
|
|||
log.debug('Single-input fee/Multi-input fee: ' + formatRatio(singleInputFeeVsFeeRatio) + ' (max: ' + formatRatio(Defaults.UTXO_SELECTION_MAX_FEE_VS_SINGLE_UTXO_FEE_FACTOR) + ')' + ' loses wrt single-input tx: ' + formatAmount((selected.length - 1) * feePerInput));
|
||||
log.debug('Tx amount/input amount:' + formatRatio(amountVsUtxoRatio) + ' (min: ' + formatRatio(Defaults.UTXO_SELECTION_MIN_TX_AMOUNT_VS_UTXO_FACTOR) + ')');
|
||||
|
||||
if (txpSize / 1000. > Defaults.MAX_TX_SIZE_IN_KB) {
|
||||
log.debug('Breaking because tx size (' + formatSize(txpSize) + ') is too big (max: ' + formatSize(Defaults.MAX_TX_SIZE_IN_KB * 1000.) + ')'); // TODO
|
||||
error = Errors.TX_MAX_SIZE_EXCEEDED;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_.isEmpty(bigInputs)) {
|
||||
if ((amountVsFeeRatio > Defaults.UTXO_SELECTION_MAX_TX_AMOUNT_VS_FEE_FACTOR &&
|
||||
singleInputFeeVsFeeRatio > Defaults.UTXO_SELECTION_MAX_FEE_VS_SINGLE_UTXO_FEE_FACTOR)) {
|
||||
|
@ -1463,12 +1478,6 @@ WalletService.prototype._selectTxInputs2 = function(txp, utxosToExclude, cb) {
|
|||
log.debug('Breaking because utxo is too small compared to tx amount');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (txpSize / 1000. > Defaults.MAX_TX_SIZE_IN_KB) {
|
||||
log.debug('Breaking because tx size is too big (' + formatSize(txpSize) + ')'); // TODO
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
total += inputAmount;
|
||||
|
@ -1489,11 +1498,9 @@ WalletService.prototype._selectTxInputs2 = function(txp, utxosToExclude, cb) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!_.isEmpty(selected)) {
|
||||
var lockedOverhead = total - txpAmount;
|
||||
log.debug('SUCCESS! Total locked: ' + formatAmount(total) + ', overhead: ' + formatAmount(lockedOverhead) + ' (' + formatRatio(lockedOverhead / txpAmount) + ')');
|
||||
} else {
|
||||
log.debug('Could not find enough funds within this utxso subset');
|
||||
if (_.isEmpty(selected)) {
|
||||
log.debug('Could not find enough funds within this utxo subset');
|
||||
return error || Errors.INSUFFICIENT_FUNDS_FOR_FEE;
|
||||
}
|
||||
|
||||
return selected;
|
||||
|
@ -1531,6 +1538,7 @@ WalletService.prototype._selectTxInputs2 = function(txp, utxosToExclude, cb) {
|
|||
|
||||
var inputs = [];
|
||||
var groups = [6, 1, 0];
|
||||
var error;
|
||||
var lastGroupLength;
|
||||
_.each(groups, function(group) {
|
||||
var candidateUtxos = _.filter(utxos, function(utxo) {
|
||||
|
@ -1549,20 +1557,25 @@ WalletService.prototype._selectTxInputs2 = function(txp, utxosToExclude, cb) {
|
|||
|
||||
lastGroupLength = candidateUtxos.length;
|
||||
|
||||
inputs = select(candidateUtxos);
|
||||
var result = select(candidateUtxos);
|
||||
if (result && !_.isArray(result)) {
|
||||
error = result;
|
||||
} else {
|
||||
inputs = result;
|
||||
error = null;
|
||||
}
|
||||
|
||||
log.debug('Selected inputs from this group: ' + formatInputs(inputs));
|
||||
|
||||
if (!_.isEmpty(inputs)) return false;
|
||||
});
|
||||
|
||||
if (_.isEmpty(inputs)) return cb(Errors.INSUFFICIENT_FUNDS_FOR_FEE);
|
||||
if (error) return cb(error);
|
||||
|
||||
txp.setInputs(inputs);
|
||||
if (txp.getEstimatedSize() / 1000 > Defaults.MAX_TX_SIZE_IN_KB)
|
||||
return cb(Errors.TX_MAX_SIZE_EXCEEDED);
|
||||
|
||||
var err = self._checkTxAndEstimateFee(txp);
|
||||
|
||||
if (!err) {
|
||||
log.debug('Successfully built transaction. Total fees: ', formatAmount(txp.fee));
|
||||
} else {
|
||||
|
|
|
@ -2132,6 +2132,7 @@ describe('Wallet service', function() {
|
|||
});
|
||||
|
||||
it('should use unconfirmed utxos only when no more confirmed utxos are available', function(done) {
|
||||
// log.level = 'debug';
|
||||
helpers.stubUtxos(server, wallet, [1.3, 'u0.5', 'u0.1', 1.2], function(utxos) {
|
||||
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 2.55, TestData.copayers[0].privKey_1H_0, {
|
||||
message: 'some message'
|
||||
|
@ -2354,10 +2355,11 @@ describe('Wallet service', function() {
|
|||
});
|
||||
|
||||
it('should fail to create a tx exceeding max size in kb', function(done) {
|
||||
log.level = 'debug';
|
||||
var _oldDefault = Defaults.MAX_TX_SIZE_IN_KB;
|
||||
Defaults.MAX_TX_SIZE_IN_KB = 1;
|
||||
helpers.stubUtxos(server, wallet, _.range(1, 10, 0), function() {
|
||||
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 8, TestData.copayers[0].privKey_1H_0);
|
||||
var _oldDefault = Defaults.MAX_TX_SIZE_IN_KB;
|
||||
Defaults.MAX_TX_SIZE_IN_KB = 1;
|
||||
server.createTxLegacy(txOpts, function(err, tx) {
|
||||
should.exist(err);
|
||||
err.code.should.equal('TX_MAX_SIZE_EXCEEDED');
|
||||
|
|
Loading…
Reference in New Issue