from pybtc.functions.hash import double_sha256 from pybtc.crypto import __decode_base58__, __encode_base58__ b58_digits = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' base32charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" base32charset_upcase = "QPZRY9X8GF2TVDW0S3JN54KHCE6MUA7L" int_base32_map = dict() base32_int_map = dict() for n, i in enumerate(base32charset): int_base32_map[i] = n base32_int_map[n] = ord(i) for n, i in enumerate(base32charset_upcase): int_base32_map[i] = n def rebasebits(data, frombits, tobits, pad=True): """General power-of-2 base conversion.""" acc = 0 bits = 0 ret = bytearray() append = ret.append maxv = (1 << tobits) - 1 max_acc = (1 << (frombits + tobits - 1)) - 1 for value in data: if value < 0 or (value >> frombits): raise ValueError("invalid bytes") acc = ((acc << frombits) | value) & max_acc bits += frombits while bits >= tobits: bits -= tobits append((acc >> bits) & maxv) if pad: if bits: append((acc << (tobits - bits)) & maxv) elif bits >= frombits or ((acc << (tobits - bits)) & maxv): raise ValueError("invalid padding") return ret def rebase_5_to_8(data, pad = True): return rebasebits(data, 5, 8, pad) def rebase_8_to_5(data, pad = True): return rebasebits(data, 8, 5, pad) def rebase_32_to_5(data): if isinstance(data, bytes): data = data.decode() b = bytearray() append = b.append try: [append(int_base32_map[i]) for i in data] except: raise Exception("Non base32 characters") return b def rebase_5_to_32(data, bytes = True): r = bytearray() append = r.append [append(base32_int_map[i]) for i in data] return r.decode() if not bytes else r def bech32_polymod(values): """Internal function that computes the Bech32 checksum.""" generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3] chk = 1 for value in values: top = chk >> 25 chk = (chk & 0x1ffffff) << 5 ^ value for i in range(5): chk ^= generator[i] if ((top >> i) & 1) else 0 return chk ^ 1 def encode_base58(b): """Encode bytes to a base58-encoded string""" # Convert big-endian bytes to integer if not b: return '' if not isinstance(b, bytes): raise ValueError("encode_base58 bytes required") return __encode_base58__(b) def decode_base58(s): """Decode a base58-encoding string, returning bytes""" if not s: return b'' if not isinstance(s, str): raise ValueError("decode_base58 string required") return __decode_base58__(s) def encode_base58_with_checksum(b): return encode_base58(b"%s%s" % (b, double_sha256(b)[:4])) def decode_base58_with_checksum(s): b = decode_base58(s) if double_sha256(b[:-4])[:4] != b[-4:]: raise Exception("invalid checksum") return b[:-4]