Repository: bitcoinjs/bitcoinjs-lib
Pull request #482 (2015-09-30 00:46:10)

fix isMultisigOutput allowing m data
Hopefully increases readability for these calculations.



Patch:
diff --git a/src/script.js b/src/script.js
index d6d5c315..2004fa1c 100644
--- a/src/script.js
+++ b/src/script.js
@@ -4,11 +4,16 @@ 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
+})()
+
+const OP_INT_BASE = OPS.OP_RESERVED // OP_1 - 1
 
 function toASM (chunks) {
   if (types.Buffer(chunks)) {
@@ -225,21 +230,21 @@ function isMultisigOutput (script) {
   if (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG) return false
 
   var mOp = chunks[0]
-  if (mOp < OPS.OP_1) return false
-  if (mOp > OPS.OP_16) return false
-
   var nOp = chunks[chunks.length - 2]
-  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
 
-  var pubKeys = chunks.slice(1, -2)
-  if (n !== pubKeys.length) return false
+  // 0 < m <= n <= 16
+  if (m <= 0) return false
+  if (m > n) return false
+  if (n > 16) return false
+  if (n !== chunks.length - 3) return false
 
-  return pubKeys.every(isCanonicalPubKey)
+  return chunks.slice(1, -2).every(isCanonicalPubKey)
 }
 
 function isNullDataOutput (script) {
@@ -309,9 +314,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
   ))
 }
@@ -349,8 +354,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')


Test patch:
diff --git a/test/fixtures/script.json b/test/fixtures/script.json
index 81f905d5..8abdcd17 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"