def deserialize(cls, bts: bytes, network='btc'): def read(n): nonlocal bts data, bts = bts[:n], bts[n:] return data net = read(4) is_private = net in get_network_attr('extended_prv', network).values() is_public = net in get_network_attr('extended_pub', network).values() assert is_public ^ is_private, f'Invalid network bytes : {bytes_to_hex(net)}' address_lookup = {val: key for key, val in ( get_network_attr('extended_prv', network) if is_private else get_network_attr('extended_pub', network)).items()} constructor = XPrv if is_private else XPub depth = bytes_to_int(read(1)) assert depth in range(256), f'Invalid depth : {depth}' fingerprint = read(4) i = bytes_to_int(read(4)) if depth == 0: i = None path = None else: ih = f'{i}' if i < 2 ** 31 else f"{i - 2 ** 31}h" path = '/'.join([constructor.root_path] + ['x' for _ in range(depth - 1)] + [ih]) code = read(32) key = read(33) key = PrivateKey(key, network=network) if is_private else PublicKey.decode(key, network=network) assert not bts, 'Leftover bytes' return constructor(key, code, depth=depth, i=i, parent=fingerprint, path=path, address_type=address_lookup[net])
def from_wif(wif: str, network='btc') -> "PrivateKey": bts = b58decode(wif) network_byte, key, checksum = bts[0:1], bts[1:-4], bts[-4:] assert sha256(sha256(network_byte + key))[:4] == checksum, 'Invalid Checksum' assert network_byte == get_network_attr( 'wif', network), 'Invalid Network byte' if key.endswith(b'\x01'): key = key[:-1] compressed = True # TODO else: compressed = False # TODO return PrivateKey(key)
def to_p2wpkh_p2sh(public_key: PublicKey) -> 'str': return legacy_address( witness_byte(witver=0) + push(hash160(public_key.encode(compressed=True))), version_byte=get_network_attr('scripthash', public_key.network))
def to_p2pkh(public_key: PublicKey, compressed=False) -> 'str': return legacy_address( public_key.encode(compressed=True) if compressed else public_key, version_byte=get_network_attr('keyhash', public_key.network))
def pubkey_to_bech32(public_key: PublicKey, witver: int) -> str: """https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#witness-program""" witprog = hash160(public_key.encode(compressed=True)) return bech32.encode(get_network_attr('hrp', public_key.network), witver, witprog)
def wif(self, compressed=False): extended = get_network_attr('wif', self.network) + self.bytes() + ( b'\x01' if compressed else b'') hashed = sha256(sha256(extended)) checksum = hashed[:4] return b58encode(extended + checksum)
def serialize(self): version = get_network_attr('extended_pub', self.key.network)[self.type] depth = int_to_bytes(self.depth) child = bytes(4) if self.is_master() else int_to_bytes(self.i).rjust(4, b'\x00') return version + depth + self.parent + child + self.code + self.key_data()