def get_address_from_output_script(script_bytes): output_type = 0 decoded = [x for x in script_GetOp(script_bytes)] r = decode_claim_script(decoded) claim_args = None if r is not False: claim_info, decoded = r if isinstance(claim_info, NameClaim): claim_args = (claim_info.name, claim_info.value) output_type |= TYPE_CLAIM elif isinstance(claim_info, ClaimSupport): claim_args = (claim_info.name, claim_info.claim_id) output_type |= TYPE_SUPPORT elif isinstance(claim_info, ClaimUpdate): claim_args = (claim_info.name, claim_info.claim_id, claim_info.value) output_type |= TYPE_UPDATE # The Genesis Block, self-payments, and pay-by-IP-address payments look like: # 65 BYTES:... CHECKSIG match_pubkey = [opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG] # Pay-by-Bitcoin-address TxOuts look like: # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG match_p2pkh = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ] # p2sh match_p2sh = [opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUAL] if match_decoded(decoded, match_pubkey): output_val = decoded[0][1].encode('hex') output_type |= TYPE_PUBKEY elif match_decoded(decoded, match_p2pkh): output_val = hash_160_to_bc_address(decoded[2][1]) output_type |= TYPE_ADDRESS elif match_decoded(decoded, match_p2sh): output_val = hash_160_to_bc_address(decoded[1][1], 5) output_type |= TYPE_ADDRESS else: output_val = bytes output_type |= TYPE_SCRIPT if output_type & (TYPE_CLAIM | TYPE_SUPPORT | TYPE_UPDATE): output_val = (claim_args, output_val) return output_type, output_val
def test_address_encode_decode(self): valid_addr_hex = "be482f953ed0feda4fc5c4d012681b6119274993" self.assertEqual( hash_160_to_bc_address(valid_addr_hex.decode('hex'), 0), "bW5PZEvEBNPQRVhwpYXSjabFgbSw1oaHyR") self.assertEqual( bc_address_to_hash_160("bW5PZEvEBNPQRVhwpYXSjabFgbSw1oaHyR"), (0, "\xbeH/\x95>\xd0\xfe\xdaO\xc5\xc4\xd0\x12h\x1ba\x19'I\x93"))
def parse_xpub(x_pubkey): if x_pubkey[0:2] in ['02', '03', '04']: pubkey = x_pubkey elif x_pubkey[0:2] == 'ff': from lbryum.bip32 import BIP32_Account xpub, s = BIP32_Account.parse_xpubkey(x_pubkey) pubkey = BIP32_Account.derive_pubkey_from_xpub(xpub, s[0], s[1]) elif x_pubkey[0:2] == 'fd': addrtype = ord(x_pubkey[2:4].decode('hex')) hash160 = x_pubkey[4:].decode('hex') pubkey = None address = hash_160_to_bc_address(hash160, addrtype) else: raise BaseException("Cannnot parse pubkey") if pubkey: address = public_key_to_bc_address(pubkey.decode('hex')) return pubkey, address
def parse_scriptSig(d, bytes): try: decoded = [x for x in script_GetOp(bytes)] except Exception: # coinbase transactions raise an exception print_error("cannot find address in input script", bytes.encode('hex')) return # payto_pubkey match = [opcodes.OP_PUSHDATA4] if match_decoded(decoded, match): sig = decoded[0][1].encode('hex') d['address'] = "(pubkey)" d['signatures'] = [sig] d['num_sig'] = 1 d['x_pubkeys'] = ["(pubkey)"] d['pubkeys'] = ["(pubkey)"] return # non-generated TxIn transactions push a signature # (seventy-something bytes) and then their public key # (65 bytes) onto the stack: match = [opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4] if match_decoded(decoded, match): sig = decoded[0][1].encode('hex') x_pubkey = decoded[1][1].encode('hex') try: signatures = parse_sig([sig]) pubkey, address = parse_xpub(x_pubkey) except: import traceback traceback.print_exc(file=sys.stdout) print_error("cannot find address in input script", bytes.encode('hex')) return d['signatures'] = signatures d['x_pubkeys'] = [x_pubkey] d['num_sig'] = 1 d['pubkeys'] = [pubkey] d['address'] = address return # p2sh transaction, m of n match = [opcodes.OP_0] + [opcodes.OP_PUSHDATA4] * (len(decoded) - 1) if not match_decoded(decoded, match): print_error("cannot find address in input script", bytes.encode('hex')) return x_sig = [x[1].encode('hex') for x in decoded[1:-1]] dec2 = [x for x in script_GetOp(decoded[-1][1])] m = dec2[0][0] - opcodes.OP_1 + 1 n = dec2[-2][0] - opcodes.OP_1 + 1 op_m = opcodes.OP_1 + m - 1 op_n = opcodes.OP_1 + n - 1 match_multisig = [op_m] + [opcodes.OP_PUSHDATA4] * n + [ op_n, opcodes.OP_CHECKMULTISIG ] if not match_decoded(dec2, match_multisig): print_error("cannot find address in input script", bytes.encode('hex')) return x_pubkeys = map(lambda x: x[1].encode('hex'), dec2[1:-2]) pubkeys = [parse_xpub(x)[0] for x in x_pubkeys] # xpub, addr = parse_xpub() redeemScript = Transaction.multisig_script(pubkeys, m) # write result in d d['num_sig'] = m d['signatures'] = parse_sig(x_sig) d['x_pubkeys'] = x_pubkeys d['pubkeys'] = pubkeys d['redeemScript'] = redeemScript d['address'] = hash_160_to_bc_address(hash_160(redeemScript.decode('hex')), 5)
def pubkeys_to_address(self, pubkeys): redeem_script = Transaction.multisig_script(sorted(pubkeys), self.m) address = hash_160_to_bc_address(hash_160(redeem_script.decode('hex')), 5) return address
def test_address_encode_prefix_error(self): valid_addr_hex = "be482f953ed0feda4fc5c4d012681b6119274993" with self.assertRaises(Exception): hash_160_to_bc_address(valid_addr_hex.decode('hex'), -1) hash_160_to_bc_address(valid_addr_hex.decode('hex'), 2) hash_160_to_bc_address(valid_addr_hex.decode('hex'), 2000)