Bitcoinjs-lib: How to check the number of signatures required in a transaction鈥檚 output?

Created on 24 Aug 2017  路  9Comments  路  Source: bitcoinjs/bitcoinjs-lib

Hello team,

I am using bitcoinjs-lib to decode a raw transaction.
I don't know whether bitcoinjs-lib can check the number of signatures required in a transaction鈥檚 output.
Could you please support?

By the way, is there any document to guide how to use Bitcoinjs-lib? I only see the examples in Readme file that show how to use this library.

Thank you.

how to / question / docs

Most helpful comment

var bitcoinjs = require('./src/index.js')
var bscript = bitcoinjs.script
var bcrypto = bitcoinjs.crypto
var st = bscript.types

var SUPPORTED = [st.P2PK, st.P2PKH, st.MULTISIG];

function contains (array, value) {
  return array.indexOf(value) !== -1;
}

function standardScriptReqSigs (scriptType, script) {
  switch (scriptType) {
    case st.MULTISIG:
      return bscript.multisig.output.decode(script).m
    case st.P2PK:
      return 1
    case st.P2PKH:
      return 1
    default:
      throw new Error('unsupported script')
  }
}

function getReqSigs (script, rs, ws) {
  var scriptType = bscript.classifyOutput(script)
  var s = script

  if (scriptType === st.P2SH) {
    if (rs === undefined) {
      throw new Error('rs required')
    }
    scriptType = bscript.classifyOutput(rs)
    s = rs
  }

  if (scriptType === st.P2WSH) {
    if (ws === undefined) {
      throw new Error('ws required')
    }
    scriptType = bscript.classifyOutput(ws)
    s = ws
  }

  if (!contains(SUPPORTED, scriptType)) {
    return null
  }

  return standardScriptReqSigs(scriptType, s)
}

var pks = [Buffer.from('020102030401020304010203040102030401020304010203040102030401020304', 'hex'),
  Buffer.from('020102030401020304010203040102030401020304010203040102030401020304', 'hex'),
  Buffer.from('020102030401020304010203040102030401020304010203040102030401020304', 'hex'),
  Buffer.from('020102030401020304010203040102030401020304010203040102030401020304', 'hex'),
  Buffer.from('020102030401020304010203040102030401020304010203040102030401020304', 'hex')
];

var multisig4 = bscript.multisig.output.encode(4, pks)
var scriptHash = bcrypto.hash160(multisig4)
var p2shMultisig = bscript.scriptHash.output.encode(scriptHash)

console.log(getReqSigs(multisig4))
console.log(getReqSigs(p2shMultisig, multisig4))

var multisig2 = bscript.multisig.output.encode(2, pks.slice(0, 3))
var witnessScriptHash = bcrypto.sha256(multisig2)
var p2wshMultisig = bscript.witnessScriptHash.output.encode(witnessScriptHash)

var p2wshScriptHash = bcrypto.hash160(multisig2)
var p2shP2wshMultisig = bscript.scriptHash.output.encode(p2wshScriptHash)

console.log(getReqSigs(p2wshMultisig, null, multisig2))
console.log(getReqSigs(p2shP2wshMultisig, p2wshMultisig, multisig2))

var p2pk = bscript.pubKey.output.encode(pks[0])

console.log(getReqSigs(p2pk))

var p2pkh = bscript.pubKeyHash.output.encode(bcrypto.hash160(pks[0]))

console.log(getReqSigs(p2pkh))

This snippet should do the trick, but as dabura says, it requires the redeem/witness scripts to fully function.

All 9 comments

@HungNguyen007 there is only examples at this time.

I don't know whether bitcoinjs-lib can check the number of signatures required in a transaction鈥檚 output.

I don't think I understand the question. Do you mean how many signatures are required to _sign_ a transaction __input__?

There is no way to tell what a P2SH multisig is until you see it as an input.

@dcousens : Thank for your prompt response.

I am using Bitcoinjs to decode a raw transaction to human language for a example from https://bitcoin.org/en/developer-reference#decoderawtransaction
Do you know how to get info of reqSigs element as example below from a raw transaction by using Bitcoinjs?

{
    "txid": "52309405287e737cf412fc42883d65a392ab950869fae80b2a5f1e33326aca46",
    "hash": "52309405287e737cf412fc42883d65a392ab950869fae80b2a5f1e33326aca46",
    "size": 223,
    "vsize": 223,
    "version": 1,
    "locktime": 0,
    "vin": [
        {
            "txid": "2ac0daff49a4ff82a35a4864797f99f23c396b0529c5ba1e04b3d7b97521feba",
            "vout": 0,
            "scriptSig": {
                "asm": "abc ...xyz",
                "hex": "egf...xzt"
            },
            "sequence": 4294967295
        }
    ],
    "vout": [
        {
            "value": 0.06990000,
            "n": 0,
            "scriptPubKey": {
            "asm": "OP_DUP OP_HASH160 01b81d5fa1e55e069e3cc2db9c19e2e80358f306 OP_EQUALVERIFY OP_CHECKSIG",
                "hex": "76a91401b81d5fa1e55e069e3cc2db9c19e2e80358f30688ac",
                "reqSigs": 1,
                "type": "pubkeyhash",
                "addresses": [
                    "1A6Ei5cRfDJ8jjhwxfzLJph8B9ZEthR9Z"
                ]
            }
        }
    ]
}

