improve error handling

This commit is contained in:
Ivan Socolsky 2016-03-04 17:10:48 -03:00
parent 485b98de86
commit 2581f488fa
2 changed files with 37 additions and 22 deletions

View File

@ -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 {

View File

@ -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');