Skip to content

Commit 53f08a7

Browse files
afk11dcousens
authored andcommitted
Script: add function for parsing multisig type scripts
1 parent 405c005 commit 53f08a7

File tree

1 file changed

+49
-28
lines changed

1 file changed

+49
-28
lines changed

src/script.js

Lines changed: 49 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ var bip66 = require('bip66')
22
var bufferutils = require('./bufferutils')
33
var typeforce = require('typeforce')
44
var types = require('./types')
5-
65
var OPS = require('./opcodes.json')
76
var 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

277304
function isNullDataOutput (script) {
@@ -399,16 +426,9 @@ function witnessScriptHashInput (scriptSig, scriptPubKey) {
399426
// OP_0 [signatures ...]
400427
function 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

Comments
 (0)