That isn't the most reliable of numbers.. It returns 1 for scripthash outputs, even though it doesn't have their redeemScripts yet.

var bitcoinjs = require('./src/index.js')
var bscript = bitcoinjs.script
var bcrypto = bitcoinjs.crypto
var st = bscript.types

var SUPPORTED = [st.P2PK, st.P2PKH, st.MULTISIG];

function contains (array, value) {
  return array.indexOf(value) !== -1;
}

function standardScriptReqSigs (scriptType, script) {
  switch (scriptType) {
    case st.MULTISIG:
      return bscript.multisig.output.decode(script).m
    case st.P2PK:
      return 1
    case st.P2PKH:
      return 1
    default:
      throw new Error('unsupported script')
  }
}

function getReqSigs (script, rs, ws) {
  var scriptType = bscript.classifyOutput(script)
  var s = script

  if (scriptType === st.P2SH) {
    if (rs === undefined) {
      throw new Error('rs required')
    }
    scriptType = bscript.classifyOutput(rs)
    s = rs
  }

  if (scriptType === st.P2WSH) {
    if (ws === undefined) {
      throw new Error('ws required')
    }
    scriptType = bscript.classifyOutput(ws)
    s = ws
  }

  if (!contains(SUPPORTED, scriptType)) {
    return null
  }

  return standardScriptReqSigs(scriptType, s)
}

var pks = [Buffer.from('020102030401020304010203040102030401020304010203040102030401020304', 'hex'),
  Buffer.from('020102030401020304010203040102030401020304010203040102030401020304', 'hex'),
  Buffer.from('020102030401020304010203040102030401020304010203040102030401020304', 'hex'),
  Buffer.from('020102030401020304010203040102030401020304010203040102030401020304', 'hex'),
  Buffer.from('020102030401020304010203040102030401020304010203040102030401020304', 'hex')
];

var multisig4 = bscript.multisig.output.encode(4, pks)
var scriptHash = bcrypto.hash160(multisig4)
var p2shMultisig = bscript.scriptHash.output.encode(scriptHash)

console.log(getReqSigs(multisig4))
console.log(getReqSigs(p2shMultisig, multisig4))

var multisig2 = bscript.multisig.output.encode(2, pks.slice(0, 3))
var witnessScriptHash = bcrypto.sha256(multisig2)
var p2wshMultisig = bscript.witnessScriptHash.output.encode(witnessScriptHash)

var p2wshScriptHash = bcrypto.hash160(multisig2)
var p2shP2wshMultisig = bscript.scriptHash.output.encode(p2wshScriptHash)

console.log(getReqSigs(p2wshMultisig, null, multisig2))
console.log(getReqSigs(p2shP2wshMultisig, p2wshMultisig, multisig2))

var p2pk = bscript.pubKey.output.encode(pks[0])

console.log(getReqSigs(p2pk))

var p2pkh = bscript.pubKeyHash.output.encode(bcrypto.hash160(pks[0]))

console.log(getReqSigs(p2pkh))

This snippet should do the trick, but as dabura says, it requires the redeem/witness scripts to fully function.

@afk11 : Thank for your snippet.

From the definition of Pay To Public Key Hash (P2PKH) in Bitcoin.org, it require one signature
(who has a corresponding private key) satisfying the conditions of P2PKH of an Output in a transaction. And the required number of signature (reqSigs) in this case should be 1. It is not relevant to redeem/witness scripts in this case.

How do you think?

@afk11 maybe solveOutput in https://github.com/bitcoinjs/bitcoinjs-lib/pull/708 could have a redeemScript parameter to do the above?

I think there's miscommunication going on here.

OP is saying "How can I calculate the required signatures from the output scriptPubkey alone?"

Everyone else is assuming he meant "input" because they know you can't calculate the sig count from the output, except for the ONE AND ONLY case which is P2PKH.

Dear OP.

You need to have a redeemScript or WitnessScript in order to calculate the required sigs for anything other than P2PKH.

@dabura667 : I agree with you and @afk11 for

You need to have a redeemScript or WitnessScript in order to calculate the required sigs for anything other than P2PKH.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

thrastarson picture thrastarson  路  3Comments

dcousens picture dcousens  路  3Comments

coingeek picture coingeek  路  4Comments

tuyennvtb picture tuyennvtb  路  3Comments

namnv04 picture namnv04  路  3Comments