Browse Source

Introduce different kinds of FeeError to distinguish the different cases. Fix the issue uncovered by this, which is that getFee might not be the actual fee, but only an estimate, if a change address is specified but there isn't enough to pay a fee and have change.

patch-2
David de Kloet 10 years ago
parent
commit
d1eb190626
  1. 10
      lib/errors/spec.js
  2. 25
      lib/transaction/transaction.js
  3. 6
      test/transaction/transaction.js

10
lib/errors/spec.js

@ -85,8 +85,14 @@ module.exports = [{
name: 'InvalidSatoshis',
message: 'Output satoshis are invalid',
}, {
name: 'FeeError',
message: 'Fees are not correctly set {0}',
name: 'SmallFeeError',
message: 'Fee is too small: {0}',
}, {
name: 'LargeFeeError',
message: 'Fee is too large: {0}',
}, {
name: 'DifferentFeeError',
message: 'Unspent value is different from specified fee: {0}',
}, {
name: 'ChangeAddressMissing',
message: 'Change address is missing'

25
lib/transaction/transaction.js

@ -203,16 +203,16 @@ Transaction.prototype.getSerializationError = function(opts) {
var isFullySigned = this.isFullySigned();
if (!opts.disableDifferentFees && feeIsDifferent) {
return new errors.Transaction.FeeError(feeIsDifferent);
return new errors.Transaction.DifferentFeeError(feeIsDifferent);
}
if (!opts.disableLargeFees && feeIsTooLarge) {
if (missingChange) {
return new errors.Transaction.ChangeAddressMissing('Fee is too large and no change address was provided');
}
return new errors.Transaction.FeeError(feeIsTooLarge);
return new errors.Transaction.LargeFeeError(feeIsTooLarge);
}
if (!opts.disableSmallFees && feeIsTooSmall) {
return new errors.Transaction.FeeError(feeIsTooSmall);
return new errors.Transaction.SmallFeeError(feeIsTooSmall);
}
if (!opts.disableDustOutputs && this._hasDustOutputs()) {
return new errors.Transaction.DustOutputs();
@ -226,27 +226,28 @@ Transaction.prototype.getSerializationError = function(opts) {
};
Transaction.prototype._isFeeDifferent = function() {
var fee = this.getFee();
var unspent = this._getUnspentValue();
if (fee !== unspent) {
return 'Unspent value ' + unspent + ' is different from specified fee ' +
fee + ' and no change address is specified';
if (!_.isUndefined(this._fee)) {
var fee = this._fee;
var unspent = this._getUnspentValue();
if (fee !== unspent) {
return 'Unspent value is ' + unspent + ' but specified fee is ' + fee;
}
}
};
Transaction.prototype._isFeeTooLarge = function() {
var fee = this.getFee();
var fee = this._getUnspentValue();
var maximumFee = Math.floor(Transaction.FEE_SECURITY_MARGIN * this._estimateFee());
if (fee > maximumFee) {
return 'Fee is too large: expected less than ' + maximumFee + ' but got ' + fee;
return 'expected less than ' + maximumFee + ' but got ' + fee;
}
};
Transaction.prototype._isFeeTooSmall = function() {
var fee = this.getFee();
var fee = this._getUnspentValue();
var minimumFee = Math.ceil(this._estimateFee() / Transaction.FEE_SECURITY_MARGIN);
if (fee < minimumFee) {
return 'Fee is too small: expected more than ' + minimumFee + ' but got ' + fee;
return 'expected more than ' + minimumFee + ' but got ' + fee;
}
};

6
test/transaction/transaction.js

@ -266,7 +266,7 @@ describe('Transaction', function() {
.sign(privateKey);
expect(function() {
return transaction.serialize();
}).to.throw(errors.Transaction.FeeError);
}).to.throw(errors.Transaction.SmallFeeError);
});
it('on second call to sign, change is not recalculated', function() {
var transaction = new Transaction()
@ -332,7 +332,7 @@ describe('Transaction', function() {
.to(toAddress, 40000000);
expect(function() {
return transaction.serialize();
}).to.throw(errors.Transaction.FeeError);
}).to.throw(errors.Transaction.LargeFeeError);
});
it('fails if a dust output is created', function() {
var transaction = new Transaction()
@ -372,7 +372,7 @@ describe('Transaction', function() {
.sign(privateKey);
expect(function() {
return transaction.serialize();
}).to.throw(errors.Transaction.FeeError);
}).to.throw(errors.Transaction.DifferentFeeError);
});
describe('skipping checks', function() {
var buildSkipTest = function(builder, check) {

Loading…
Cancel
Save