codex32_tests.cpp raw
1 // Copyright (c) 2023 The Limenka developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5 #include <bech32.h>
6 #include <codex32.h>
7 #include <test/util/str.h>
8
9 #include <boost/test/unit_test.hpp>
10
11 #include <array>
12 #include <string>
13
14 BOOST_AUTO_TEST_SUITE(codex32_tests)
15
16 BOOST_AUTO_TEST_CASE(codex32_bip93_misc_invalid)
17 {
18 // This example uses a "0" threshold with a non-"s" index
19 const std::string input1 = "ms10fauxxxxxxxxxxxxxxxxxxxxxxxxxxxx0z26tfn0ulw3p";
20 const auto dec1 = codex32::Result{input1};
21 BOOST_CHECK_EQUAL(dec1.error(), codex32::INVALID_SHARE_IDX);
22
23 // This example has a threshold that is not a digit.
24 const std::string input2 = "ms1fauxxxxxxxxxxxxxxxxxxxxxxxxxxxxxda3kr3s0s2swg";
25 const auto dec2 = codex32::Result{input2};
26 BOOST_CHECK_EQUAL(dec2.error(), codex32::INVALID_K);
27 }
28
29 BOOST_AUTO_TEST_CASE(codex32_bip93_vector_1)
30 {
31 const std::string input = "ms10testsxxxxxxxxxxxxxxxxxxxxxxxxxx4nzvca9cmczlw";
32
33 const auto dec = codex32::Result{input};
34 BOOST_CHECK(dec.IsValid());
35 BOOST_CHECK_EQUAL(dec.error(), codex32::OK);
36 BOOST_CHECK_EQUAL(dec.GetHrp(), "ms");
37 BOOST_CHECK_EQUAL(dec.GetK(), 0);
38 BOOST_CHECK_EQUAL(dec.GetIdString(), "test");
39 BOOST_CHECK_EQUAL(dec.GetShareIndex(), 's');
40
41 const auto payload = dec.GetPayload();
42 BOOST_CHECK_EQUAL(payload.size(), 16);
43 BOOST_CHECK_EQUAL(HexStr(payload), "318c6318c6318c6318c6318c6318c631");
44
45 // Try re-encoding
46 BOOST_CHECK_EQUAL(input, dec.Encode());
47
48 // Try directly constructing the share
49 const auto direct = codex32::Result("ms", 0, "test", 's', payload);
50 BOOST_CHECK(direct.IsValid());
51 BOOST_CHECK_EQUAL(direct.error(), codex32::OK);
52 BOOST_CHECK_EQUAL(direct.GetIdString(), "test");
53 BOOST_CHECK_EQUAL(direct.GetShareIndex(), 's');
54
55 // We cannot check that the codex32 string is exactly the same as the
56 // input, since it will not be -- the test vector has nonzero trailing
57 // bits while our code will always choose zero trailing bits. But we
58 // can at least check that the payloads are identical.
59 const auto payload_direct = direct.GetPayload();
60 BOOST_CHECK_EQUAL(HexStr(payload), HexStr(payload_direct));
61 }
62
63 BOOST_AUTO_TEST_CASE(codex32_bip93_vector_2)
64 {
65 const std::string input_a = "MS12NAMEA320ZYXWVUTSRQPNMLKJHGFEDCAXRPP870HKKQRM";
66 const auto dec_a = codex32::Result{input_a};
67 BOOST_CHECK(dec_a.IsValid());
68 BOOST_CHECK_EQUAL(dec_a.GetHrp(), "ms");
69 BOOST_CHECK_EQUAL(dec_a.GetK(), 2);
70 BOOST_CHECK_EQUAL(dec_a.GetIdString(), "name");
71 BOOST_CHECK_EQUAL(dec_a.GetShareIndex(), 'a');
72 BOOST_CHECK(CaseInsensitiveEqual(input_a, dec_a.Encode()));
73
74 const std::string input_c = "MS12NAMECACDEFGHJKLMNPQRSTUVWXYZ023FTR2GDZMPY6PN";
75 const auto dec_c = codex32::Result{input_c};
76 BOOST_CHECK(dec_c.IsValid());
77 BOOST_CHECK_EQUAL(dec_c.GetHrp(), "ms");
78 BOOST_CHECK_EQUAL(dec_c.GetK(), 2);
79 BOOST_CHECK_EQUAL(dec_c.GetIdString(), "name");
80 BOOST_CHECK_EQUAL(dec_c.GetShareIndex(), 'c');
81 BOOST_CHECK(CaseInsensitiveEqual(input_c, dec_c.Encode()));
82
83 const auto d = codex32::Result{{input_a, input_c}, 'd'};
84 BOOST_CHECK(d.IsValid());
85 BOOST_CHECK_EQUAL(d.GetHrp(), "ms");
86 BOOST_CHECK_EQUAL(d.GetK(), 2);
87 BOOST_CHECK_EQUAL(d.GetIdString(), "name");
88 BOOST_CHECK_EQUAL(d.GetShareIndex(), 'd');
89 BOOST_CHECK(CaseInsensitiveEqual("MS12NAMEDLL4F8JLH4E5VDVULDLFXU2JHDNLSM97XVENRXEG", d.Encode()));
90
91 const auto err1 = codex32::Result{{}, 's'};
92 BOOST_CHECK_EQUAL(err1.error(), codex32::TOO_FEW_SHARES);
93 const auto err2 = codex32::Result{{input_c}, 's'};
94 BOOST_CHECK_EQUAL(err2.error(), codex32::TOO_FEW_SHARES);
95 const auto err3 = codex32::Result{{input_a, input_c}, 'b'};
96 BOOST_CHECK_EQUAL(err3.error(), codex32::INVALID_SHARE_IDX);
97
98 const auto s = codex32::Result{{input_a, input_c}, 's'};
99 BOOST_CHECK(s.IsValid());
100 BOOST_CHECK_EQUAL(s.GetHrp(), "ms");
101 BOOST_CHECK_EQUAL(s.GetK(), 2);
102 BOOST_CHECK_EQUAL(s.GetIdString(), "name");
103 BOOST_CHECK_EQUAL(s.GetShareIndex(), 's');
104 BOOST_CHECK(CaseInsensitiveEqual("MS12NAMES6XQGUZTTXKEQNJSJZV4JV3NZ5K3KWGSPHUH6EVW", s.Encode()));
105
106 const auto seed = s.GetPayload();
107 BOOST_CHECK_EQUAL(seed.size(), 16);
108 BOOST_CHECK_EQUAL(HexStr(seed), "d1808e096b35b209ca12132b264662a5");
109 }
110
111 BOOST_AUTO_TEST_CASE(codex32_bip93_vector_3)
112 {
113 const auto s = codex32::Result("ms", 3, "Cash", 's', ParseHex("ffeeddccbbaa99887766554433221100"));
114 BOOST_CHECK(s.IsValid());
115 BOOST_CHECK_EQUAL(s.GetIdString(), "cash");
116 BOOST_CHECK_EQUAL(s.GetShareIndex(), 's');
117 BOOST_CHECK_EQUAL(s.GetK(), 3);
118 BOOST_CHECK_EQUAL(s.Encode(), "ms13cashsllhdmn9m42vcsamx24zrxgs3qqjzqud4m0d6nln");
119
120 const auto a = codex32::Result{"ms13casha320zyxwvutsrqpnmlkjhgfedca2a8d0zehn8a0t"};
121 BOOST_CHECK(a.IsValid());
122 BOOST_CHECK_EQUAL(a.GetIdString(), "cash");
123 BOOST_CHECK_EQUAL(a.GetShareIndex(), 'a');
124 BOOST_CHECK_EQUAL(a.GetK(), 3);
125
126 const auto c = codex32::Result{"ms13cashcacdefghjklmnpqrstuvwxyz023949xq35my48dr"};
127 BOOST_CHECK(c.IsValid());
128 BOOST_CHECK_EQUAL(c.GetIdString(), "cash");
129 BOOST_CHECK_EQUAL(c.GetShareIndex(), 'c');
130 BOOST_CHECK_EQUAL(c.GetK(), 3);
131
132 const auto err1 = codex32::Result{{}, 'd'};
133 BOOST_CHECK_EQUAL(err1.error(), codex32::TOO_FEW_SHARES);
134 const auto err2 = codex32::Result{{a, c}, 'd'};
135 BOOST_CHECK_EQUAL(err2.error(), codex32::TOO_FEW_SHARES);
136 const auto err3 = codex32::Result{{s, a}, 'd'};
137 BOOST_CHECK_EQUAL(err3.error(), codex32::TOO_FEW_SHARES);
138 const auto err4 = codex32::Result{{s, s, a}, 'd'};
139 BOOST_CHECK_EQUAL(err4.error(), codex32::DUPLICATE_SHARE);
140
141 const auto d = codex32::Result{{s, a, c}, 'd'};
142 BOOST_CHECK(d.IsValid());
143 BOOST_CHECK_EQUAL(d.GetIdString(), "cash");
144 BOOST_CHECK_EQUAL(d.GetShareIndex(), 'd');
145 BOOST_CHECK_EQUAL(d.GetK(), 3);
146 BOOST_CHECK_EQUAL(d.Encode(), "ms13cashd0wsedstcdcts64cd7wvy4m90lm28w4ffupqs7rm");
147
148 const auto e = codex32::Result{{a, c, d}, 'e'};
149 BOOST_CHECK(e.IsValid());
150 BOOST_CHECK_EQUAL(e.GetIdString(), "cash");
151 BOOST_CHECK_EQUAL(e.GetShareIndex(), 'e');
152 BOOST_CHECK_EQUAL(e.GetK(), 3);
153 BOOST_CHECK_EQUAL(e.Encode(), "ms13casheekgpemxzshcrmqhaydlp6yhms3ws7320xyxsar9");
154
155 const auto f = codex32::Result{{a, s, d}, 'f'};
156 BOOST_CHECK(f.IsValid());
157 BOOST_CHECK_EQUAL(f.GetIdString(), "cash");
158 BOOST_CHECK_EQUAL(f.GetShareIndex(), 'f');
159 BOOST_CHECK_EQUAL(f.GetK(), 3);
160 BOOST_CHECK_EQUAL(f.Encode(), "ms13cashf8jh6sdrkpyrsp5ut94pj8ktehhw2hfvyrj48704");
161
162 // Mismatched data
163 const auto g1 = codex32::Result{"ms", 2, "cash", 'g', ParseHex("ffeeddccbbaa99887766554433221100")};
164 BOOST_CHECK(g1.IsValid());
165 const auto err_s1 = codex32::Result{{a, c, g1}, 's'};
166 BOOST_CHECK_EQUAL(err_s1.error(), codex32::MISMATCH_K);
167
168 const auto g2 = codex32::Result{"ms", 3, "leet", 'g', ParseHex("ffeeddccbbaa99887766554433221100")};
169 BOOST_CHECK(g2.IsValid());
170 const auto err_s2 = codex32::Result{{a, c, g2}, 's'};
171 BOOST_CHECK_EQUAL(err_s2.error(), codex32::MISMATCH_ID);
172
173 const auto g3 = codex32::Result{"ms", 3, "cash", 'g', ParseHex("ffeeddccbbaa99887766554433221100ab")};
174 BOOST_CHECK(g3.IsValid());
175 const auto err_s3 = codex32::Result{{a, c, g3}, 's'};
176 BOOST_CHECK_EQUAL(err_s3.error(), codex32::MISMATCH_LENGTH);
177 }
178
179 BOOST_AUTO_TEST_CASE(codex32_bip93_vector_4)
180 {
181 const std::string seed = "ffeeddccbbaa99887766554433221100ffeeddccbbaa99887766554433221100";
182 const auto s = codex32::Result{"ms", 0, "leet", 's', ParseHex(seed)};
183 BOOST_CHECK(s.IsValid());
184 BOOST_CHECK_EQUAL(s.GetIdString(), "leet");
185 BOOST_CHECK_EQUAL(s.GetShareIndex(), 's');
186 BOOST_CHECK_EQUAL(s.GetK(), 0);
187 BOOST_CHECK_EQUAL(HexStr(s.GetPayload()), seed);
188 BOOST_CHECK_EQUAL(s.Encode(), "ms10leetsllhdmn9m42vcsamx24zrxgs3qrl7ahwvhw4fnzrhve25gvezzyqqtum9pgv99ycma");
189
190 std::vector<std::string> alternates = {
191 "ms10leetsllhdmn9m42vcsamx24zrxgs3qrl7ahwvhw4fnzrhve25gvezzyqqtum9pgv99ycma",
192 "ms10leetsllhdmn9m42vcsamx24zrxgs3qrl7ahwvhw4fnzrhve25gvezzyqpj82dp34u6lqtd",
193 "ms10leetsllhdmn9m42vcsamx24zrxgs3qrl7ahwvhw4fnzrhve25gvezzyqzsrs4pnh7jmpj5",
194 "ms10leetsllhdmn9m42vcsamx24zrxgs3qrl7ahwvhw4fnzrhve25gvezzyqrfcpap2w8dqezy",
195 "ms10leetsllhdmn9m42vcsamx24zrxgs3qrl7ahwvhw4fnzrhve25gvezzyqy5tdvphn6znrf0",
196 "ms10leetsllhdmn9m42vcsamx24zrxgs3qrl7ahwvhw4fnzrhve25gvezzyq9dsuypw2ragmel",
197 "ms10leetsllhdmn9m42vcsamx24zrxgs3qrl7ahwvhw4fnzrhve25gvezzyqx05xupvgp4v6qx",
198 "ms10leetsllhdmn9m42vcsamx24zrxgs3qrl7ahwvhw4fnzrhve25gvezzyq8k0h5p43c2hzsk",
199 "ms10leetsllhdmn9m42vcsamx24zrxgs3qrl7ahwvhw4fnzrhve25gvezzyqgum7hplmjtr8ks",
200 "ms10leetsllhdmn9m42vcsamx24zrxgs3qrl7ahwvhw4fnzrhve25gvezzyqf9q0lpxzt5clxq",
201 "ms10leetsllhdmn9m42vcsamx24zrxgs3qrl7ahwvhw4fnzrhve25gvezzyq28y48pyqfuu7le",
202 "ms10leetsllhdmn9m42vcsamx24zrxgs3qrl7ahwvhw4fnzrhve25gvezzyqt7ly0paesr8x0f",
203 "ms10leetsllhdmn9m42vcsamx24zrxgs3qrl7ahwvhw4fnzrhve25gvezzyqvrvg7pqydv5uyz",
204 "ms10leetsllhdmn9m42vcsamx24zrxgs3qrl7ahwvhw4fnzrhve25gvezzyqd6hekpea5n0y5j",
205 "ms10leetsllhdmn9m42vcsamx24zrxgs3qrl7ahwvhw4fnzrhve25gvezzyqwcnrwpmlkmt9dt",
206 "ms10leetsllhdmn9m42vcsamx24zrxgs3qrl7ahwvhw4fnzrhve25gvezzyq0pgjxpzx0ysaam",
207 };
208 for (const auto& alt : alternates) {
209 const auto s_alt = codex32::Result{alt};
210 BOOST_CHECK(s_alt.IsValid());
211 BOOST_CHECK_EQUAL(HexStr(s_alt.GetPayload()), seed);
212 }
213 }
214
215 BOOST_AUTO_TEST_CASE(codex32_bip93_vector_5)
216 {
217 const auto s = codex32::Result{"MS100C8VSM32ZXFGUHPCHTLUPZRY9X8GF2TVDW0S3JN54KHCE6MUA7LQPZYGSFJD6AN074RXVCEMLH8WU3TK925ACDEFGHJKLMNPQRSTUVWXY06FHPV80UNDVARHRAK"};
218 BOOST_CHECK(s.IsValid());
219 BOOST_CHECK_EQUAL(s.error(), codex32::OK);
220 BOOST_CHECK_EQUAL(s.GetIdString(), "0c8v");
221 BOOST_CHECK_EQUAL(s.GetShareIndex(), 's');
222 BOOST_CHECK_EQUAL(s.GetK(), 0);
223 BOOST_CHECK_EQUAL(HexStr(s.GetPayload()), "dc5423251cb87175ff8110c8531d0952d8d73e1194e95b5f19d6f9df7c01111104c9baecdfea8cccc677fb9ddc8aec5553b86e528bcadfdcc201c17c638c47e9");
224 }
225
226 BOOST_AUTO_TEST_CASE(codex32_errors)
227 {
228 const std::vector<codex32::Result> errs = {
229 codex32::Result("ms", 3, "cash", 's', ParseHex("ffeeddccbbaa99887766554433221100")),
230 // bad hrp
231 codex32::Result("bc", 3, "cash", 's', ParseHex("ffeeddccbbaa99887766554433221100")),
232 // bad ID len
233 codex32::Result("ms", 3, "cas", 's', ParseHex("ffeeddccbbaa99887766554433221100")),
234 codex32::Result("ms", 3, "cashcashcash", 's', ParseHex("ffeeddccbbaa99887766554433221100")),
235 codex32::Result("ms", 3, "", 's', ParseHex("ffeeddccbbaa99887766554433221100")),
236 // bad id char
237 codex32::Result("ms", 3, "bash", 's', ParseHex("ffeeddccbbaa99887766554433221100")),
238 // bad k
239 codex32::Result("ms", 1, "cash", 's', ParseHex("ffeeddccbbaa99887766554433221100")),
240 codex32::Result("ms", 10, "cash", 's', ParseHex("ffeeddccbbaa99887766554433221100")),
241 codex32::Result("ms", 100000, "cash", 's', ParseHex("ffeeddccbbaa99887766554433221100")),
242 // bad share idx
243 codex32::Result("ms", 100000, "cash", 'b', ParseHex("ffeeddccbbaa99887766554433221100")),
244 codex32::Result("ms", 100000, "cash", 'i', ParseHex("ffeeddccbbaa99887766554433221100")),
245 codex32::Result("ms", 100000, "cash", '1', ParseHex("ffeeddccbbaa99887766554433221100")),
246 codex32::Result("ms", 100000, "cash", 'o', ParseHex("ffeeddccbbaa99887766554433221100")),
247 codex32::Result("ms", 100000, "cash", ' ', ParseHex("ffeeddccbbaa99887766554433221100")),
248 };
249
250 BOOST_CHECK_EQUAL(errs[0].error(), codex32::OK);
251 BOOST_CHECK_EQUAL(errs[1].error(), codex32::INVALID_HRP);
252 BOOST_CHECK_EQUAL(errs[2].error(), codex32::INVALID_ID_LEN);
253 BOOST_CHECK_EQUAL(errs[3].error(), codex32::INVALID_ID_LEN);
254 BOOST_CHECK_EQUAL(errs[4].error(), codex32::INVALID_ID_LEN);
255 BOOST_CHECK_EQUAL(errs[5].error(), codex32::INVALID_ID_CHAR);
256 BOOST_CHECK_EQUAL(errs[6].error(), codex32::INVALID_K);
257 BOOST_CHECK_EQUAL(errs[7].error(), codex32::INVALID_K);
258 BOOST_CHECK_EQUAL(errs[8].error(), codex32::INVALID_K);
259 BOOST_CHECK_EQUAL(errs[9].error(), codex32::INVALID_SHARE_IDX);
260 BOOST_CHECK_EQUAL(errs[10].error(), codex32::INVALID_SHARE_IDX);
261 BOOST_CHECK_EQUAL(errs[11].error(), codex32::INVALID_SHARE_IDX);
262 BOOST_CHECK_EQUAL(errs[12].error(), codex32::INVALID_SHARE_IDX);
263 BOOST_CHECK_EQUAL(errs[13].error(), codex32::INVALID_SHARE_IDX);
264
265 }
266
267 BOOST_AUTO_TEST_CASE(codex32_bip93_invalid_1)
268 {
269 std::vector<std::string> bad_checksum = {
270 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxve740yyge2ghq",
271 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxve740yyge2ghp",
272 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxlk3yepcstwr",
273 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxx6pgnv7jnpcsp",
274 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxx0cpvr7n4geq",
275 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxm5252y7d3lr",
276 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxrd9sukzl05ej",
277 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxc55srw5jrm0",
278 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxgc7rwhtudwc",
279 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxx4gy22afwghvs",
280 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxme084q0vpht7pe0",
281 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxme084q0vpht7pew",
282 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxqyadsp3nywm8a",
283 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxzvg7ar4hgaejk",
284 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxcznau0advgxqe",
285 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxch3jrc6j5040j",
286 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx52gxl6ppv40mcv",
287 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx7g4g2nhhle8fk",
288 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx63m45uj8ss4x8",
289 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxy4r708q7kg65x",
290 };
291 for (const auto& bad : bad_checksum) {
292 auto res = codex32::Result{bad};
293 BOOST_CHECK_EQUAL(res.error(), codex32::BAD_CHECKSUM);
294 }
295 }
296
297 BOOST_AUTO_TEST_CASE(codex32_bip93_invalid_2)
298 {
299 std::vector<std::string> bad_checksum = {
300 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxurfvwmdcmymdufv",
301 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxcsyppjkd8lz4hx3",
302 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxu6hwvl5p0l9xf3c",
303 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxwqey9rfs6smenxa",
304 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxv70wkzrjr4ntqet",
305 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3hmlrmpa4zl0v",
306 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxrfggf88znkaup",
307 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxpt7l4aycv9qzj",
308 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxus27z9xtyxyw3",
309 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxcwm4re8fs78vn",
310 };
311 for (const auto& bad : bad_checksum) {
312 auto res = codex32::Result{bad};
313 BOOST_CHECK(res.error() == codex32::BAD_CHECKSUM || res.error() == codex32::INVALID_LENGTH);
314 }
315 }
316
317 BOOST_AUTO_TEST_CASE(codex32_bip93_invalid_3)
318 {
319 std::vector<std::string> bad_checksum = {
320 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxw0a4c70rfefn4",
321 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxk4pavy5n46nea",
322 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxx9lrwar5zwng4w",
323 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxr335l5tv88js3",
324 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxvu7q9nz8p7dj68v",
325 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxpq6k542scdxndq3",
326 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxkmfw6jm270mz6ej",
327 "ms12fauxxxxxxxxxxxxxxxxxxxxxxxxxxzhddxw99w7xws",
328 "ms12fauxxxxxxxxxxxxxxxxxxxxxxxxxxxx42cux6um92rz",
329 "ms12fauxxxxxxxxxxxxxxxxxxxxxxxxxxxxxarja5kqukdhy9",
330 "ms12fauxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxky0ua3ha84qk8",
331 "ms12fauxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx9eheesxadh2n2n9",
332 "ms12fauxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx9llwmgesfulcj2z",
333 "ms12fauxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx02ev7caq6n9fgkf",
334 };
335 for (const auto& bad : bad_checksum) {
336 auto res = codex32::Result{bad};
337 BOOST_CHECK_EQUAL(res.error(), codex32::INVALID_LENGTH);
338 }
339 }
340
341 BOOST_AUTO_TEST_CASE(codex32_bip93_invalid_hrp)
342 {
343 std::vector<std::string> bad_checksum = {
344 "0fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxuqxkk05lyf3x2",
345 "10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxuqxkk05lyf3x2",
346 "ms0fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxuqxkk05lyf3x2",
347 "m10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxuqxkk05lyf3x2",
348 "s10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxuqxkk05lyf3x2",
349 "0fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxhkd4f70m8lgws",
350 "10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxhkd4f70m8lgws",
351 "m10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxx8t28z74x8hs4l",
352 "s10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxh9d0fhnvfyx3x",
353 };
354 for (const auto& bad : bad_checksum) {
355 auto res = codex32::Result{bad};
356 BOOST_CHECK(res.error() == codex32::INVALID_HRP || res.error() == codex32::BECH32_DECODE);
357 }
358 }
359
360 BOOST_AUTO_TEST_CASE(codex32_bip93_invalid_case)
361 {
362 std::vector<std::string> bad_checksum = {
363 "Ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxuqxkk05lyf3x2",
364 "mS10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxuqxkk05lyf3x2",
365 "MS10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxuqxkk05lyf3x2",
366 "ms10FAUXsxxxxxxxxxxxxxxxxxxxxxxxxxxuqxkk05lyf3x2",
367 "ms10fauxSxxxxxxxxxxxxxxxxxxxxxxxxxxuqxkk05lyf3x2",
368 "ms10fauxsXXXXXXXXXXXXXXXXXXXXXXXXXXuqxkk05lyf3x2",
369 "ms10fauxsxxxxxxxxxxxxxxxxxxxxxxxxxxUQXKK05LYF3X2",
370 };
371 for (const auto& bad : bad_checksum) {
372 auto res = codex32::Result{bad};
373 BOOST_CHECK_EQUAL(res.error(), codex32::BECH32_DECODE);
374 }
375 }
376
377 BOOST_AUTO_TEST_SUITE_END()
378