Module jmwallet.wallet.address

Bitcoin address generation utilities.

This module re-exports address utilities from jmcore.bitcoin for backward compatibility.

Functions

def bech32_encode(hrp: str, data: list[int]) ‑> str
Expand source code
def bech32_encode(hrp: str, data: list[int]) -> str:
    """
    Legacy wrapper for bech32 encoding.

    This function is kept for backward compatibility with
    maker/tx_verification.py which imports it.
    """
    # First element is witness version, rest is the witness program in 5-bit groups
    if data:
        witver = data[0]
        # Convert 5-bit groups back to 8-bit for bech32 lib
        # The bech32 lib's encode takes 8-bit data and converts internally
        # So we need to convert from 5-bit to 8-bit
        witprog_5bit = data[1:]
        # Convert 5-bit groups to bytes
        acc = 0
        bits = 0
        witprog = []
        for value in witprog_5bit:
            acc = (acc << 5) | value
            bits += 5
            while bits >= 8:
                bits -= 8
                witprog.append((acc >> bits) & 0xFF)
        result = bech32_lib.encode(hrp, witver, bytes(witprog))
        if result is None:
            raise ValueError("Failed to encode bech32")
        return result
    raise ValueError("Empty data")

Legacy wrapper for bech32 encoding.

This function is kept for backward compatibility with maker/tx_verification.py which imports it.

def convertbits(data: bytes, frombits: int, tobits: int, pad: bool = True) ‑> list[int]
Expand source code
def convertbits(data: bytes, frombits: int, tobits: int, pad: bool = True) -> list[int]:
    """
    Convert between bit groups.

    Legacy wrapper kept for backward compatibility.
    """
    acc = 0
    bits = 0
    ret = []
    maxv = (1 << tobits) - 1
    max_acc = (1 << (frombits + tobits - 1)) - 1

    for value in data:
        acc = ((acc << frombits) | value) & max_acc
        bits += frombits
        while bits >= tobits:
            bits -= tobits
            ret.append((acc >> bits) & maxv)

    if pad:
        if bits:
            ret.append((acc << (tobits - bits)) & maxv)
    elif bits >= frombits or ((acc << (tobits - bits)) & maxv):
        raise ValueError("Invalid bits")

    return ret

Convert between bit groups.

Legacy wrapper kept for backward compatibility.

def hash160(data: bytes) ‑> bytes
Expand source code
def hash160(data: bytes) -> bytes:
    """
    RIPEMD160(SHA256(data)) - Used for Bitcoin addresses.

    Args:
        data: Input data to hash

    Returns:
        20-byte hash
    """
    return hashlib.new("ripemd160", hashlib.sha256(data).digest()).digest()

RIPEMD160(SHA256(data)) - Used for Bitcoin addresses.

Args

data
Input data to hash

Returns

20-byte hash

def pubkey_to_p2wpkh_address(pubkey: bytes | str, network: str | NetworkType = 'mainnet') ‑> str
Expand source code
@validate_call
def pubkey_to_p2wpkh_address(pubkey: bytes | str, network: str | NetworkType = "mainnet") -> str:
    """
    Convert compressed public key to P2WPKH (native SegWit) address.

    Args:
        pubkey: 33-byte compressed public key (bytes or hex string)
        network: Network type

    Returns:
        Bech32 P2WPKH address
    """
    if isinstance(pubkey, str):
        pubkey = bytes.fromhex(pubkey)

    if len(pubkey) != 33:
        raise ValueError(f"Invalid compressed pubkey length: {len(pubkey)}")

    pubkey_hash = hash160(pubkey)
    hrp = get_hrp(network)

    result = bech32_lib.encode(hrp, 0, pubkey_hash)
    if result is None:
        raise ValueError("Failed to encode bech32 address")
    return result

Convert compressed public key to P2WPKH (native SegWit) address.

Args

pubkey
33-byte compressed public key (bytes or hex string)
network
Network type

Returns

Bech32 P2WPKH address

def pubkey_to_p2wpkh_script(pubkey: bytes | str) ‑> bytes
Expand source code
def pubkey_to_p2wpkh_script(pubkey: bytes | str) -> bytes:
    """
    Create P2WPKH scriptPubKey from public key.

    Args:
        pubkey: 33-byte compressed public key (bytes or hex string)

    Returns:
        22-byte P2WPKH scriptPubKey (OP_0 <20-byte-hash>)
    """
    if isinstance(pubkey, str):
        pubkey = bytes.fromhex(pubkey)

    pubkey_hash = hash160(pubkey)
    return bytes([0x00, 0x14]) + pubkey_hash

Create P2WPKH scriptPubKey from public key.

Args

pubkey
33-byte compressed public key (bytes or hex string)

Returns

22-byte P2WPKH scriptPubKey (OP_0 <20-byte-hash>)

def script_to_p2wsh_address(script: bytes, network: str | NetworkType = 'mainnet') ‑> str
Expand source code
@validate_call
def script_to_p2wsh_address(script: bytes, network: str | NetworkType = "mainnet") -> str:
    """
    Convert witness script to P2WSH address.

    Args:
        script: Witness script bytes
        network: Network type

    Returns:
        Bech32 P2WSH address
    """
    script_hash = sha256(script)
    hrp = get_hrp(network)

    result = bech32_lib.encode(hrp, 0, script_hash)
    if result is None:
        raise ValueError("Failed to encode bech32 address")
    return result

Convert witness script to P2WSH address.

Args

script
Witness script bytes
network
Network type

Returns

Bech32 P2WSH address

def script_to_p2wsh_scriptpubkey(script: bytes) ‑> bytes
Expand source code
def script_to_p2wsh_scriptpubkey(script: bytes) -> bytes:
    """
    Create P2WSH scriptPubKey from witness script.

    Args:
        script: Witness script bytes

    Returns:
        34-byte P2WSH scriptPubKey (OP_0 <32-byte-hash>)
    """
    script_hash = sha256(script)
    return bytes([0x00, 0x20]) + script_hash

Create P2WSH scriptPubKey from witness script.

Args

script
Witness script bytes

Returns

34-byte P2WSH scriptPubKey (OP_0 <32-byte-hash>)