Branch data Line data Source code
1 : : // Copyright (c) 2017 Pieter Wuille
2 : : // Copyright (c) 2021 The Bitcoin Core developers
3 : : // Distributed under the MIT software license, see the accompanying
4 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 : :
6 : : #include <bech32.h>
7 : : #include <test/util/str.h>
8 : :
9 : : #include <boost/test/unit_test.hpp>
10 : :
11 : : #include <string>
12 : :
13 : 0 : BOOST_AUTO_TEST_SUITE(bech32_tests)
14 : :
15 : 0 : BOOST_AUTO_TEST_CASE(bech32_testvectors_valid)
16 : : {
17 : 0 : static const std::string CASES[] = {
18 : 0 : "A12UEL5L",
19 : 0 : "a12uel5l",
20 : 0 : "an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1tt5tgs",
21 : 0 : "abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw",
22 : 0 : "11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j",
23 : 0 : "split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w",
24 : 0 : "?1ezyfcl",
25 : : };
26 : 0 : for (const std::string& str : CASES) {
27 : 0 : const auto dec = bech32::Decode(str);
28 : 0 : BOOST_CHECK(dec.encoding == bech32::Encoding::BECH32);
29 : 0 : std::string recode = bech32::Encode(bech32::Encoding::BECH32, dec.hrp, dec.data);
30 : 0 : BOOST_CHECK(!recode.empty());
31 : 0 : BOOST_CHECK(CaseInsensitiveEqual(str, recode));
32 : 0 : }
33 : 0 : }
34 : :
35 : 0 : BOOST_AUTO_TEST_CASE(bech32m_testvectors_valid)
36 : : {
37 : 0 : static const std::string CASES[] = {
38 : 0 : "A1LQFN3A",
39 : 0 : "a1lqfn3a",
40 : 0 : "an83characterlonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11sg7hg6",
41 : 0 : "abcdef1l7aum6echk45nj3s0wdvt2fg8x9yrzpqzd3ryx",
42 : 0 : "11llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllludsr8",
43 : 0 : "split1checkupstagehandshakeupstreamerranterredcaperredlc445v",
44 : 0 : "?1v759aa"
45 : : };
46 : 0 : for (const std::string& str : CASES) {
47 : 0 : const auto dec = bech32::Decode(str);
48 : 0 : BOOST_CHECK(dec.encoding == bech32::Encoding::BECH32M);
49 : 0 : std::string recode = bech32::Encode(bech32::Encoding::BECH32M, dec.hrp, dec.data);
50 : 0 : BOOST_CHECK(!recode.empty());
51 : 0 : BOOST_CHECK(CaseInsensitiveEqual(str, recode));
52 : 0 : }
53 : 0 : }
54 : :
55 : 0 : BOOST_AUTO_TEST_CASE(bech32_testvectors_invalid)
56 : : {
57 : 0 : static const std::string CASES[] = {
58 : 0 : " 1nwldj5",
59 : 0 : "\x7f""1axkwrx",
60 : 0 : "\x80""1eym55h",
61 : 0 : "an84characterslonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1569pvx",
62 : 0 : "pzry9x0s0muk",
63 : 0 : "1pzry9x0s0muk",
64 : 0 : "x1b4n0q5v",
65 : 0 : "li1dgmt3",
66 : 0 : "de1lg7wt\xff",
67 : 0 : "A1G7SGD8",
68 : 0 : "10a06t8",
69 : 0 : "1qzzfhee",
70 : 0 : "a12UEL5L",
71 : 0 : "A12uEL5L",
72 : 0 : "abcdef1qpzrz9x8gf2tvdw0s3jn54khce6mua7lmqqqxw",
73 : 0 : "test1zg69w7y6hn0aqy352euf40x77qddq3dc",
74 : 0 : };
75 : 0 : static const std::pair<std::string, std::vector<int>> ERRORS[] = {
76 : 0 : {"Invalid character or mixed case", {0}},
77 : 0 : {"Invalid character or mixed case", {0}},
78 : 0 : {"Invalid character or mixed case", {0}},
79 : 0 : {"Bech32 string too long", {90}},
80 : 0 : {"Missing separator", {}},
81 : 0 : {"Invalid separator position", {0}},
82 : 0 : {"Invalid Base 32 character", {2}},
83 : 0 : {"Invalid separator position", {2}},
84 : 0 : {"Invalid character or mixed case", {8}},
85 : 0 : {"Invalid checksum", {}}, // The checksum is calculated using the uppercase form so the entire string is invalid, not just a few characters
86 : 0 : {"Invalid separator position", {0}},
87 : 0 : {"Invalid separator position", {0}},
88 : 0 : {"Invalid character or mixed case", {3, 4, 5, 7}},
89 : 0 : {"Invalid character or mixed case", {3}},
90 : 0 : {"Invalid Bech32 checksum", {11}},
91 : 0 : {"Invalid Bech32 checksum", {9, 16}},
92 : : };
93 : : static_assert(std::size(CASES) == std::size(ERRORS), "Bech32 CASES and ERRORS should have the same length");
94 : :
95 : 0 : int i = 0;
96 : 0 : for (const std::string& str : CASES) {
97 : 0 : const auto& err = ERRORS[i];
98 : 0 : const auto dec = bech32::Decode(str);
99 : 0 : BOOST_CHECK(dec.encoding == bech32::Encoding::INVALID);
100 : 0 : auto [error, error_locations] = bech32::LocateErrors(str);
101 : 0 : BOOST_CHECK_EQUAL(err.first, error);
102 : 0 : BOOST_CHECK(err.second == error_locations);
103 : 0 : i++;
104 : 0 : }
105 : 0 : }
106 : :
107 : 0 : BOOST_AUTO_TEST_CASE(bech32m_testvectors_invalid)
108 : : {
109 : 0 : static const std::string CASES[] = {
110 : 0 : " 1xj0phk",
111 : 0 : "\x7f""1g6xzxy",
112 : 0 : "\x80""1vctc34",
113 : 0 : "an84characterslonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11d6pts4",
114 : 0 : "qyrz8wqd2c9m",
115 : 0 : "1qyrz8wqd2c9m",
116 : 0 : "y1b0jsk6g",
117 : 0 : "lt1igcx5c0",
118 : 0 : "in1muywd",
119 : 0 : "mm1crxm3i",
120 : 0 : "au1s5cgom",
121 : 0 : "M1VUXWEZ",
122 : 0 : "16plkw9",
123 : 0 : "1p2gdwpf",
124 : 0 : "abcdef1l7aum6echk45nj2s0wdvt2fg8x9yrzpqzd3ryx",
125 : 0 : "test1zg69v7y60n00qy352euf40x77qcusag6",
126 : : };
127 : 0 : static const std::pair<std::string, std::vector<int>> ERRORS[] = {
128 : 0 : {"Invalid character or mixed case", {0}},
129 : 0 : {"Invalid character or mixed case", {0}},
130 : 0 : {"Invalid character or mixed case", {0}},
131 : 0 : {"Bech32 string too long", {90}},
132 : 0 : {"Missing separator", {}},
133 : 0 : {"Invalid separator position", {0}},
134 : 0 : {"Invalid Base 32 character", {2}},
135 : 0 : {"Invalid Base 32 character", {3}},
136 : 0 : {"Invalid separator position", {2}},
137 : 0 : {"Invalid Base 32 character", {8}},
138 : 0 : {"Invalid Base 32 character", {7}},
139 : 0 : {"Invalid checksum", {}},
140 : 0 : {"Invalid separator position", {0}},
141 : 0 : {"Invalid separator position", {0}},
142 : 0 : {"Invalid Bech32m checksum", {21}},
143 : 0 : {"Invalid Bech32m checksum", {13, 32}},
144 : : };
145 : : static_assert(std::size(CASES) == std::size(ERRORS), "Bech32m CASES and ERRORS should have the same length");
146 : :
147 : 0 : int i = 0;
148 : 0 : for (const std::string& str : CASES) {
149 : 0 : const auto& err = ERRORS[i];
150 : 0 : const auto dec = bech32::Decode(str);
151 : 0 : BOOST_CHECK(dec.encoding == bech32::Encoding::INVALID);
152 : 0 : auto [error, error_locations] = bech32::LocateErrors(str);
153 : 0 : BOOST_CHECK_EQUAL(err.first, error);
154 : 0 : BOOST_CHECK(err.second == error_locations);
155 : 0 : i++;
156 : 0 : }
157 : 0 : }
158 : :
159 : 0 : BOOST_AUTO_TEST_SUITE_END()
|