Add check for output amount > input amount
This commit is contained in:
parent
bd172e7c09
commit
c5d7eacfac
@ -60,6 +60,9 @@ module.exports = [{
|
|||||||
}, {
|
}, {
|
||||||
name: 'NeedMoreInfo',
|
name: 'NeedMoreInfo',
|
||||||
message: '{0}'
|
message: '{0}'
|
||||||
|
}, {
|
||||||
|
name: 'InvalidOutputAmountSum',
|
||||||
|
message: '{0}'
|
||||||
}, {
|
}, {
|
||||||
name: 'MissingSignatures',
|
name: 'MissingSignatures',
|
||||||
message: 'Some inputs have not been fully signed'
|
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,
|
* @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:
|
* it's expected to contain a set of flags to skip certain tests:
|
||||||
* <ul>
|
* * `disableAll`: disable all checks
|
||||||
* <li><tt>disableAll</tt>: disable all checks</li>
|
* * `disableSmallFees`: disable checking for fees that are too small
|
||||||
* <li><tt>disableSmallFees</tt>: disable checking for fees that are too small</li>
|
* * `disableLargeFees`: disable checking for fees that are too large
|
||||||
* <li><tt>disableLargeFees</tt>: disable checking for fees that are too large</li>
|
* * `disableNotFullySigned`: disable checking if all inputs are fully signed
|
||||||
* <li><tt>disableNotFullySigned</tt>: disable checking if all inputs are fully signed</li>
|
* * `disableDustOutputs`: disable checking if there are no outputs that are dust amounts
|
||||||
* <li><tt>disableDustOutputs</tt>: disable checking if there are no outputs that are dust amounts</li>
|
* * `disableMoreOutputThanInput`: disable checking if the transaction spends more bitcoins than the sum of the input amounts
|
||||||
* </ul>
|
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
Transaction.prototype.serialize = function(unsafe) {
|
Transaction.prototype.serialize = function(unsafe) {
|
||||||
@ -136,15 +135,33 @@ Transaction.prototype.uncheckedSerialize = Transaction.prototype.toString = func
|
|||||||
* (decoderawtransaction, sendrawtransaction)
|
* (decoderawtransaction, sendrawtransaction)
|
||||||
*
|
*
|
||||||
* @param {Object} opts allows to skip certain tests:
|
* @param {Object} opts allows to skip certain tests:
|
||||||
* <ul>
|
* * `disableSmallFees`: disable checking for fees that are too small
|
||||||
* <li><tt>disableSmallFees</tt>: disable checking for fees that are too small</li>
|
* * `disableLargeFees`: disable checking for fees that are too large
|
||||||
* <li><tt>disableLargeFees</tt>: disable checking for fees that are too large</li>
|
* * `disableIsFullySigned`: disable checking if all inputs are fully signed
|
||||||
* <li><tt>disableIsFullySigned</tt>: disable checking if all inputs are fully signed</li>
|
* * `disableDustOutputs`: disable checking if there are no outputs that are dust amounts
|
||||||
* <li><tt>disableDustOutputs</tt>: disable checking if there are no outputs that are dust amounts</li>
|
* * `disableMoreOutputThanInput`: disable checking if the transaction spends more bitcoins than the sum of the input amounts
|
||||||
* </ul>
|
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
Transaction.prototype.checkedSerialize = function(opts) {
|
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 || {};
|
opts = opts || {};
|
||||||
var missingChange = this._missingChange();
|
var missingChange = this._missingChange();
|
||||||
var feeIsTooLarge = this._isFeeTooLarge();
|
var feeIsTooLarge = this._isFeeTooLarge();
|
||||||
@ -154,20 +171,22 @@ Transaction.prototype.checkedSerialize = function(opts) {
|
|||||||
|
|
||||||
if (!opts.disableLargeFees && feeIsTooLarge) {
|
if (!opts.disableLargeFees && feeIsTooLarge) {
|
||||||
if (missingChange) {
|
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) {
|
if (!opts.disableSmallFees && feeIsTooSmall) {
|
||||||
throw new errors.Transaction.FeeError(feeIsTooSmall);
|
return new errors.Transaction.FeeError(feeIsTooSmall);
|
||||||
}
|
}
|
||||||
if (!opts.disableDustOutputs && this._hasDustOutputs()) {
|
if (!opts.disableDustOutputs && this._hasDustOutputs()) {
|
||||||
throw new errors.Transaction.DustOutputs();
|
return new errors.Transaction.DustOutputs();
|
||||||
}
|
}
|
||||||
if (!opts.disableIsFullySigned && !isFullySigned) {
|
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;
|
Transaction.FEE_SECURITY_MARGIN = 15;
|
||||||
|
|||||||
@ -388,6 +388,13 @@ describe('Transaction', function() {
|
|||||||
.change(changeAddress);
|
.change(changeAddress);
|
||||||
}, 'disableIsFullySigned');
|
}, '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