1

For example decode the ScriptPubKey like

4104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac

to some data like this

{
"result": {
    "asm": "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f OP_CHECKSIG",
    "reqSigs": 1,
    "type": "pubkey",
    "addresses": [
        "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
    ],
    "p2sh": "3DjjKyU38gSfuVxajV43MUy4vHkg1JVL7T"
},
"error": null,
"id": null
}

In general, something like the function in decodescript rpc.
http://chainquery.com/bitcoin-api/decodescript

2 Answers 2

1

I just added that to my toy library.

>>> from btctools import decode_scriptpubkey
>>> decode_scriptpubkey('76a914b3c2dc3a7f68a024a5d2ee9d4012dca1134dea8588ac')
{'address': '1HPVPU3xHMPcxmgdP9puPbnDcHDV5JhURh',
 'asm': 'OP_DUP OP_HASH160 b3c2dc3a7f68a024a5d2ee9d4012dca1134dea85 OP_EQUALVERIFY OP_CHECKSIG',
 'hex': '76a914b3c2dc3a7f68a024a5d2ee9d4012dca1134dea8588ac',
 'type': 'P2PKH'}
0

Resolved and save the code in here. https://github.com/keviny/bitcoin-block-parser

Many details are found in https://en.bitcoin.it/wiki/Script.

The code to decode the ScriptPubKey in transaction output:

class TxOutput:
  def __init__(self, blockchain, idx):
    self.idx = idx
    self.value = uint8(blockchain)
    self.script_len = varint(blockchain)
    self.pubkey = blockchain.read(self.script_len)
    self.addr = "UNKNOWN"
    self.decode_scriptpubkey(self.pubkey)

  def to_string(self):
    sb = []
    sb.append("Value: %d" % self.value + " Satoshi")
    sb.append("Script Len: %d" % self.script_len)
    sb.append("ScriptPubkey: %s" % self.addr)
    sb.append("Addr: %s" % self.addr)
    return sb

  def decode_scriptpubkey(self, data):
    ''' https://en.bitcoin.it/wiki/Script '''
    hexstr = hashStr(data)
    # Get the first two bytes.
    # which might some problem.
    # https://www.blockchain.com/btc/tx/7bd54def72825008b4ca0f4aeff13e6be2c5fe0f23430629a9d484a1ac2a29b8
    try:
      op_idx = int(hexstr[0:2], 16)
    except:
      self.type = "EXCEPTION"
      self.addr = "UNKNOWN"
      return
    try:
      op_code = OPCODE_NAMES[op_idx]
    except KeyError:
      if op_idx==65:
        self.type = "P2PK"
        # Obsoleted pay to pubkey directly
        # For detail see: https://en.bitcoin.it/wiki/Script#Obsolete_pay-to-pubkey_transaction
        pub_key_len = op_idx
        op_code_tail = OPCODE_NAMES[int(hexstr[2 + pub_key_len * 2:2 + pub_key_len * 2 + 2], 16)]
        self.pubkey_human = "Pubkey OP_CODE: None Bytes:%s tail_op_code:%s %d" % (pub_key_len, op_code_tail, op_idx)
        self.addr = pubkey_to_address(hexstr[2:2 + pub_key_len * 2])[0]
      else:
        # Some times people will push data directly
        # e.g: https://www.blockchain.com/btc/tx/d65bb24f6289dad27f0f7e75e80e187d9b189a82dcf5a86fb1c6f8ff2b2c190f
        self.type = "UN"
        pub_key_len = op_idx
        self.pubkey_human = "PUSH_DATA:%s" % hexstr[2:2 + pub_key_len * 2]
        self.addr = "UNKNOWN"
      return
    try:
      if op_code == "OP_DUP":
        self.type = "P2PKHA"
        # P2PKHA pay to pubkey hash mode
        # For detail see: https://en.bitcoin.it/wiki/Script#Standard_Transaction_to_Bitcoin_address_.28pay-to-pubkey-hash.29
        op_code2 = OPCODE_NAMES[int(hexstr[2:4], 16)]
        pub_key_len = int(hexstr[4:6], 16)
        op_code_tail2 = OPCODE_NAMES[int(hexstr[6 + pub_key_len * 2:6 + pub_key_len * 2 + 2], 16)]
        op_code_tail_last = OPCODE_NAMES[int(hexstr[6 + pub_key_len * 2 + 2:6 + pub_key_len * 2 + 4], 16)]
        self.pubkey_human = "%s %s %s %s %s" % (op_code, op_code2,  hexstr[6:6 + pub_key_len * 2], op_code_tail2, op_code_tail_last)
        self.addr = gen_addr(hexstr[6:6 + pub_key_len * 2])[0]
      elif op_code == "OP_HASH160":
        self.type = "P2SH"
        # P2SHA pay to script hash
        # https://en.bitcoin.it/wiki/Transaction#Pay-to-Script-Hash
        pub_key_len = int(hexstr[2:4], 16)
        op_code_tail = OPCODE_NAMES[int(hexstr[4 + pub_key_len * 2:4 + pub_key_len * 2 + 2], 16)]
        hash_code = hexstr[4:4 + pub_key_len * 2]
        self.pubkey_human = "%s %s %s" % (op_code, hash_code, op_code_tail)
        self.addr = hash_code
      elif op_code == "OP_RETURN":
        self.type = "OP_RETURN"
        pub_key_len = int(hexstr[2:4], 16)
        hash_code = hexstr[4:4 + pub_key_len * 2]
        self.pubkey_human = "OP_RETURN %s" % (hash_code)
        self.addr = hash_code
      else:  # TODO extend for multi-signature parsing
        self.type = "UN"
        self.pubkey_human = "Need to extend multi-signaturer parsing %x" % int(hexstr[0:2], 16) + op_code
        self.addr = "UNKNOWN"
    except:
      self.type = "ERROR"
      self.addr = "UNKNOWN"
1
  • Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference.
    – Andrew Chow
    Oct 25, 2018 at 14:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.