@@ -2,7 +2,6 @@ var bip66 = require('bip66')
22var bufferutils = require ( './bufferutils' )
33var typeforce = require ( 'typeforce' )
44var types = require ( './types' )
5-
65var OPS = require ( './opcodes.json' )
76var REVERSE_OPS = ( function ( ) {
87 var result = { }
@@ -251,27 +250,55 @@ function isMultisigInput (script, allowIncomplete) {
251250 return chunks . slice ( 1 ) . every ( isCanonicalSignature )
252251}
253252
254- function isMultisigOutput ( script ) {
255- var chunks = decompile ( script )
256- if ( chunks . length < 4 ) return false
257- if ( chunks [ chunks . length - 1 ] !== OPS . OP_CHECKMULTISIG ) return false
258-
259- var mOp = chunks [ 0 ]
260- var nOp = chunks [ chunks . length - 2 ]
253+ function parseMultisigScript ( scriptPubKey ) {
254+ var chunks = decompile ( scriptPubKey )
255+ if ( chunks . length < 4 ) {
256+ throw new Error ( 'Multisig script should contain at least 4 elements' )
257+ }
258+ if ( chunks [ chunks . length - 1 ] !== OPS . OP_CHECKMULTISIG ) {
259+ throw new Error ( 'Final opcode should be OP_CHECKMULTISIG' )
260+ }
261+ if ( ! types . Number ( chunks [ 0 ] ) ) {
262+ throw new Error ( 'First element must be a number-push opcode' )
263+ }
264+ if ( ! types . Number ( chunks [ chunks . length - 2 ] ) ) {
265+ throw new Error ( 'Second-last element must be a number-push opcode' )
266+ }
267+ var m = chunks [ 0 ] - OP_INT_BASE
268+ var n = chunks [ chunks . length - 2 ] - OP_INT_BASE
261269
262- if ( ! types . Number ( mOp ) ) return false
263- if ( ! types . Number ( nOp ) ) return false
270+ if ( m <= 0 ) {
271+ throw new Error ( 'Number of signatures required must be greater than zero' )
272+ }
273+ if ( n > 16 ) {
274+ throw new Error ( 'Number of public keys must be less than 17' )
275+ }
276+ if ( m > n ) {
277+ throw new Error ( 'Number of signatures cannot exceed the number of public keys' )
278+ }
279+ if ( n !== chunks . length - 3 ) {
280+ throw new Error ( 'n does not match the number of public keys' )
281+ }
264282
265- var m = mOp - OP_INT_BASE
266- var n = nOp - OP_INT_BASE
283+ var keys = chunks . slice ( 1 , - 2 )
284+ if ( ! keys . every ( isCanonicalPubKey ) ) {
285+ throw new Error ( 'Non-canonical pubic key found' )
286+ }
267287
268- // 0 < m <= n <= 16
269- if ( m <= 0 ) return false
270- if ( m > n ) return false
271- if ( n > 16 ) return false
272- if ( n !== chunks . length - 3 ) return false
288+ return {
289+ nRequiredSigs : m ,
290+ nPublicKeys : n ,
291+ publicKeyBuffers : keys
292+ }
293+ }
273294
274- return chunks . slice ( 1 , - 2 ) . every ( isCanonicalPubKey )
295+ function isMultisigOutput ( script ) {
296+ try {
297+ parseMultisigScript ( script )
298+ return true
299+ } catch ( e ) {
300+ return false
301+ }
275302}
276303
277304function isNullDataOutput ( script ) {
@@ -399,16 +426,9 @@ function witnessScriptHashInput (scriptSig, scriptPubKey) {
399426// OP_0 [signatures ...]
400427function multisigInput ( signatures , scriptPubKey ) {
401428 if ( scriptPubKey ) {
402- var chunks = decompile ( scriptPubKey )
403- if ( ! isMultisigOutput ( chunks ) ) throw new Error ( 'Expected multisig scriptPubKey' )
404-
405- var mOp = chunks [ 0 ]
406- var nOp = chunks [ chunks . length - 2 ]
407- var m = mOp - OP_INT_BASE
408- var n = nOp - OP_INT_BASE
409-
410- if ( signatures . length < m ) throw new Error ( 'Not enough signatures provided' )
411- if ( signatures . length > n ) throw new Error ( 'Too many signatures provided' )
429+ var scriptData = parseMultisigScript ( scriptPubKey )
430+ if ( signatures . length < scriptData . nRequiredSigs ) throw new Error ( 'Not enough signatures provided' )
431+ if ( signatures . length > scriptData . nPublicKeys ) throw new Error ( 'Too many signatures provided' )
412432 }
413433
414434 return compile ( [ ] . concat ( OPS . OP_0 , signatures ) )
@@ -441,6 +461,7 @@ module.exports = {
441461 isMultisigOutput : isMultisigOutput ,
442462 isNullDataOutput : isNullDataOutput ,
443463
464+ parseMultisigScript : parseMultisigScript ,
444465 classifyOutput : classifyOutput ,
445466 classifyInput : classifyInput ,
446467 pubKeyOutput : pubKeyOutput ,
0 commit comments