def test_bech32_insertion_issue() -> None: """Test documented bech32 insertion issue. https://github.com/sipa/bech32/issues/51 https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-November/017443.html https://gist.github.com/sipa/a9845b37c1b298a7301c33a04090b2eb https://gist.github.com/sipa/a9845b37c1b298a7301c33a04090b2eb https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2020-October/018236.html https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2020-December/018292.html https://gist.github.com/sipa/14c248c288c3880a3b191f978a34508e """ strings = ("ii2134hk2xmat79tp", "eyg5bsz1l2mrq5ypl40hp") for string in strings: for i in range(20): decode(string[:-1] + i * "q" + string[-1:], _BECH32_1_CONST)
def witness_from_address(b32addr: String) -> Tuple[int, bytes, str]: """Return the witness from a bech32 native SegWit address. The returned data structure is: version, program, network. """ if isinstance(b32addr, str): b32addr = b32addr.strip() # the following check was originally in b32decode # but it does not pertain there if len(b32addr) > 90: raise BTClibValueError(f"invalid bech32 address length: {len(b32addr)} > 90") hrp, data = decode(b32addr) wit_ver = data[0] wit_prog = bytes(power_of_2_base_conversion(data[1:], 5, 8, False)) wit_prog = check_witness(wit_ver, wit_prog) # check that it is a known SegWit address type network = network_from_key_value("hrp", hrp) if network is None: raise BTClibValueError(f"invalid hrp: {hrp}") return wit_ver, wit_prog, network
def test_valid_checksum(self): """Test validation of valid checksums.""" for test in VALID_CHECKSUM: _, _ = bech32.decode(test) pos = test.rfind('1') test = test[:pos + 1] + chr(ord(test[pos + 1]) ^ 1) + test[pos + 2:] self.assertRaises(ValueError, bech32.decode, test)
def test_bech32() -> None: "Test bech32 checksum." valid_checksum = [ "A12UEL5L", "a12uel5l", "an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1tt5tgs", "abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw", "11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j", "split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w", "?1ezyfcl", # the next one would have been invalid with the 90 char limit "an84characterslonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1569pvx", ] for test in valid_checksum: decoded = decode(test, _BECH32_1_CONST) assert decoded == decode(test.encode("ascii"), _BECH32_1_CONST) assert encode(*decoded, _BECH32_1_CONST).decode() == test.lower() pos = test.rfind("1") test = test[:pos + 1] + chr(ord(test[pos + 1]) ^ 1) + test[pos + 2:] with pytest.raises(BTClibValueError): decode(test, _BECH32_1_CONST) invalid_checksum = [ ["\x20" + " 1nwldj5", r"HRP character out of range: *"], ["\x7F" + "1axkwrx", r"HRP character out of range: *"], ["\x80" + "1eym55h", r"HRP character out of range: *"], ["pzry9x0s0muk", r"no separator character: *"], ["1pzry9x0s0muk", r"empty HRP: *"], ["x1b4n0q5v", r"invalid data character: *"], ["li1dgmt3", r"too short checksum: *"], # Invalid character in checksum ["de1lg7wt\xff", r"invalid character in checksum: *"], # checksum calculated with uppercase form of HRP ["A1G7SGD8", r"invalid checksum: *"], ["10a06t8", r"empty HRP: *"], ["1qzzfhee", r"empty HRP: *"], ] for addr, err_msg in invalid_checksum: with pytest.raises(BTClibValueError, match=err_msg): decode(addr, _BECH32_1_CONST)
def test_bech32m() -> None: valid_checksum = [ "A1LQFN3A", "a1lqfn3a", "an83characterlonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11sg7hg6", "abcdef1l7aum6echk45nj3s0wdvt2fg8x9yrzpqzd3ryx", "11llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllludsr8", "split1checkupstagehandshakeupstreamerranterredcaperredlc445v", "?1v759aa", # the next one would have been invalid with the 90 char limit "an84characterslonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11d6pts4", ] for test in valid_checksum: decoded = decode(test, _BECH32_M_CONST) assert decoded == decode(test.encode("ascii"), _BECH32_M_CONST) assert encode(*decoded, _BECH32_M_CONST).decode() == test.lower() pos = test.rfind("1") test = test[:pos + 1] + chr(ord(test[pos + 1]) ^ 1) + test[pos + 2:] with pytest.raises(BTClibValueError): decode(test, _BECH32_M_CONST) invalid_checksum = [ ["\x20" + "1xj0phk", r"HRP character out of range: *"], ["\x7F" + "1g6xzxy", r"HRP character out of range: *"], ["\x80" + "1vctc34", r"HRP character out of range: *"], ["qyrz8wqd2c9m", r"no separator character: *"], ["1qyrz8wqd2c9m", r"empty HRP: *"], ["y1b0jsk6g", r"invalid data character: *"], ["lt1igcx5c0", r"invalid data character: *"], ["in1muywd", r"too short checksum: *"], ["mm1crxm3i", r"invalid character in checksum: *"], ["au1s5cgom", r"invalid character in checksum: *"], ["M1VUXWEZ", r"invalid checksum: *"], ["16plkw9", r"empty HRP: *"], ["1p2gdwpf", r"empty HRP: *"], ] for addr, err_msg in invalid_checksum: with pytest.raises(BTClibValueError, match=err_msg): decode(addr, _BECH32_M_CONST)