Example #1
0
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
Example #3
0
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
Example #5
0
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