Browse Source

Script: add function for parsing multisig type scripts

hk-custom-address
Thomas Kerin 8 years ago
committed by Daniel Cousens
parent
commit
53f08a7569
  1. 77
      src/script.js

77
src/script.js

@ -2,7 +2,6 @@ var bip66 = require('bip66')
var bufferutils = require('./bufferutils') var bufferutils = require('./bufferutils')
var typeforce = require('typeforce') var typeforce = require('typeforce')
var types = require('./types') var types = require('./types')
var OPS = require('./opcodes.json') var OPS = require('./opcodes.json')
var REVERSE_OPS = (function () { var REVERSE_OPS = (function () {
var result = {} var result = {}
@ -251,27 +250,55 @@ function isMultisigInput (script, allowIncomplete) {
return chunks.slice(1).every(isCanonicalSignature) return chunks.slice(1).every(isCanonicalSignature)
} }
function isMultisigOutput (script) { function parseMultisigScript (scriptPubKey) {
var chunks = decompile(script) var chunks = decompile(scriptPubKey)
if (chunks.length < 4) return false if (chunks.length < 4) {
if (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG) return false throw new Error('Multisig script should contain at least 4 elements')
}
var mOp = chunks[0] if (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG) {
var nOp = chunks[chunks.length - 2] throw new Error('Final opcode should be OP_CHECKMULTISIG')
}
if (!types.Number(chunks[0])) {
throw new Error('First element must be a number-push opcode')
}
if (!types.Number(chunks[chunks.length - 2])) {
throw new Error('Second-last element must be a number-push opcode')
}
var m = chunks[0] - OP_INT_BASE
var n = chunks[chunks.length - 2] - OP_INT_BASE
if (!types.Number(mOp)) return false if (m <= 0) {
if (!types.Number(nOp)) return false throw new Error('Number of signatures required must be greater than zero')
}
if (n > 16) {
throw new Error('Number of public keys must be less than 17')
}
if (m > n) {
throw new Error('Number of signatures cannot exceed the number of public keys')
}
if (n !== chunks.length - 3) {
throw new Error('n does not match the number of public keys')
}
var m = mOp - OP_INT_BASE var keys = chunks.slice(1, -2)
var n = nOp - OP_INT_BASE if (!keys.every(isCanonicalPubKey)) {
throw new Error('Non-canonical pubic key found')
}
// 0 < m <= n <= 16 return {
if (m <= 0) return false nRequiredSigs: m,
if (m > n) return false nPublicKeys: n,
if (n > 16) return false publicKeyBuffers: keys
if (n !== chunks.length - 3) return false }
}
return chunks.slice(1, -2).every(isCanonicalPubKey) function isMultisigOutput (script) {
try {
parseMultisigScript(script)
return true
} catch (e) {
return false
}
} }
function isNullDataOutput (script) { function isNullDataOutput (script) {
@ -399,16 +426,9 @@ function witnessScriptHashInput (scriptSig, scriptPubKey) {
// OP_0 [signatures ...] // OP_0 [signatures ...]
function multisigInput (signatures, scriptPubKey) { function multisigInput (signatures, scriptPubKey) {
if (scriptPubKey) { if (scriptPubKey) {
var chunks = decompile(scriptPubKey) var scriptData = parseMultisigScript(scriptPubKey)
if (!isMultisigOutput(chunks)) throw new Error('Expected multisig scriptPubKey') if (signatures.length < scriptData.nRequiredSigs) throw new Error('Not enough signatures provided')
if (signatures.length > scriptData.nPublicKeys) throw new Error('Too many signatures provided')
var mOp = chunks[0]
var nOp = chunks[chunks.length - 2]
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')
} }
return compile([].concat(OPS.OP_0, signatures)) return compile([].concat(OPS.OP_0, signatures))
@ -441,6 +461,7 @@ module.exports = {
isMultisigOutput: isMultisigOutput, isMultisigOutput: isMultisigOutput,
isNullDataOutput: isNullDataOutput, isNullDataOutput: isNullDataOutput,
parseMultisigScript: parseMultisigScript,
classifyOutput: classifyOutput, classifyOutput: classifyOutput,
classifyInput: classifyInput, classifyInput: classifyInput,
pubKeyOutput: pubKeyOutput, pubKeyOutput: pubKeyOutput,

Loading…
Cancel
Save