def test_valid_checksum(self): """Test checksum creation and validation.""" for test in VALID_CHECKSUM: hrp, _ = bech32.bech32_decode(test) self.assertIsNotNone(hrp) pos = test.rfind('1') test = test[:pos+1] + chr(ord(test[pos + 1]) ^ 1) + test[pos+2:] hrp, _ = bech32.bech32_decode(test) self.assertIsNone(hrp)
def doit(given_addr, path=None, addr_fmt=None, script=None): if not script: try: # prefer using xpub if we can mk = BIP32Node.from_wallet_key(master_xpub) sk = mk.subkey_for_path(path[2:]) except PublicPrivateMismatchError: mk = BIP32Node.from_wallet_key(simulator_fixed_xprv) sk = mk.subkey_for_path(path[2:]) if addr_fmt == AF_CLASSIC: # easy assert sk.address() == given_addr elif addr_fmt & AFC_PUBKEY: pkh = sk.hash160(use_uncompressed=False) if addr_fmt == AF_P2WPKH: hrp, data = bech32_decode(given_addr) decoded = convertbits(data[1:], 5, 8, False) assert hrp in {'tb', 'bc' } assert bytes(decoded[-20:]) == pkh else: assert addr_fmt == AF_P2WPKH_P2SH assert given_addr[0] in '23' expect = a2b_hashed_base58(given_addr)[1:] assert len(expect) == 20 assert hash160(b'\x00\x14' + pkh) == expect elif addr_fmt & AFC_SCRIPT: assert script, 'need a redeem/witness script' if addr_fmt == AF_P2SH: assert given_addr[0] in '23' expect = a2b_hashed_base58(given_addr)[1:] assert hash160(script) == expect elif addr_fmt == AF_P2WSH: hrp, data = bech32_decode(given_addr) assert hrp in {'tb', 'bc' } decoded = convertbits(data[1:], 5, 8, False) assert bytes(decoded[-32:]) == sha256(script).digest() elif addr_fmt == AF_P2WSH_P2SH: assert given_addr[0] in '23' expect = a2b_hashed_base58(given_addr)[1:] assert hash160(b'\x00\x20' + sha256(script).digest()) == expect else: raise pytest.fail(f'not ready for {addr_fmt:x} yet') else: raise ValueError(addr_fmt) return sk if not script else None
def patch(state: Optional[Dict], delegating: Optional[Dict], config: Config) -> Dict: tasks = [ _patch_schedule_task(task, int(x["height"]), config) for x in state.get("tasks") or [] for task in x.get("Schedule", []) ] if delegating: for cluster in delegating.get("clusters", None) or []: t: str = modulo_to_time(cluster["modulo"], config) tasks.extend({ "handler_name": "delegating/accrue", "time": t, "data": base64.standard_b64encode( bytes( bech32.convertbits(bech32.bech32_decode(acc)[1], 5, 8))).decode() } for acc in cluster["accounts"]) tasks.append({ "handler_name": "referral/status-bonus", "time": height_to_time(((config.initial_height - 1) // ONE_WEEK_BLOCKS + 1) * ONE_WEEK_BLOCKS, config) }) return { "params": { "day_nanos": str(24 * 60**2 * 10**9 // config.time_quotient) }, "tasks": tasks }
def cardano_shelly_check(match: regex.Match): text = match.groupdict().get('valu') # Bech32 decoding ret = bech32.bech32_decode(text) if ret == (None, None): return None, {} return ('ada', text), {}
def doit(given_addr, path, addr_fmt): mk = BIP32Node.from_wallet_key(master_xpub) sk = mk.subkey_for_path(path[2:]) if addr_fmt == AF_CLASSIC: # easy assert sk.address() == given_addr elif addr_fmt & AFC_PUBKEY: pkh = sk.hash160(use_uncompressed=False) if addr_fmt == AF_P2WPKH: hrp, data = bech32_decode(given_addr) decoded = convertbits(data[1:], 5, 8, False) assert hrp in {'tb', 'bc'} assert bytes(decoded[-20:]) == pkh else: assert addr_fmt == AF_P2WPKH_P2SH assert given_addr[0] in '23' expect = a2b_hashed_base58(given_addr)[1:] assert len(expect) == 20 assert hash160(b'\x00\x14' + pkh) == expect elif addr_fmt & AFC_SCRIPT: raise pytest.fail('multisig/p2sh addr not handled') else: raise ValueError(addr_fmt)
def validate(self): decoded_address = bech32.bech32_decode( self.request.address.decode('utf-8')) hrp = decoded_address[0] data = decoded_address[1] if hrp not in self.hrp_table: return False if data is None: return False """ test = [] for i in data: test.append(hex(i)) print(test) test = [] converted = bech32.convertbits(decoded_address[1], 5, 8, False) for i in converted: test.append(hex(i)) print(test) """ return True
def encode_fallback(fallback, currency): """ Encode all supported fallback addresses. """ if currency == 'bc' or currency == 'tb': fbhrp, witness = bech32_decode(fallback) if fbhrp: if fbhrp != currency: raise ValueError("Not a bech32 address for this currency") wver = witness[0] if wver > 16: raise ValueError("Invalid witness version {}".format( witness[0])) wprog = u5_to_bitarray(witness[1:]) else: addr = base58.b58decode_check(fallback) if is_p2pkh(currency, addr[0]): wver = 17 elif is_p2sh(currency, addr[0]): wver = 18 else: raise ValueError( "Unknown address type for {}".format(currency)) wprog = addr[1:] return tagged('f', bitstring.pack("uint:5", wver) + wprog) else: raise NotImplementedError( "Support for currency {} not implemented".format(currency))
def is_bech32(data: str) -> bool: # ignore if we are testing if os.environ.get("JIGU_BECH32_VALIDATE", "1") == "0": return True return bech32.bech32_decode(data) != ( None, None, )
def test_bech32(): testBechStr = "band1m5lq9u533qaya4q3nfyl6ulzqkpkhge9q8tpzs" hrp, bz = bech32_decode(testBechStr) assert hrp == BECH32_ADDR_ACC_PREFIX, "Invalid bech32 prefix" assert bz is not None, "result should not be empty" result = bech32_encode(BECH32_ADDR_VAL_PREFIX, bz) assert result == "bandvaloper1m5lq9u533qaya4q3nfyl6ulzqkpkhge9v30z8m", "invalid encoding"
def is_valid_address(cls, address: Address) -> bool: """ Check if the address is valid. :param address: the address to validate """ result = bech32_decode(address) return result != (None, None) and result[0] == cls.address_prefix
def bech32decode(bech): ''' Decode bech32 string into prefix and bytearray of data ''' hrp, data = bech32.bech32_decode(bech) # Return early if we couldn't parse the input string if data is None: return hrp, False converted = bech32.convertbits(data, 5, 8, False) return hrp, converted
def _from_bech32(cls, bech: str, prefix: str) -> PublicKey: hrp, bz = bech32_decode(bech) assert hrp == prefix, "Invalid bech32 prefix" bz = convertbits(bz, 5, 8, False) self = cls(_error_do_not_use_init_directly=True) self.verify_key = VerifyingKey.from_string( bytes(bz[5:]), curve=SECP256k1, hashfunc=hashlib.sha256 ) return self
def _bech32_decode(bech32: str, *, allowed_hrp: Set[str] = None) -> Tuple[str, List[int]]: hrp, data = bech32_decode(bech32) if None in (hrp, data) or (allowed_hrp and hrp not in allowed_hrp): raise ValueError(f"Invalid Human Readable Prefix (HRP): {hrp}.") return hrp, data
def AddressTest(rpc: RPC) -> None: #Test a variety of valid addresses. for _ in range(50): test(rpc, bytes([0]) + os.urandom(32), False, "Meros rejected a valid address.") #Invalid checksum. invalidChecksum: str = encodeAddress(os.urandom(33)) if invalidChecksum[-1] != 'q': invalidChecksum = invalidChecksum[:-1] + 'q' else: invalidChecksum = invalidChecksum[:-1] + 't' test(rpc, invalidChecksum, True, "Meros accepted an address with an invalid checksum.") #Invalid version byte. test(rpc, bytes([255]) + os.urandom(32), True, "Meros accepted an address with an invalid version byte.") #Invalid length. test(rpc, os.urandom(32), True, "Meros accepted an address with an invalid length.") test(rpc, os.urandom(34), True, "Meros accepted an address with an invalid length.") #Create a random address for us to mutate while preserving the checksum. randomKey: bytes = os.urandom(32) unchanged: str = encodeAddress(bytes([0]) + randomKey) #Sanity check against it. test(rpc, unchanged, False, "Meros rejected a valid address.") #Mutate it as described in https://github.com/sipa/bech32/issues/51#issuecomment-496797984. #Since we can insert any amount of 'q's, run this ten times. #It should be noted that this first insertion decodes to the same byte vector. #That said, the reference code is able to detect it as invalid due to its padding properties. #Because of that, it's noted here as an invalid case, to ensure compliance. for i in range(10): mutated: str = unchanged[:-1] + CHARSET[CHARSET.find(unchanged[-1]) ^ 1] #Just i would be 0 on the first run, which would be a NOP. #Therefore, a valid and unmodified address. mutated += "q" * (i + 1) mutated = mutated[:-1] + CHARSET[CHARSET.find(mutated[-1]) ^ 1] #Sanity check that our mutation worked. decoded: Union[Tuple[None, None], Tuple[str, List[int]]] = bech32_decode(mutated) if decoded is Tuple[None, None]: raise Exception("Mutation stopped the checksum from passing.") test( rpc, mutated, True, "Meros accepted an address which had been mutated yet still passed the checksum." )
def decodeAddress( address: str ) -> bytes: decoded: Union[Tuple[None, None], Tuple[str, List[int]]] = bech32_decode(address) if decoded[1] is None: raise TestError("Decoding an invalid address.") res: List[int] = convertbits(decoded[1], 5, 8) if res[0] != 0: raise TestError("Decoding an address which isn't a Public Key.") return bytes(res[1:33])
def test_invoice_decode(node_factory, impl): capacity = 10**7 node1 = node_factory.get_node(implementation=impl) amount = int(capacity / 10) payment_request = node1.invoice(amount) hrp, data = bech32_decode(payment_request) assert hrp and data assert hrp.startswith('lnbcrt')
def _from_bech32(cls, bech: str, prefix: str) -> "Address": hrp, bz = bech32_decode(bech) assert hrp == prefix, "Invalid bech32 prefix" if bz is None: raise DecodeError("Cannot decode bech32") eight_bit_r = convertbits(bz, 5, 8, False) if eight_bit_r is None: raise ConvertError("Cannot convert to 8 bit") return cls(bytes(eight_bit_r))
def network(self): decoded_address = bech32.bech32_decode( self.request.address.decode('utf-8')) hrp = decoded_address[0] for name, networks in self.request.currency.networks.items(): for netw in networks: if hrp == netw: return name return ""
def decode_bytes(bech32_string): try: hrp, data = bech32_decode(bech32_string) except: return None, None if not hrp: return None, None deconverted = convertbits(data, 5, 8, False) assert deconverted decoded = bytes(deconverted) return hrp, decoded
def test_n_decoding(): # We flip the signature recovery bit, which would normally give a different # pubkey. hrp, data = bech32_decode( lnencode(LnAddr(RHASH, amount=24, tags=[('d', '')]), PRIVKEY)) databits = u5_to_bitarray(data) databits.invert(-1) lnaddr = lndecode(bech32_encode(hrp, bitarray_to_u5(databits))) assert hexlify(lnaddr.pubkey.serialize(compressed=True)) != PUBKEY # But not if we supply expliciy `n` specifier! hrp, data = bech32_decode( lnencode( LnAddr(RHASH, amount=24, tags=[('d', ''), ('n', unhexlify(PUBKEY))]), PRIVKEY)) databits = u5_to_bitarray(data) databits.invert(-1) lnaddr = lndecode(bech32_encode(hrp, bitarray_to_u5(databits))) assert hexlify(lnaddr.pubkey.serialize(compressed=True)) == PUBKEY
def address_type(self): if len(self.request.address) == 0: return "" decoded_address = bech32.bech32_decode( self.request.address.decode('utf-8')) hrp = decoded_address[0] if hrp not in self.hrp_table: return "" return hrp
def bech32_to_scripthash(address): hrp, data = bech32.bech32_decode(address) witver, witprog = bech32.decode(hrp, address) script = [witver, len(witprog)] + witprog script = ''.join('{:02x}'.format(x) for x in script) scripthash = hashlib.sha256(binascii.unhexlify(script)).hexdigest() rev = '' i = len(scripthash) - 2 while i >= 0: rev += scripthash[i:i + 2] i -= 2 return rev
def convert_prefix(in_val: str) -> str: prefix = "" for key in replaceable_map: if in_val.startswith(key): prefix = key[:-1] break if not prefix: raise ValueError(f"Cannot decode string {in_val}") _, data = bech32.bech32_decode(in_val) return bech32.bech32_encode(conversion_map[prefix], data)
def validate(self): decoded_address = bech32.bech32_decode( self.request.address.decode('utf-8')) data = decoded_address[1] if self.network == "": return False if data is None: return False return True
def is_valid_address(address: str) -> bool: if not (len(address) == 43 and address.islower()): return False prefix, data = bech32_decode(address) if prefix is None or data is None: return False if prefix == 'htdf' and len(data) == 32: return True return False
def __get_seed_keys(self): """ retrieve the nodeids of the ln seed nodes from lseed.bitcoinstats.com """ domain = "lseed.bitcoinstats.com" srv_records = dns.resolver.query(domain, "SRV") res = [] for srv in srv_records: bech32 = str(srv.target).rstrip(".").split(".")[0] data = bech32_decode(bech32)[1] decoded = convertbits(data, 5, 4) res.append("".join( ['{:1x}'.format(integer) for integer in decoded])[:-1]) return res
def to_val_pubkey(data: AccPubKey) -> ValPubKey: """Converts an account pubkey into a validator pubkey. Args: data (AccPubKey): account pubkey Raises: ValueError: if provided string is not Bech32 Returns: ValPubKey: validator pubkey """ vals = bech32_decode(data) if vals[1] is None: raise ValueError(f"invalid bech32: {data}") return ValPubKey(bech32_encode("terravaloperpub", vals[1]))
def to_val_address(data: AccAddress) -> ValAddress: """Converts an account address into a validator operator address. Args: data (AccAddress): account address Raises: ValueError: if provided string is not Bech32 Returns: ValAddress: validator operator address """ vals = bech32_decode(data) if vals[1] is None: raise ValueError(f"invalid bech32: {data}") return ValAddress(bech32_encode("terravaloper", vals[1]))
def decode(pr: str) -> Invoice: """ Super naïve bolt11 decoder, only gets payment_hash, description/description_hash and amount in msatoshi. based on https://github.com/rustyrussell/lightning-payencode/blob/master/lnaddr.py """ hrp, data = bech32_decode(pr) if not hrp: raise ValueError("Bad bech32 checksum") if not hrp.startswith("ln"): raise ValueError("Does not start with ln") data = u5_to_bitarray(data) # Final signature 65 bytes, split it off. if len(data) < 65 * 8: raise ValueError("Too short to contain signature") data = bitstring.ConstBitStream(data[:-65 * 8]) invoice = Invoice() m = re.search("[^\d]+", hrp[2:]) if m: amountstr = hrp[2 + m.end():] if amountstr != "": invoice.amount_msat = unshorten_amount(amountstr) # pull out date data.read(35).uint while data.pos != data.len: tag, tagdata, data = pull_tagged(data) data_length = len(tagdata) / 5 if tag == "d": invoice.description = trim_to_bytes(tagdata).decode("utf-8") elif tag == "h" and data_length == 52: invoice.description = hexlify( trim_to_bytes(tagdata)).decode("ascii") elif tag == "p" and data_length == 52: invoice.payment_hash = hexlify( trim_to_bytes(tagdata)).decode("ascii") return invoice
def is_valid_address(address) -> bool: """ Check if given string is valid one address NOTE: This function is NOT thread safe due to the C function used by the bech32 library. Parameters ---------- address: str String to check if valid one address Returns ------- bool Is valid address """ if not address.startswith('one1'): return False hrp, _ = bech32_decode(address) if not hrp: return False return True