From a686817f3cd4ca82e831fef8ebb5b56e2b2e12f3 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Fri, 2 Oct 2015 12:36:51 +1000 Subject: [PATCH 1/5] tests: add m/n is data failing tests --- test/fixtures/script.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/fixtures/script.json b/test/fixtures/script.json index 81f905d..8abdcd1 100644 --- a/test/fixtures/script.json +++ b/test/fixtures/script.json @@ -245,6 +245,14 @@ "description": "n > len(pubKeys)", "scriptPubKey": "OP_1 024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34 OP_2 OP_CHECKMULTISIG" }, + { + "description": "m is data", + "scriptPubKey": "ffff 024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34 OP_1 OP_CHECKMULTISIG" + }, + { + "description": "n is data", + "scriptPubKey": "OP_1 024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34 ffff OP_CHECKMULTISIG" + }, { "description": "non-canonical pubKey (bad length)", "scriptPubKey": "OP_1 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffff OP_1 OP_CHECKMULTISIG" From 74c2f1d957413acf8e9da85ed4e87759b1de1e5b Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Fri, 2 Oct 2015 12:51:34 +1000 Subject: [PATCH 2/5] script: n/m must be numbers, not data --- src/script.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/script.js b/src/script.js index d6d5c31..3d82557 100644 --- a/src/script.js +++ b/src/script.js @@ -225,10 +225,12 @@ function isMultisigOutput (script) { if (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG) return false var mOp = chunks[0] + if (!types.Number(mOp)) return false if (mOp < OPS.OP_1) return false if (mOp > OPS.OP_16) return false var nOp = chunks[chunks.length - 2] + if (!types.Number(nOp)) return false if (nOp < OPS.OP_1) return false if (nOp > OPS.OP_16) return false From 5be9b04741f0e4acdcf5fe153d1c48af2ecf32c0 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Fri, 2 Oct 2015 12:59:30 +1000 Subject: [PATCH 3/5] script: isolate initialization of REVERSE_OPS --- src/script.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/script.js b/src/script.js index 3d82557..0c8749b 100644 --- a/src/script.js +++ b/src/script.js @@ -4,11 +4,14 @@ var typeforce = require('typeforce') var types = require('./types') var OPS = require('./opcodes') -var REVERSE_OPS = [] -for (var op in OPS) { - var code = OPS[op] - REVERSE_OPS[code] = op -} +var REVERSE_OPS = (function () { + var result = {} + for (var op in OPS) { + var code = OPS[op] + result[code] = op + } + return result +})() function toASM (chunks) { if (types.Buffer(chunks)) { From 0ca1e40a6d9954bbc672d5c22222851e1f632342 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Fri, 2 Oct 2015 13:00:00 +1000 Subject: [PATCH 4/5] script: refactor isMultisigOutput for clarity --- src/script.js | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/script.js b/src/script.js index 0c8749b..69ce147 100644 --- a/src/script.js +++ b/src/script.js @@ -13,6 +13,8 @@ var REVERSE_OPS = (function () { return result })() +const OP_INT_BASE = OPS.OP_RESERVED // OP_1 - 1 + function toASM (chunks) { if (types.Buffer(chunks)) { chunks = decompile(chunks) @@ -228,18 +230,18 @@ function isMultisigOutput (script) { if (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG) return false var mOp = chunks[0] - if (!types.Number(mOp)) return false - if (mOp < OPS.OP_1) return false - if (mOp > OPS.OP_16) return false - var nOp = chunks[chunks.length - 2] - if (!types.Number(nOp)) return false - if (nOp < OPS.OP_1) return false - if (nOp > OPS.OP_16) return false - var m = mOp - (OPS.OP_1 - 1) - var n = nOp - (OPS.OP_1 - 1) - if (n < m) return false + if (!types.Number(mOp)) return false + if (!types.Number(nOp)) return false + + var m = mOp - OP_INT_BASE + var n = nOp - OP_INT_BASE + + // 0 < m <= n <= 16 + if (m <= 0) return false + if (m > n) return false + if (n > 16) return false var pubKeys = chunks.slice(1, -2) if (n !== pubKeys.length) return false @@ -314,9 +316,9 @@ function multisigOutput (m, pubKeys) { if (n < m) throw new Error('Not enough pubKeys provided') return compile([].concat( - (OPS.OP_1 - 1) + m, + OP_INT_BASE + m, pubKeys, - (OPS.OP_1 - 1) + n, + OP_INT_BASE + n, OPS.OP_CHECKMULTISIG )) } @@ -354,8 +356,8 @@ function multisigInput (signatures, scriptPubKey) { var mOp = chunks[0] var nOp = chunks[chunks.length - 2] - var m = mOp - (OPS.OP_1 - 1) - var n = nOp - (OPS.OP_1 - 1) + var m = mOp - OP_INT_BASE + var n = nOp - OP_INT_BASE if (signatures.length < m) throw new Error('Not enough signatures provided') if (signatures.length > n) throw new Error('Too many signatures provided') From 173994c6e0034f3218cf86769d3d6c68264e7112 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Fri, 2 Oct 2015 13:02:03 +1000 Subject: [PATCH 5/5] script: avoid slice if n !== pubKeys.length --- src/script.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/script.js b/src/script.js index 69ce147..2004fa1 100644 --- a/src/script.js +++ b/src/script.js @@ -242,11 +242,9 @@ function isMultisigOutput (script) { if (m <= 0) return false if (m > n) return false if (n > 16) return false + if (n !== chunks.length - 3) return false - var pubKeys = chunks.slice(1, -2) - if (n !== pubKeys.length) return false - - return pubKeys.every(isCanonicalPubKey) + return chunks.slice(1, -2).every(isCanonicalPubKey) } function isNullDataOutput (script) {