Script: add function for parsing multisig type scripts
This commit is contained in:
parent
405c005802
commit
53f08a7569
1 changed files with 52 additions and 31 deletions
|
@ -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 parseMultisigScript (scriptPubKey) {
|
||||||
|
var chunks = decompile(scriptPubKey)
|
||||||
|
if (chunks.length < 4) {
|
||||||
|
throw new Error('Multisig script should contain at least 4 elements')
|
||||||
|
}
|
||||||
|
if (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG) {
|
||||||
|
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 (m <= 0) {
|
||||||
|
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 keys = chunks.slice(1, -2)
|
||||||
|
if (!keys.every(isCanonicalPubKey)) {
|
||||||
|
throw new Error('Non-canonical pubic key found')
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
nRequiredSigs: m,
|
||||||
|
nPublicKeys: n,
|
||||||
|
publicKeyBuffers: keys
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function isMultisigOutput (script) {
|
function isMultisigOutput (script) {
|
||||||
var chunks = decompile(script)
|
try {
|
||||||
if (chunks.length < 4) return false
|
parseMultisigScript(script)
|
||||||
if (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG) return false
|
return true
|
||||||
|
} catch (e) {
|
||||||
var mOp = chunks[0]
|
return false
|
||||||
var nOp = chunks[chunks.length - 2]
|
}
|
||||||
|
|
||||||
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
|
|
||||||
if (n !== chunks.length - 3) return false
|
|
||||||
|
|
||||||
return chunks.slice(1, -2).every(isCanonicalPubKey)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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…
Add table
Reference in a new issue