import hashlib import struct from io import BytesIO from secp256k1 import ECKey from typing import Union def from_hex(hex_string): """Deserialize from a hex string representation (e.g. from RPC)""" return BytesIO(bytes.fromhex(hex_string)) def ser_uint32(u: int) -> bytes: return u.to_bytes(4, "big") def ser_uint256(u): return u.to_bytes(32, 'little') def deser_uint256(f): return int.from_bytes(f.read(32), 'little') def deser_txid(txid: str): # recall that txids are serialized little-endian, but displayed big-endian # this means when converting from a human readable hex txid, we need to first # reverse it before deserializing it dixt = "".join(map(str.__add__, txid[-2::-2], txid[-1::-2])) return bytes.fromhex(dixt) def deser_compact_size(f: BytesIO): view = f.getbuffer() nbytes = view.nbytes; view.release() if (nbytes == 0): return 0 # end of stream nit = struct.unpack(" bytes: return hashlib.new("ripemd160", hashlib.sha256(s).digest()).digest() def is_p2tr(spk: bytes) -> bool: if len(spk) != 34: return False # OP_1 OP_PUSHBYTES_32 <32 bytes> return (spk[0] == 0x51) & (spk[1] == 0x20) def is_p2wpkh(spk: bytes) -> bool: if len(spk) != 22: return False # OP_0 OP_PUSHBYTES_20 <20 bytes> return (spk[0] == 0x00) & (spk[1] == 0x14) def is_p2sh(spk: bytes) -> bool: if len(spk) != 23: return False # OP_HASH160 OP_PUSHBYTES_20 <20 bytes> OP_EQUAL return (spk[0] == 0xA9) & (spk[1] == 0x14) & (spk[-1] == 0x87) def is_p2pkh(spk: bytes) -> bool: if len(spk) != 25: return False # OP_DUP OP_HASH160 OP_PUSHBYTES_20 <20 bytes> OP_EQUALVERIFY OP_CHECKSIG return (spk[0] == 0x76) & (spk[1] == 0xA9) & (spk[2] == 0x14) & (spk[-2] == 0x88) & (spk[-1] == 0xAC)