22 #include <ripple/beast/unit_test.h>
23 #include <ripple/protocol/impl/b58_utils.h>
24 #include <ripple/protocol/tokens.h>
26 #include <boost/multiprecision/cpp_int.hpp>
27 #include <boost/random.hpp>
39 [[nodiscard]]
inline auto
49 constexpr
int numTokenTypeIndexes = 9;
51 [[nodiscard]]
inline auto
54 assert(i < numTokenTypeIndexes);
79 "Invalid token selection passed to tokenTypeAndSize() "
84 [[nodiscard]]
inline auto
88 auto& rng = randEngine();
90 return tokenTypeAndSize(d(rng));
94 [[nodiscard]]
inline auto
98 auto& rng = randEngine();
100 auto [tokType, tokSize] = randomTokenTypeAndSize();
101 std::generate(d.begin(), d.begin() + tokSize, [&] { return dist(rng); });
102 return {tokType, d.subspan(0, tokSize)};
114 auto sa = asString(a);
115 auto sb = asString(b);
116 std::cerr <<
"\n\n" << sa <<
"\n" << sb <<
"\n";
130 auto sa = asString(a);
131 auto sb = asString(b);
132 std::cerr <<
"\n\n" << sa <<
"\n" << sb <<
"\n";
137 namespace multiprecision_utils {
139 boost::multiprecision::checked_uint512_t
142 boost::multiprecision::checked_uint512_t mbp = 0;
143 for (
auto i =
in.rbegin(); i !=
in.rend(); ++i)
154 auto eng = randEngine();
157 auto const numCoeff = numCoeffDist(eng);
160 for (
int i = 0; i < numCoeff; ++i)
168 class base58_test :
public beast::unit_test::suite
173 testcase(
"b58_multiprecision");
175 using namespace boost::multiprecision;
178 auto eng = randEngine();
180 for (
int i = 0; i < iters; ++i)
185 auto bigInt = multiprecision_utils::randomBigInt();
186 auto const boostBigInt = multiprecision_utils::toBoostMP(
189 auto const refDiv = boostBigInt / d;
190 auto const refMod = boostBigInt % d;
192 auto const mod = b58_fast::detail::inplace_bigint_div_rem(
194 auto const foundDiv = multiprecision_utils::toBoostMP(bigInt);
196 BEAST_EXPECT(foundDiv == refDiv);
198 for (
int i = 0; i < iters; ++i)
201 auto bigInt = multiprecision_utils::randomBigInt( 2);
202 if (bigInt[bigInt.size() - 1] ==
205 bigInt[bigInt.size() - 1] -= 1;
207 auto const boostBigInt = multiprecision_utils::toBoostMP(
210 auto const refAdd = boostBigInt + d;
212 b58_fast::detail::inplace_bigint_add(
214 auto const foundAdd = multiprecision_utils::toBoostMP(bigInt);
215 BEAST_EXPECT(refAdd == foundAdd);
217 for (
int i = 0; i < iters; ++i)
220 auto bigInt = multiprecision_utils::randomBigInt( 2);
223 bigInt[bigInt.size() - 1] = 0;
224 auto const boostBigInt = multiprecision_utils::toBoostMP(
227 auto const refMul = boostBigInt * d;
229 b58_fast::detail::inplace_bigint_mul(
231 auto const foundMul = multiprecision_utils::toBoostMP(bigInt);
232 BEAST_EXPECT(refMul == foundMul);
239 testcase(
"fast_matches_ref");
246 for (
int i = 0; i < 2; ++i)
251 auto const r = ripple::b58_fast::detail::b256_to_b58_be(
254 b58Result[i] = r.value();
264 BEAST_EXPECT(s.
size());
265 b58Result[i] = outBuf.subspan(0, s.
size());
269 if (BEAST_EXPECT(b58Result[0].
size() == b58Result[1].
size()))
275 b58Result[0].
size()) == 0))
277 printAsChar(b58Result[0], b58Result[1]);
281 for (
int i = 0; i < 2; ++i)
284 b256ResultBuf[i].
data(), b256ResultBuf[i].
size()};
289 b58Result[i].
data() + b58Result[i].
size());
291 ripple::b58_fast::detail::b58_to_b256_be(in, outBuf);
293 b256Result[i] = r.value();
298 b58Result[i].
begin(), b58Result[i].
end());
301 BEAST_EXPECT(s.
size());
302 b256Result[i] = outBuf.subspan(0, s.
size());
307 if (BEAST_EXPECT(b256Result[0].
size() == b256Result[1].
size()))
311 b256Result[0].
data(),
312 b256Result[1].
data(),
313 b256Result[0].
size()) == 0))
315 printAsInt(b256Result[0], b256Result[1]);
327 for (
int i = 0; i < 2; ++i)
330 b58ResultBuf[i].
data(), b58ResultBuf[i].
size()};
333 auto const r = ripple::b58_fast::encodeBase58Token(
334 tokType, b256Data, outBuf);
336 b58Result[i] = r.value();
341 tokType, b256Data.data(), b256Data.size());
342 BEAST_EXPECT(s.
size());
343 b58Result[i] = outBuf.subspan(0, s.
size());
347 if (BEAST_EXPECT(b58Result[0].
size() == b58Result[1].
size()))
353 b58Result[0].
size()) == 0))
355 printAsChar(b58Result[0], b58Result[1]);
359 for (
int i = 0; i < 2; ++i)
362 b256ResultBuf[i].
data(), b256ResultBuf[i].
size()};
367 b58Result[i].
data() + b58Result[i].
size());
368 auto const r = ripple::b58_fast::decodeBase58Token(
369 tokType, in, outBuf);
371 b256Result[i] = r.value();
376 b58Result[i].
begin(), b58Result[i].
end());
379 BEAST_EXPECT(s.
size());
380 b256Result[i] = outBuf.subspan(0, s.
size());
385 if (BEAST_EXPECT(b256Result[0].
size() == b256Result[1].
size()))
389 b256Result[0].
data(),
390 b256Result[1].
data(),
391 b256Result[0].
size()) == 0))
393 printAsInt(b256Result[0], b256Result[1]);
400 testRawEncode(b256Data);
401 testTokenEncode(tokType, b256Data);
406 for (
int i = 0; i < numTokenTypeIndexes; ++i)
409 auto const [tokType, tokSize] = tokenTypeAndSize(i);
410 for (
int d = 0; d <= 255; ++d)
419 for (
int i = 0; i < iters; ++i)
422 auto const [tokType, b256Data] = randomB256TestData(b256DataBuf);
423 testIt(tokType, b256Data);
430 testMultiprecision();
431 testFastMatchesRef();