def witness_from_address(b32addr: String) -> Tuple[int, bytes, str]: "Return the witness from a bech32 native SegWit address." if isinstance(b32addr, str): b32addr = b32addr.strip() # the following check was originally in b32decode # but it does not pertain there if len(b32addr) > 90: raise BTClibValueError( f"invalid bech32 address length: {len(b32addr)} > 90") hrp, data = b32decode(b32addr) # check that it is a known SegWit address type network = network_from_key_value("hrp", hrp) if network is None: raise BTClibValueError(f"invalid hrp: {hrp}") if len(data) == 0: raise BTClibValueError(f"empty data in bech32 address: {b32addr!r}") wit_ver = data[0] wit_prg = bytes(power_of_2_base_conversion(data[1:], 5, 8, False)) return wit_ver, check_witness(wit_ver, wit_prg), network
def address_from_xpub(xpub: BIP32Key) -> str: """Return the SLIP132 base58/bech32 address. The address is always derived from the compressed public key, as this is the default public key representation in BIP32. """ if not isinstance(xpub, BIP32KeyData): xpub = BIP32KeyData.b58decode(xpub) if xpub.key[0] not in (2, 3): err_msg = f"not a public key: {xpub.b58encode()}" raise BTClibValueError(err_msg) function_list: List[Callable[[Any, str], str]] = [ b58.p2pkh, b32.p2wpkh, b58.p2wpkh_p2sh, ] version_list: List[str] = [ "bip32_pub", "slip132_p2wpkh_pub", "slip132_p2wpkh_p2sh_pub", ] for version, function in zip(version_list, function_list): # with pytohn>=3.8 use walrus operator # if network := network_from_key_value(version, xpub.version): network = network_from_key_value(version, xpub.version) if network: return function(xpub, network) err_msg = f"unknown xpub version: {xpub.version.hex()}" # pragma: no cover raise BTClibValueError(err_msg) # pragma: no cover
def h160_from_address(b58addr: String) -> Tuple[str, bytes, str]: "Return the payload from a base58 address." if isinstance(b58addr, str): b58addr = b58addr.strip() payload = b58decode(b58addr, 21) prefix = payload[:1] for script_type in ("p2pkh", "p2sh"): # with pytohn>=3.8 use walrus operator # if network := network_from_key_value(script_type, prefix): network = network_from_key_value(script_type, prefix) if network: return script_type, payload[1:], network err_msg = f"invalid base58 address prefix: 0x{prefix.hex()}" raise BTClibValueError(err_msg)
def _prv_keyinfo_from_wif(wif: String, network: Optional[str] = None, compressed: Optional[bool] = None) -> PrvkeyInfo: """Return private key tuple(int, compressed, network) from a WIF. WIF is always compressed and includes network information: here the 'network, compressed' input parameters are passed only to allow consistency checks. """ if isinstance(wif, str): wif = wif.strip() payload = b58decode(wif) net = network_from_key_value("wif", payload[:1]) if net is None: raise BTClibValueError(f"invalid wif prefix: {payload[:1]!r}") if network is not None and net != network: raise BTClibValueError(f"not a {network} wif: {wif!r}") ec = NETWORKS[net].curve if len(payload) == ec.n_size + 2: # compressed WIF compr = True if payload[-1] != 0x01: # must have a trailing 0x01 raise BTClibValueError( "not a compressed WIF: missing trailing 0x01") prv_key = payload[1:-1] elif len(payload) == ec.n_size + 1: # uncompressed WIF compr = False prv_key = payload[1:] else: raise BTClibValueError(f"wrong WIF size: {len(payload)}") if compressed is not None and compr != compressed: raise BTClibValueError("compression requirement mismatch") q = int.from_bytes(prv_key, byteorder="big") if not 0 < q < ec.n: raise BTClibValueError(f"private key {hex(q)} not in [1, n-1]") return q, net, compr
def witness_from_address(b32addr: String) -> Tuple[int, bytes, str]: """Return the witness from a bech32 native SegWit address. The returned data structure is: version, program, network. """ if isinstance(b32addr, str): b32addr = b32addr.strip() # the following check was originally in b32decode # but it does not pertain there if len(b32addr) > 90: raise BTClibValueError( f"invalid bech32 address length: {len(b32addr)} > 90") hrp, data, checksum = __b32decode(b32addr) if len(data) == 0: raise BTClibValueError(f"empty data in bech32 address: {b32addr!r}") wit_ver = data[0] wit_prog = bytes(power_of_2_base_conversion(data[1:], 5, 8, False)) wit_prog = check_witness(wit_ver, wit_prog) if wit_ver == 0: if not b32_verify_checksum(hrp, data + checksum): raise BTClibValueError(f"invalid checksum: {b32addr!r}") else: if not bech32m_verify_checksum(hrp, data + checksum): raise BTClibValueError(f"invalid checksum: {b32addr!r}") # check that it is a known SegWit address type network = network_from_key_value("hrp", hrp) if network is None: raise BTClibValueError(f"invalid hrp: {hrp}") return wit_ver, wit_prog, network