Browse Source

Add check for output amount > input amount

patch-2
eordano 10 years ago
parent
commit
c5d7eacfac
  1. 3
      lib/errors/spec.js
  2. 57
      lib/transaction/transaction.js
  3. 7
      test/transaction/transaction.js

3
lib/errors/spec.js

@ -60,6 +60,9 @@ module.exports = [{
}, {
name: 'NeedMoreInfo',
message: '{0}'
}, {
name: 'InvalidOutputAmountSum',
message: '{0}'
}, {
name: 'MissingSignatures',
message: 'Some inputs have not been fully signed'

57
lib/transaction/transaction.js

@ -110,13 +110,12 @@ Transaction.prototype._getHash = function() {
*
* @param {Object|boolean=} unsafe if true, skip all tests. if it's an object,
* it's expected to contain a set of flags to skip certain tests:
* <ul>
* <li><tt>disableAll</tt>: disable all checks</li>
* <li><tt>disableSmallFees</tt>: disable checking for fees that are too small</li>
* <li><tt>disableLargeFees</tt>: disable checking for fees that are too large</li>
* <li><tt>disableNotFullySigned</tt>: disable checking if all inputs are fully signed</li>
* <li><tt>disableDustOutputs</tt>: disable checking if there are no outputs that are dust amounts</li>
* </ul>
* * `disableAll`: disable all checks
* * `disableSmallFees`: disable checking for fees that are too small
* * `disableLargeFees`: disable checking for fees that are too large
* * `disableNotFullySigned`: disable checking if all inputs are fully signed
* * `disableDustOutputs`: disable checking if there are no outputs that are dust amounts
* * `disableMoreOutputThanInput`: disable checking if the transaction spends more bitcoins than the sum of the input amounts
* @return {string}
*/
Transaction.prototype.serialize = function(unsafe) {
@ -136,15 +135,33 @@ Transaction.prototype.uncheckedSerialize = Transaction.prototype.toString = func
* (decoderawtransaction, sendrawtransaction)
*
* @param {Object} opts allows to skip certain tests:
* <ul>
* <li><tt>disableSmallFees</tt>: disable checking for fees that are too small</li>
* <li><tt>disableLargeFees</tt>: disable checking for fees that are too large</li>
* <li><tt>disableIsFullySigned</tt>: disable checking if all inputs are fully signed</li>
* <li><tt>disableDustOutputs</tt>: disable checking if there are no outputs that are dust amounts</li>
* </ul>
* * `disableSmallFees`: disable checking for fees that are too small
* * `disableLargeFees`: disable checking for fees that are too large
* * `disableIsFullySigned`: disable checking if all inputs are fully signed
* * `disableDustOutputs`: disable checking if there are no outputs that are dust amounts
* * `disableMoreOutputThanInput`: disable checking if the transaction spends more bitcoins than the sum of the input amounts
* @return {string}
*/
Transaction.prototype.checkedSerialize = function(opts) {
var serializationError = this.getSerializationError(opts);
if (serializationError) {
throw serializationError;
}
return this.uncheckedSerialize();
};
/**
* Retrieve a possible error that could appear when trying to serialize and broadcast this transaction
*
* @param {Object} opts allows to skip certain tests:
* * `disableSmallFees`: disable checking for fees that are too small
* * `disableLargeFees`: disable checking for fees that are too large
* * `disableIsFullySigned`: disable checking if all inputs are fully signed
* * `disableDustOutputs`: disable checking if there are no outputs that are dust amounts
* * `disableMoreOutputThanInput`: disable checking if the transaction spends more bitcoins than the sum of the input amounts
* @return {bitcore.Error}
*/
Transaction.prototype.getSerializationError = function(opts) {
opts = opts || {};
var missingChange = this._missingChange();
var feeIsTooLarge = this._isFeeTooLarge();
@ -154,20 +171,22 @@ Transaction.prototype.checkedSerialize = function(opts) {
if (!opts.disableLargeFees && feeIsTooLarge) {
if (missingChange) {
throw new errors.Transaction.ChangeAddressMissing('Fee is too large and no change address was provided');
return new errors.Transaction.ChangeAddressMissing('Fee is too large and no change address was provided');
}
throw new errors.Transaction.FeeError(feeIsTooLarge);
return new errors.Transaction.FeeError(feeIsTooLarge);
}
if (!opts.disableSmallFees && feeIsTooSmall) {
throw new errors.Transaction.FeeError(feeIsTooSmall);
return new errors.Transaction.FeeError(feeIsTooSmall);
}
if (!opts.disableDustOutputs && this._hasDustOutputs()) {
throw new errors.Transaction.DustOutputs();
return new errors.Transaction.DustOutputs();
}
if (!opts.disableIsFullySigned && !isFullySigned) {
throw new errors.Transaction.MissingSignatures();
return new errors.Transaction.MissingSignatures();
}
if (!opts.disableMoreOutputThanInput && this._getUnspentValue < 0) {
return new errors.Transaction.InvalidOutputAmountSum();
}
return this.uncheckedSerialize();
};
Transaction.FEE_SECURITY_MARGIN = 15;

7
test/transaction/transaction.js

@ -388,6 +388,13 @@ describe('Transaction', function() {
.change(changeAddress);
}, 'disableIsFullySigned');
});
it('can skip the check that avoids spending more bitcoins than the inputs for a transaction', function() {
buildSkipTest(function(transaction) {
return transaction
.to(toAddress, 10000000000)
.change(changeAddress);
}, 'disableMoreOutputThanInput');
});
});
});

Loading…
Cancel
Save