diff --git a/lib/bcoin/mtx.js b/lib/bcoin/mtx.js index 1346f37c..7523900b 100644 --- a/lib/bcoin/mtx.js +++ b/lib/bcoin/mtx.js @@ -684,21 +684,37 @@ MTX.prototype.scriptOutput = function scriptOutput(index, options) { output.script = Script.createOutputScript(options); }; -MTX.prototype.maxSize = function maxSize(maxM, maxN) { - var copy = this.clone(); +MTX.prototype.isScripted = function isScripted() { + if (this.inputs.length === 0) + return false; + + if (this.outputs.length === 0) + return false; + + return this.inputs.every(function(input) { + return input.script.code.length > 0 || input.witness.items.length > 0; + }); +}; + +MTX.prototype.maxSize = function maxSize(maxM, maxN, force) { var i, j, input, total, size, prev, m, n, witness; - // Create copy with 0-script inputs - for (i = 0; i < copy.inputs.length; i++) { - copy.inputs[i].script = new Script([]); - copy.inputs[i].witness = new Witness([]); + if (!force && this.isScripted()) + return this.getVirtualSize(); + + // Calculate the size, minus the input scripts. + total = bcoin.protocol.framer.tx.size(this); + + for (i = 0; i < this.inputs.length; i++) { + input = this.inputs[i]; + size = input.script.getSize(); + total -= utils.sizeVarint(size) + size; + total += 1; } - total = bcoin.protocol.framer.tx.size(copy); - // Add size for signatures and public keys - for (i = 0; i < copy.inputs.length; i++) { - input = copy.inputs[i]; + for (i = 0; i < this.inputs.length; i++) { + input = this.inputs[i]; size = 0; witness = false; @@ -712,12 +728,12 @@ MTX.prototype.maxSize = function maxSize(maxM, maxN) { // If we have access to the redeem script, // we can use it to calculate size much easier. - if (this.inputs[i].script.code.length && prev.isScripthash()) { + if (input.script.code.length && prev.isScripthash()) { // Need to add the redeem script size // here since it will be ignored by // the isMultisig clause. // OP_PUSHDATA2 [redeem] - prev = this.inputs[i].script.getRedeem(); + prev = input.script.getRedeem(); size += 3 + prev.getSize(); } @@ -727,8 +743,8 @@ MTX.prototype.maxSize = function maxSize(maxM, maxN) { // redeem script (if there was one) // is now worth 4 points. size *= 4; - if (this.inputs[i].witness.items.length && prev.isWitnessScripthash()) { - prev = this.inputs[i].witness.getRedeem(); + if (input.witness.items.length && prev.isWitnessScripthash()) { + prev = input.witness.getRedeem(); size += 3 + prev.getSize(); } else if (prev.isWitnessPubkeyhash()) { prev = Script.createPubkeyhash(prev.code[1]); @@ -889,7 +905,7 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) { // bytes (10000 satoshi for every 1024 bytes). do { // Calculate max possible size after signing. - size = tx.maxSize(options.m, options.n); + size = tx.maxSize(options.m, options.n, true); if (tryFree) { if (tx.isFree(network.height + 1, size)) {