def get_public_key_hex_from_tx(inputs, address): """ Given a list of inputs and outputs and the address of one of the inputs, find the public key. """ ret = None for inp in inputs: input_scriptsig = inp.get('scriptSig', None) if input_scriptsig is None: continue input_asm = input_scriptsig.get("asm") if len(input_asm.split(" ")) >= 2: # public key is the second hex string. verify it matches the address pubkey_hex = input_asm.split(" ")[1] pubkey = None try: pubkey = pybitcoin.BitcoinPublicKey(str(pubkey_hex)) except Exception, e: traceback.print_exc() log.warning("Invalid public key '%s'" % pubkey_hex) continue if address != pubkey.address(): continue ret = pubkey_hex break
def btc_decoderawtransaction_get_pubkey_from_script( script ): """ Given a pay-to-public-key script, get the public key. Returns a hex string on success. Returns None on error. """ # format: [1-byte length] [pubkey] OP_CHECKSIG pubkey_len = int( script[0:1], 16 ) if len(script[:-2]) == pubkey_len * 2 and script[-2:].lower() == 'ac': # the rest of the script is a public key bin_pubkey = binascii.unhexlify( script[2:2*pubkey_len] ) try: pk = pybitcoin.BitcoinPublicKey( bin_pubkey ) return pk.to_hex() except: return None else: return None
def parse_nameop(opcode, payload, fake_pubkey, recipient=None, recipient_address=None, import_update_hash=None): opcode_name = OPCODE_NAMES[opcode] pubk = pybitcoin.BitcoinPublicKey(fake_pubkey) address = pubk.address() script_pubkey = pybitcoin.make_pay_to_address_script(address) senders = [{ "script_pubkey": script_pubkey, "script_type": "pubkeyhash", "addresses": [address] }] # just enough to get the public key inputs = [{ "scriptSig": { "asm": "ignored %s" % fake_pubkey, } }] script = "OP_RETURN %s" % payload try: scripthex = pybitcoin.make_op_return_script(payload) except: if len(payload) == 0: scripthex = "6a" else: raise outputs = [{ "scriptPubKey": { "asm": script, "hex": scripthex, "addresses": [] } }] if recipient_address is not None: script = "OP_DUP OP_HASH160 %s OP_EQUALVERIFY OP_CHECKSIG" % binascii.hexlify( pybitcoin.bin_double_sha256(fake_pubkey)) scripthex = pybitcoin.make_pay_to_address_script(recipient_address) outputs.append({ "scriptPubKey": { "asm": script, "hex": scripthex, "addresses": [recipient_address] } }) if import_update_hash is not None: script = "OP_DUP OP_HASH160 %s OP_EQUALVERIFY OP_CHECKSIG" % import_update_hash scripthex = pybitcoin.make_pay_to_address_script( pybitcoin.hex_hash160_to_address(import_update_hash)) outputs.append({ "scriptPubKey": { "asm": script, "hex": scripthex, "addresses": [pybitcoin.hex_hash160_to_address(import_update_hash)] } }) try: op = op_extract(opcode_name, payload, senders, inputs, outputs, 373601, 0, "00" * 64) except AssertionError, ae: # failed to parse return None
def btc_decoderawtransaction_compat( tx_hex ): """ Implementation of bitcoind's decoderawtransaction JSONRPC method. Tries to be faithful enough to bitcoind for virtualchain's sake. Does NOT handle coinbase transactions """ inputs, outputs, locktime, version = tx_deserialize( tx_hex ) txid = make_txid( tx_hex ) vin = [] vout = [] for inp in inputs: vin_inp = { "txid": inp['transaction_hash'], "vout": inp['output_index'], } if inp.has_key("script_sig"): scriptsig_hex = inp['script_sig'] scriptsig_asm = btc_decoderawtransaction_script_hex_to_asm( scriptsig_hex ) vin_inp['scriptSig'] = { 'asm': scriptsig_asm, 'hex': scriptsig_hex } if inp.has_key("sequence"): vin_inp['sequence'] = inp['sequence'] vin.append( vin_inp ) for i in xrange( 0, len(outputs) ): out = outputs[i] script_type = btc_decoderawtransaction_get_script_type( out['script_hex'] ) addresses = [] if script_type == "pubkeyhash": addresses.append( pybitcoin.script_hex_to_address( out['script_hex'] ) ) elif script_type == "pubkey": pubkey = btc_decoderawtransaction_get_pubkey_from_script( out['script_hex'] ) addr = pybitcoin.BitcoinPublicKey( pubkey ).address() addresses.append( addr ) elif script_type == "scripthash": script_hash = btc_decoderawtransaction_get_script_hash_from_script( out['script_hex'] ) addr = pybitcoin.b58check_encode( binascii.unhexlify( script_hash ), version_byte=5 ) addresses.append( addr ) vout_out = { "value": float(out['value']) / 10e7, "mock_bitcoind_value_satoshi": out['value'], # NOTE: extra "n": i, "scriptPubKey": { 'asm': btc_decoderawtransaction_script_hex_to_asm( out['script_hex'] ), 'hex': out['script_hex'], "type": script_type }, } if script_type in ["pubkeyhash", "pubkey", "scripthash"]: vout_out['scriptPubKey']['reqSigs'] = 1 if len(addresses) > 0: vout_out['scriptPubKey']['addresses'] = addresses vout.append( vout_out ) tx_decoded = { "txid": txid, "version": version, "locktime": locktime, "vin": vin, "vout": vout } return tx_decoded