def gen_invalid_bech32_vector(template): '''Generate possibly invalid bech32 vector''' no_data = randbool(0.1) to_upper = randbool(0.1) hrp = template[0] witver = template[1] witprog = bytearray(os.urandom(template[2])) if no_data: rv = bech32_encode(hrp, []) else: data = [witver] + convertbits(witprog, 8, 5) if template[3] and not no_data: if template[2] % 5 in {2, 4}: data[-1] |= 1 else: data.append(0) rv = bech32_encode(hrp, data) if template[4]: i = len(rv) - random.randrange(1, 7) rv = rv[:i] + random.choice(CHARSET.replace(rv[i], '')) + rv[i + 1:] if template[5]: i = len(hrp) + 1 + random.randrange(0, len(rv) - len(hrp) - 4) rv = rv[:i] + rv[i:i + 4].upper() + rv[i + 4:] if to_upper: rv = rv.swapcase() return rv
def decodeAddress(addr, network="mainnet"): hrp = {"mainnet": "ckb", "testnet": "ckt"}[network] hrpgot, data = sa.bech32_decode(addr) if hrpgot != hrp or data == None: return False decoded = sa.convertbits(data, 5, 8, False) if decoded == None: return False payload = bytes(decoded) format_type = payload[0] if format_type == FORMAT_TYPE_SHORT: code_index = payload[1] pk = payload[2:].hex() return ("short", code_index, pk) elif format_type == FORMAT_TYPE_FULL_DATA or format_type == FORMAT_TYPE_FULL_TYPE: full_type = { FORMAT_TYPE_FULL_DATA: "Data", FORMAT_TYPE_FULL_TYPE: "Type" }[format_type] ptr = 1 code_hash = payload[ptr:ptr + 32].hex() ptr += 32 args = [] while ptr < len(payload): arg_len = int(payload[ptr]) ptr += 1 args.append(payload[ptr:ptr + arg_len].hex()) ptr += arg_len return ("full", full_type, code_hash, args)
def gen_valid_bech32_vector(template): '''Generate valid bech32 vector''' hrp = template[0] witver = template[1] witprog = bytearray(os.urandom(template[2])) dst_prefix = bytearray(template[4]) rv = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5)) return rv, dst_prefix + witprog
def bech32Decode(hrp, addr): hrpgot, data = segwit_addr.bech32_decode(addr) if hrpgot != hrp: return None decoded = segwit_addr.convertbits(data, 5, 8, False) if decoded is None or len(decoded) < 2 or len(decoded) > 40: return None return bytes(decoded)
def generateShortAddress(code_index, args, network="mainnet"): """ generate a short ckb address """ hrp = {"mainnet": "ckb", "testnet": "ckt"}[network] hrpexp = sa.bech32_hrp_expand(hrp) format_type = FORMAT_TYPE_SHORT payload = bytes([format_type, code_index]) + bytes.fromhex(args) data_part = sa.convertbits(payload, 8, 5) values = hrpexp + data_part polymod = sa.bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ 1 checksum = [(polymod >> 5 * (5 - i)) & 31 for i in range(6)] combined = data_part + checksum addr = hrp + '1' + ''.join([sa.CHARSET[d] for d in combined]) return addr
def pk_decode(a): (hrp, pk5) = segwit_addr.bech32_decode(a) if hrp != 'pk': return None pk8 = segwit_addr.convertbits(pk5, 5, 8) if len(pk8) < 33: return None if len(pk8) > 33: for b in pk8[33:]: if b > 0: return None pk8 = pk8[0:33] return bytestohex(pk8)
def generateFullAddress(hash_type, code_hash, args, network="mainnet"): format_type = { "Data": bytes([FORMAT_TYPE_FULL_DATA]), "Type": bytes([FORMAT_TYPE_FULL_TYPE]) }[hash_type] hrp = {"mainnet": "ckb", "testnet": "ckt"}[network] hrpexp = sa.bech32_hrp_expand(hrp) payload = bytes(format_type) + bytes.fromhex(code_hash) payload += bytes.fromhex(args) data_part = sa.convertbits(payload, 8, 5) values = hrpexp + data_part polymod = sa.bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ 1 checksum = [(polymod >> 5 * (5 - i)) & 31 for i in range(6)] combined = data_part + checksum addr = hrp + '1' + ''.join([sa.CHARSET[d] for d in combined]) return addr
def bech32Encode(hrp, data): ret = segwit_addr.bech32_encode(hrp, segwit_addr.convertbits(data, 8, 5)) if bech32Decode(hrp, ret) is None: return None return ret
def bech32Encode(hrp, data): ret = bech32_encode(hrp, convertbits(data, 8, 5)) if bech32Decode(hrp, ret) is None: return None return ret
def pk_encode(k): pk8 = hextobytes(k) pk5 = segwit_addr.convertbits(pk8, 8, 5) a = segwit_addr.bech32_encode('pk', pk5) return a