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