diff --git a/lib/bcoin/mtx.js b/lib/bcoin/mtx.js index cf8ec2ec..08766213 100644 --- a/lib/bcoin/mtx.js +++ b/lib/bcoin/mtx.js @@ -13,6 +13,7 @@ var assert = utils.assert; var constants = bcoin.protocol.constants; var Script = bcoin.script; var opcodes = constants.opcodes; +var HASH160 = constants.ZERO_HASH.slice(0, 20); /** * A mutable transaction object. @@ -387,6 +388,8 @@ MTX.prototype.signInput = function signInput(index, addr, key, type) { // signing p2sh transactions. if (prev.isScripthash()) { prev = input.script.getRedeem(); + if (!prev) + throw new Error('Input has not been templated.'); len = vector.length - 1; } @@ -398,6 +401,8 @@ MTX.prototype.signInput = function signInput(index, addr, key, type) { // pushes onto the stack). if (prev.isWitnessScripthash()) { prev = input.witness.getRedeem(); + if (!prev) + throw new Error('Input has not been templated.'); vector = input.witness; len = vector.length - 1; version = 1; @@ -421,6 +426,9 @@ MTX.prototype.signInput = function signInput(index, addr, key, type) { if (!utils.equal(addr.publicKey, prev.get(0))) return false; + if (vector.getSmall(0) !== 0) + throw new Error('Input has not been templated.'); + vector.set(0, signature); vector.compile(); @@ -437,6 +445,9 @@ MTX.prototype.signInput = function signInput(index, addr, key, type) { if (!utils.equal(addr.keyHash, prev.get(2))) return false; + if (!Script.isKey(vector.get(1))) + throw new Error('Input has not been templated.'); + vector.set(0, signature); vector.compile(); @@ -476,6 +487,9 @@ MTX.prototype.signInput = function signInput(index, addr, key, type) { n = keys.length; } + if (vector.getSmall(0) !== 0) + throw new Error('Input has not been templated.'); + // Something is very wrong here. Abort. if (len - 1 > n) return false; @@ -582,6 +596,8 @@ MTX.prototype.isSigned = function isSigned() { // signing p2sh transactions. if (prev.isScripthash()) { prev = input.script.getRedeem(); + if (!prev) + return false; len = vector.length - 1; } @@ -590,6 +606,8 @@ MTX.prototype.isSigned = function isSigned() { // and potentially alter the length. if (prev.isWitnessScripthash()) { prev = input.witness.getRedeem(); + if (!prev) + return false; vector = input.witness; len = vector.length - 1; } else if (prev.isWitnessPubkeyhash()) { @@ -895,9 +913,9 @@ MTX.prototype.maxSize = function maxSize(options, force) { // simply add more of the fee to the change // output. // m value - m = options.m || 15; + m = options.m || 3; // n value - n = options.n || 15; + n = options.n || 3; // OP_0 size += 1; // OP_PUSHDATA0 [signature] ... @@ -1025,7 +1043,7 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) { } } - if (options.fee) { + if (options.fee != null) { fee = options.fee; // Transfer `total` funds maximum. @@ -1042,7 +1060,9 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) { address: options.changeAddress, // In case we don't have a change address, // use a fake p2pkh output to gauge size. - keyHash: constants.ZERO_HASH.slice(0, 20), + script: !options.changeAddress + ? Script.createPubkeyhash(HASH160) + : null, value: 0 }); @@ -1154,7 +1174,8 @@ MTX.prototype.fill = function fill(coins, options) { // Will only happen in rare cases where // we're redeeming all non-standard coins. - assert(changeAddress, 'No change address available.'); + if (!changeAddress) + throw new Error('No change address available.'); // Add coins to transaction. for (i = 0; i < result.coins.length; i++) @@ -1172,10 +1193,10 @@ MTX.prototype.fill = function fill(coins, options) { // Do nothing. Change is added to fee. this.outputs.pop(); this.changeIndex = -1; - assert(this.getFee() === result.fee + result.change); + assert.equal(this.getFee(), result.fee + result.change); } else { this.changeIndex = this.outputs.length - 1; - assert(this.getFee() === result.fee); + assert.equal(this.getFee(), result.fee); } return result;