diff --git a/lib/transaction/transaction.js b/lib/transaction/transaction.js index 6d1feb631..e5e60a7f1 100644 --- a/lib/transaction/transaction.js +++ b/lib/transaction/transaction.js @@ -192,10 +192,10 @@ Transaction.prototype.getSerializationError = function(opts) { opts = opts || {}; return this._isInvalidSatoshis() || + this._hasMoreOutputThanInput(opts) || this._hasFeeError(opts) || this._hasDustOutputs(opts) || - this._isMissingSignatures(opts) || - this._hasMoreOutputThanInput(opts); + this._isMissingSignatures(opts); }; Transaction.prototype._isInvalidSatoshis = function() { diff --git a/test/transaction/transaction.js b/test/transaction/transaction.js index 66db3e5f0..cd0eefacb 100644 --- a/test/transaction/transaction.js +++ b/test/transaction/transaction.js @@ -385,22 +385,36 @@ describe('Transaction', function() { return transaction.serialize(); }).to.throw(errors.Transaction.FeeError.Different); }); + it('checks output amount before fee errors', function() { + var transaction = new Transaction(); + transaction.from(simpleUtxoWith1BTC); + transaction + .to(toAddress, 10000000000000) + .change(changeAddress) + .fee(5); + + expect(function() { + return transaction.serialize(); + }).to.throw(errors.Transaction.InvalidOutputAmountSum); + }); describe('skipping checks', function() { - var buildSkipTest = function(builder, check) { + var buildSkipTest = function(builder, check, expectedError, opts) { return function() { var transaction = new Transaction(); transaction.from(simpleUtxoWith1BTC); builder(transaction); - var options = {}; + var options = opts || {}; options[check] = true; expect(function() { return transaction.serialize(options); }).not.to.throw(); + + options[check] = false; expect(function() { - return transaction.serialize(); - }).to.throw(); + return transaction.serialize(options); + }).to.throw(expectedError); }; }; it('can skip the check for too much fee', buildSkipTest( @@ -409,54 +423,38 @@ describe('Transaction', function() { .fee(50000000) .change(changeAddress) .sign(privateKey); - }, 'disableLargeFees')); + }, 'disableLargeFees', errors.Transaction.FeeError.TooLarge)); it('can skip the check for a fee that is too small', buildSkipTest( function(transaction) { return transaction .fee(1) .change(changeAddress) .sign(privateKey); - }, 'disableSmallFees')); + }, 'disableSmallFees', errors.Transaction.FeeError.TooSmall)); it('can skip the check that prevents dust outputs', buildSkipTest( function(transaction) { return transaction .to(toAddress, 100) .change(changeAddress) .sign(privateKey); - }, 'disableDustOutputs')); - it('can skip the check that prevents unsigned outputs', function() { - var transaction = new Transaction(); - transaction.from(simpleUtxoWith1BTC); - transaction.to(toAddress, 10000); - transaction.change(changeAddress); - var options = {}; - options.disableIsFullySigned = true; - expect(function() { - return transaction.serialize(options); - }).not.to.throw(errors.Transaction.MissingSignatures); - expect(function() { - return transaction.serialize(); - }).to.throw(errors.Transaction.MissingSignatures); - }); - it('can skip the check that avoids spending more bitcoins than the inputs for a transaction', function() { - var transaction = new Transaction(); - transaction.from(simpleUtxoWith1BTC); - transaction.to(toAddress, 10000000000000); - transaction.change(changeAddress); - expect(function() { - return transaction.serialize({ - disableSmallFees: true, - disableIsFullySigned: true, - disableMoreOutputThanInput: true - }); - }).not.to.throw(errors.Transaction.InvalidOutputAmountSum); - expect(function() { - return transaction.serialize({ - disableIsFullySigned: true, - disableSmallFees: true - }); - }).to.throw(errors.Transaction.InvalidOutputAmountSum); - }); + }, 'disableDustOutputs', errors.Transaction.DustOutputs)); + it('can skip the check that prevents unsigned outputs', buildSkipTest( + function(transaction) { + return transaction + .to(toAddress, 10000) + .change(changeAddress); + }, 'disableIsFullySigned', errors.Transaction.UnableToVerifySignature)); + it('can skip the check that avoids spending more bitcoins than the inputs for a transaction', buildSkipTest( + function(transaction) { + return transaction + .to(toAddress, 10000000000000) + .change(changeAddress); + }, 'disableMoreOutputThanInput', + errors.Transaction.InvalidOutputAmountSum, + { + 'disableSmallFees': true, + 'disableIsFullySigned': true + })); }); });