From 595ada8c862fd5612227b1fc80532437775018aa Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Sun, 18 Dec 2016 03:20:47 -0800 Subject: [PATCH] mtx/wallet: more sanity checks for sending. --- lib/btc/errors.js | 14 +++++++++----- lib/primitives/mtx.js | 18 ++++++++++++------ lib/wallet/wallet.js | 18 +++++++++++++----- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/lib/btc/errors.js b/lib/btc/errors.js index 90c1cdea..6d612654 100644 --- a/lib/btc/errors.js +++ b/lib/btc/errors.js @@ -138,13 +138,17 @@ function FundingError(msg, available, required) { if (Error.captureStackTrace) Error.captureStackTrace(this, FundingError); - msg += ' (available=' + Amount.btc(available) + ','; - msg += ' required=' + Amount.btc(required) + ')'; - this.type = 'FundingError'; this.message = msg; - this.availableFunds = available; - this.requiredFunds = required; + this.availableFunds = -1; + this.requiredFunds = -1; + + if (available != null) { + this.message += ' (available=' + Amount.btc(available) + ','; + this.message += ' required=' + Amount.btc(required) + ')'; + this.availableFunds = available; + this.requiredFunds = required; + } } util.inherits(FundingError, Error); diff --git a/lib/primitives/mtx.js b/lib/primitives/mtx.js index 3c37dd27..92e61168 100644 --- a/lib/primitives/mtx.js +++ b/lib/primitives/mtx.js @@ -293,6 +293,16 @@ MTX.prototype.getSigops = function getSigops(flags) { return TX.prototype.getSigops.call(this, this.view, flags); }; +/** + * Calculate sigops weight, taking into account witness programs. + * @param {VerifyFlags?} flags + * @returns {Number} sigop weight + */ + +MTX.prototype.getSigopsCost = function getSigopsCost(flags) { + return TX.prototype.getSigopsCost.call(this, this.view, flags); +}; + /** * Perform contextual checks to verify input, output, * and fee values, as well as coinbase spend maturity @@ -1697,12 +1707,8 @@ CoinSelector.prototype.selectEstimate = co(function* selectEstimate(fee) { this.fee = this.getFee(size); - if (this.maxFee > 0 && this.fee > this.maxFee) { - throw new FundingError( - 'Fee is too high.', - this.tx.getInputValue(), - this.total()); - } + if (this.maxFee > 0 && this.fee > this.maxFee) + throw new FundingError('Fee is too high.'); // Failed to get enough funds, add more coins. if (!this.isFull()) diff --git a/lib/wallet/wallet.js b/lib/wallet/wallet.js index 3a30c227..061057c2 100644 --- a/lib/wallet/wallet.js +++ b/lib/wallet/wallet.js @@ -1622,16 +1622,24 @@ Wallet.prototype.send = co(function* send(options, passphrase) { */ Wallet.prototype._send = co(function* send(options, passphrase) { - var tx = yield this.createTX(options, true); + var mtx = yield this.createTX(options, true); + var tx; - yield this.sign(tx, passphrase); + yield this.sign(mtx, passphrase); - if (!tx.isSigned()) + if (!mtx.isSigned()) throw new Error('TX could not be fully signed.'); - assert(tx.getFee() <= constants.tx.MAX_FEE, 'TX exceeds maxfee.'); + assert(mtx.getFee() <= constants.tx.MAX_FEE, 'TX exceeds maxfee.'); - tx = tx.toTX(); + tx = mtx.toTX(); + + // Sanity checks. + if (tx.getSigopsCost(mtx.view) > constants.tx.MAX_SIGOPS_COST) + throw new Error('TX exceeds policy sigops.'); + + if (tx.getWeight() > constants.tx.MAX_WEIGHT) + throw new Error('TX exceeds policy weight.'); yield this.db.addTX(tx);