diff --git a/lib/bcoin/address.js b/lib/bcoin/address.js index fa641c08..f9272204 100644 --- a/lib/bcoin/address.js +++ b/lib/bcoin/address.js @@ -250,14 +250,14 @@ Address.prototype.fromScript = function fromScript(script) { } // Fast case - if (script.isPubkey()) { + if (script.isPubkey(true)) { this.hash = utils.hash160(script.raw.slice(1, script.raw[0] + 1)); this.type = 'pubkeyhash'; this.version = -1; return this; } - if (script.isPubkeyhash()) { + if (script.isPubkeyhash(true)) { this.hash = script.raw.slice(3, 23); this.type = 'pubkeyhash'; this.version = -1; @@ -272,14 +272,14 @@ Address.prototype.fromScript = function fromScript(script) { } // Slow case (allow non-minimal data and parse script) - if (script.isPubkey(true)) { + if (script.isPubkey()) { this.hash = utils.hash160(script.code[0].data); this.type = 'pubkeyhash'; this.version = -1; return this; } - if (script.isPubkeyhash(true)) { + if (script.isPubkeyhash()) { this.hash = script.code[2].data; this.type = 'pubkeyhash'; this.version = -1; diff --git a/lib/bcoin/coins.js b/lib/bcoin/coins.js index b405b056..70346033 100644 --- a/lib/bcoin/coins.js +++ b/lib/bcoin/coins.js @@ -193,7 +193,7 @@ Coins.prototype.toRaw = function toRaw(writer) { prefix = 0; // Saves up to 7 bytes. - if (output.script.isPubkeyhash()) { + if (output.script.isPubkeyhash(true)) { prefix = 1; hash = output.script.code[2].data; } else if (output.script.isScripthash()) { diff --git a/lib/bcoin/mtx.js b/lib/bcoin/mtx.js index a41ed469..f591586f 100644 --- a/lib/bcoin/mtx.js +++ b/lib/bcoin/mtx.js @@ -300,7 +300,7 @@ MTX.prototype.scriptInput = function scriptInput(index, addr) { vector = input.script; } - if (prev.isPubkey(true)) { + if (prev.isPubkey()) { // P2PK if (!utils.equal(prev.get(1), addr.publicKey)) return false; @@ -310,7 +310,7 @@ MTX.prototype.scriptInput = function scriptInput(index, addr) { return true; vector.set(0, opcodes.OP_0); - } else if (prev.isPubkeyhash(true)) { + } else if (prev.isPubkeyhash()) { // P2PKH if (!utils.equal(prev.get(2), addr.keyHash)) return false; @@ -474,7 +474,7 @@ MTX.prototype.signInput = function signInput(index, addr, key, type) { signature = this.createSignature(index, prev, key, type, version); // P2PK - if (prev.isPubkey(true)) { + if (prev.isPubkey()) { // Already signed. if (Script.isSignature(vector.get(0))) return true; @@ -493,7 +493,7 @@ MTX.prototype.signInput = function signInput(index, addr, key, type) { } // P2PKH - if (prev.isPubkeyhash(true)) { + if (prev.isPubkeyhash()) { // Already signed. if (Script.isSignature(vector.get(0))) return true; @@ -673,10 +673,10 @@ MTX.prototype.isSigned = function isSigned() { len = vector.length; } - if (prev.isPubkey(true)) { + if (prev.isPubkey()) { if (!Script.isSignature(vector.get(0))) return false; - } else if (prev.isPubkeyhash(true)) { + } else if (prev.isPubkeyhash()) { if (!Script.isSignature(vector.get(0))) return false; } else if (prev.isMultisig()) { @@ -883,11 +883,11 @@ MTX.prototype.maxSize = function maxSize(options, force) { } } - if (prev.isPubkey(true)) { + if (prev.isPubkey()) { // P2PK // OP_PUSHDATA0 [signature] size += 1 + 73; - } else if (prev.isPubkeyhash(true)) { + } else if (prev.isPubkeyhash()) { // P2PKH // OP_PUSHDATA0 [signature] size += 1 + 73; diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index 955a8d5c..725be882 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -2827,53 +2827,54 @@ Script.prototype.getAddress = function getAddress() { /** * Test whether the output script is pay-to-pubkey. - * @param {Boolean} [sloppy=false] - Allow non-minimal scripts. + * @param {Boolean} [minimal=false] - Minimaldata only. * @returns {Boolean} */ -Script.prototype.isPubkey = function isPubkey(sloppy) { - if (sloppy) { - return this.code.length === 2 - && Script.isKey(this.code[0].data) - && this.code[1].value === opcodes.OP_CHECKSIG; +Script.prototype.isPubkey = function isPubkey(minimal) { + if (minimal) { + return this.raw[0] >= 33 && this.raw[0] <= 65 + && this.raw[0] + 2 === this.raw.length + && this.raw[this.raw.length - 1] === opcodes.OP_CHECKSIG; } - return this.raw[0] >= 33 && this.raw[0] <= 65 - && this.raw[0] + 2 === this.raw.length - && this.raw[this.raw.length - 1] === opcodes.OP_CHECKSIG; + return this.code.length === 2 + && Script.isKey(this.code[0].data) + && this.code[1].value === opcodes.OP_CHECKSIG; }; /** * Test whether the output script is pay-to-pubkeyhash. - * @param {Boolean} [sloppy=false] - Allow non-minimal scripts. + * @param {Boolean} [minimal=false] - Minimaldata only. * @returns {Boolean} */ -Script.prototype.isPubkeyhash = function isPubkeyhash(sloppy) { - if (sloppy) { - return this.code.length === 5 - && this.code[0].value === opcodes.OP_DUP - && this.code[1].value === opcodes.OP_HASH160 - && Script.isHash(this.code[2].data) - && this.code[3].value === opcodes.OP_EQUALVERIFY - && this.code[4].value === opcodes.OP_CHECKSIG; +Script.prototype.isPubkeyhash = function isPubkeyhash(minimal) { + if (!minimal) { + return this.raw.length === 25 + && this.raw[0] === opcodes.OP_DUP + && this.raw[1] === opcodes.OP_HASH160 + && this.raw[2] === 0x14 + && this.raw[23] === opcodes.OP_EQUALVERIFY + && this.raw[24] === opcodes.OP_CHECKSIG; } - return this.raw.length === 25 - && this.raw[0] === opcodes.OP_DUP - && this.raw[1] === opcodes.OP_HASH160 - && this.raw[2] === 0x14 - && this.raw[23] === opcodes.OP_EQUALVERIFY - && this.raw[24] === opcodes.OP_CHECKSIG; + return this.code.length === 5 + && this.code[0].value === opcodes.OP_DUP + && this.code[1].value === opcodes.OP_HASH160 + && Script.isHash(this.code[2].data) + && this.code[3].value === opcodes.OP_EQUALVERIFY + && this.code[4].value === opcodes.OP_CHECKSIG; }; /** * Test whether the output script is pay-to-multisig. + * @param {Boolean} [minimal=false] - Minimaldata only. * @returns {Boolean} */ -Script.prototype.isMultisig = function isMultisig() { - var m, n, i; +Script.prototype.isMultisig = function isMultisig(minimal) { + var m, n, i, op; if (this.raw.length < 41) return false; @@ -2895,8 +2896,15 @@ Script.prototype.isMultisig = function isMultisig() { return false; for (i = 1; i < n + 1; i++) { - if (!Script.isKey(this.code[i].data)) + op = this.code[i]; + + if (!Script.isKey(op.data)) return false; + + if (minimal) { + if (!Script.isMinimal(op.data, op.value)) + return false; + } } return true; @@ -2919,11 +2927,11 @@ Script.prototype.isScripthash = function isScripthash() { /** * Test whether the output script is nulldata/opreturn. - * @param {Boolean} [sloppy=false] - Allow non-minimal scripts. + * @param {Boolean} [minimal=false] - Minimaldata only. * @returns {Boolean} */ -Script.prototype.isNulldata = function isNulldata(sloppy) { +Script.prototype.isNulldata = function isNulldata(minimal) { var i, op; if (this.raw.length > constants.script.MAX_OP_RETURN_BYTES) @@ -2938,29 +2946,30 @@ Script.prototype.isNulldata = function isNulldata(sloppy) { if (this.raw.length === 1) return true; - if (sloppy) { - for (i = 1; i < this.code.length; i++) { - op = this.code[i]; - if (op.data) - continue; - if (op.value === -1) - return false; - if (op.value > opcodes.OP_16) - return false; - } - return true; + if (minimal) { + if (this.raw.length === 2) + return Script.getSmall(this.raw[1]) !== -1; + + if (this.raw[1] >= 0x01 && this.raw[1] <= 0x4b) + return this.raw[1] + 2 === this.raw.length; + + if (this.raw[1] === opcodes.OP_PUSHDATA1) + return this.raw[2] > 75 && this.raw[2] + 3 === this.raw.length; + + return false; } - if (this.raw.length === 2) - return Script.getSmall(this.raw[1]) !== -1; + for (i = 1; i < this.code.length; i++) { + op = this.code[i]; + if (op.data) + continue; + if (op.value === -1) + return false; + if (op.value > opcodes.OP_16) + return false; + } - if (this.raw[1] >= 0x01 && this.raw[1] <= 0x4b) - return this.raw[1] + 2 === this.raw.length; - - if (this.raw[1] === opcodes.OP_PUSHDATA1) - return this.raw[2] > 75 && this.raw[2] + 3 === this.raw.length; - - return false; + return true; }; /** diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index 07928dee..9b69bf2f 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -1735,7 +1735,7 @@ TX.prototype.isWatched = function isWatched(filter) { outpoint = bcoin.outpoint.fromTX(this, i); filter.add(outpoint.toRaw()); } else if (filter.update === constants.filterFlags.PUBKEY_ONLY) { - if (output.script.isPubkey(true) || output.script.isMultisig()) { + if (output.script.isPubkey() || output.script.isMultisig()) { outpoint = bcoin.outpoint.fromTX(this, i); filter.add(outpoint.toRaw()); }