Add check for output amount > input amount
This commit is contained in:
parent
bd172e7c09
commit
c5d7eacfac
@ -60,6 +60,9 @@ module.exports = [{
|
||||
}, {
|
||||
name: 'NeedMoreInfo',
|
||||
message: '{0}'
|
||||
}, {
|
||||
name: 'InvalidOutputAmountSum',
|
||||
message: '{0}'
|
||||
}, {
|
||||
name: 'MissingSignatures',
|
||||
message: 'Some inputs have not been fully signed'
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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…
Reference in New Issue
Block a user