When checking for transaction serialization errors, check the output amount before checking fee errors. Added a test for it and also improved buildSkipTest by specifying which error to expect and using it for some tests where it wasn't used yet.

This commit is contained in:
David de Kloet 2015-05-18 22:40:54 +02:00 committed by Braydon Fuller
parent 001f71d1bf
commit 8c5b2c851b
2 changed files with 40 additions and 42 deletions

View File

@ -192,10 +192,10 @@ Transaction.prototype.getSerializationError = function(opts) {
opts = opts || {}; opts = opts || {};
return this._isInvalidSatoshis() || return this._isInvalidSatoshis() ||
this._hasMoreOutputThanInput(opts) ||
this._hasFeeError(opts) || this._hasFeeError(opts) ||
this._hasDustOutputs(opts) || this._hasDustOutputs(opts) ||
this._isMissingSignatures(opts) || this._isMissingSignatures(opts);
this._hasMoreOutputThanInput(opts);
}; };
Transaction.prototype._isInvalidSatoshis = function() { Transaction.prototype._isInvalidSatoshis = function() {

View File

@ -385,22 +385,36 @@ describe('Transaction', function() {
return transaction.serialize(); return transaction.serialize();
}).to.throw(errors.Transaction.FeeError.Different); }).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() { describe('skipping checks', function() {
var buildSkipTest = function(builder, check) { var buildSkipTest = function(builder, check, expectedError, opts) {
return function() { return function() {
var transaction = new Transaction(); var transaction = new Transaction();
transaction.from(simpleUtxoWith1BTC); transaction.from(simpleUtxoWith1BTC);
builder(transaction); builder(transaction);
var options = {}; var options = opts || {};
options[check] = true; options[check] = true;
expect(function() { expect(function() {
return transaction.serialize(options); return transaction.serialize(options);
}).not.to.throw(); }).not.to.throw();
options[check] = false;
expect(function() { expect(function() {
return transaction.serialize(); return transaction.serialize(options);
}).to.throw(); }).to.throw(expectedError);
}; };
}; };
it('can skip the check for too much fee', buildSkipTest( it('can skip the check for too much fee', buildSkipTest(
@ -409,54 +423,38 @@ describe('Transaction', function() {
.fee(50000000) .fee(50000000)
.change(changeAddress) .change(changeAddress)
.sign(privateKey); .sign(privateKey);
}, 'disableLargeFees')); }, 'disableLargeFees', errors.Transaction.FeeError.TooLarge));
it('can skip the check for a fee that is too small', buildSkipTest( it('can skip the check for a fee that is too small', buildSkipTest(
function(transaction) { function(transaction) {
return transaction return transaction
.fee(1) .fee(1)
.change(changeAddress) .change(changeAddress)
.sign(privateKey); .sign(privateKey);
}, 'disableSmallFees')); }, 'disableSmallFees', errors.Transaction.FeeError.TooSmall));
it('can skip the check that prevents dust outputs', buildSkipTest( it('can skip the check that prevents dust outputs', buildSkipTest(
function(transaction) { function(transaction) {
return transaction return transaction
.to(toAddress, 100) .to(toAddress, 100)
.change(changeAddress) .change(changeAddress)
.sign(privateKey); .sign(privateKey);
}, 'disableDustOutputs')); }, 'disableDustOutputs', errors.Transaction.DustOutputs));
it('can skip the check that prevents unsigned outputs', function() { it('can skip the check that prevents unsigned outputs', buildSkipTest(
var transaction = new Transaction(); function(transaction) {
transaction.from(simpleUtxoWith1BTC); return transaction
transaction.to(toAddress, 10000); .to(toAddress, 10000)
transaction.change(changeAddress); .change(changeAddress);
var options = {}; }, 'disableIsFullySigned', errors.Transaction.UnableToVerifySignature));
options.disableIsFullySigned = true; it('can skip the check that avoids spending more bitcoins than the inputs for a transaction', buildSkipTest(
expect(function() { function(transaction) {
return transaction.serialize(options); return transaction
}).not.to.throw(errors.Transaction.MissingSignatures); .to(toAddress, 10000000000000)
expect(function() { .change(changeAddress);
return transaction.serialize(); }, 'disableMoreOutputThanInput',
}).to.throw(errors.Transaction.MissingSignatures); errors.Transaction.InvalidOutputAmountSum,
}); {
it('can skip the check that avoids spending more bitcoins than the inputs for a transaction', function() { 'disableSmallFees': true,
var transaction = new Transaction(); 'disableIsFullySigned': true
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);
});
}); });
}); });