Transactions
是否有任何 python 庫可用於在輸出中解碼腳本
例如像這樣解碼 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>
我剛剛將它添加到我的玩具庫中。
>>> from btctools import decode_scriptpubkey >>> 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"