Transactions

是否有任何 python 庫可用於在輸出中解碼腳本

  • August 16, 2021

例如像這樣解碼 ScriptPubKey

4104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac

像這樣的一些數據

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

一般來說,類似於 decodescript rpc 中的函式。

<http://chainquery.com/bitcoin-api/decodescript>

我剛剛將它添加到我的玩具庫中。

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

已解決並將程式碼保存在此處。 <https://github.com/keviny/bitcoin-block-parser>

在https://en.bitcoin.it/wiki/Script中可以找到許多詳細資訊。

在交易輸出中解碼 ScriptPubKey 的程式碼:

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"

引用自:https://bitcoin.stackexchange.com/questions/78633