22#include <xrpl/beast/unit_test.h>
23#include <xrpl/protocol/detail/b58_utils.h>
24#include <xrpl/protocol/tokens.h>
26#include <boost/multiprecision/cpp_int.hpp>
27#include <boost/random.hpp>
39[[nodiscard]]
inline auto
49constexpr 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";
137namespace multiprecision_utils {
139boost::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)
173 testcase(
"b58_multiprecision");
175 using namespace boost::multiprecision;
178 auto eng = randEngine();
181 for (
int i = 0; i < iters; ++i)
186 auto bigInt = multiprecision_utils::randomBigInt();
187 auto const boostBigInt = multiprecision_utils::toBoostMP(
190 auto const refDiv = boostBigInt / d;
191 auto const refMod = boostBigInt % d;
193 auto const mod = b58_fast::detail::inplace_bigint_div_rem(
195 auto const foundDiv = multiprecision_utils::toBoostMP(bigInt);
197 BEAST_EXPECT(foundDiv == refDiv);
199 for (
int i = 0; i < iters; ++i)
202 auto bigInt = multiprecision_utils::randomBigInt( 2);
203 if (bigInt[bigInt.size() - 1] ==
206 bigInt[bigInt.size() - 1] -= 1;
208 auto const boostBigInt = multiprecision_utils::toBoostMP(
211 auto const refAdd = boostBigInt + d;
213 auto const result = b58_fast::detail::inplace_bigint_add(
215 BEAST_EXPECT(result == TokenCodecErrc::success);
216 auto const foundAdd = multiprecision_utils::toBoostMP(bigInt);
217 BEAST_EXPECT(refAdd == foundAdd);
219 for (
int i = 0; i < iters; ++i)
226 auto const boostBigInt = multiprecision_utils::toBoostMP(
229 auto const refAdd = boostBigInt + d;
231 auto const result = b58_fast::detail::inplace_bigint_add(
233 BEAST_EXPECT(result == TokenCodecErrc::overflowAdd);
234 auto const foundAdd = multiprecision_utils::toBoostMP(bigInt);
235 BEAST_EXPECT(refAdd != foundAdd);
237 for (
int i = 0; i < iters; ++i)
240 auto bigInt = multiprecision_utils::randomBigInt( 2);
243 bigInt[bigInt.size() - 1] = 0;
244 auto const boostBigInt = multiprecision_utils::toBoostMP(
247 auto const refMul = boostBigInt * d;
249 auto const result = b58_fast::detail::inplace_bigint_mul(
251 BEAST_EXPECT(result == TokenCodecErrc::success);
252 auto const foundMul = multiprecision_utils::toBoostMP(bigInt);
253 BEAST_EXPECT(refMul == foundMul);
255 for (
int i = 0; i < iters; ++i)
261 auto const boostBigInt = multiprecision_utils::toBoostMP(
264 auto const refMul = boostBigInt * d;
266 auto const result = b58_fast::detail::inplace_bigint_mul(
268 BEAST_EXPECT(result == TokenCodecErrc::inputTooLarge);
269 auto const foundMul = multiprecision_utils::toBoostMP(bigInt);
270 BEAST_EXPECT(refMul != foundMul);
277 testcase(
"fast_matches_ref");
284 for (
int i = 0; i < 2; ++i)
289 auto const r = ripple::b58_fast::detail::b256_to_b58_be(
292 b58Result[i] = r.value();
302 BEAST_EXPECT(s.
size());
303 b58Result[i] = outBuf.subspan(0, s.
size());
307 if (BEAST_EXPECT(b58Result[0].
size() == b58Result[1].
size()))
313 b58Result[0].
size()) == 0))
315 printAsChar(b58Result[0], b58Result[1]);
319 for (
int i = 0; i < 2; ++i)
322 b256ResultBuf[i].
data(), b256ResultBuf[i].
size()};
327 b58Result[i].
data() + b58Result[i].
size());
329 ripple::b58_fast::detail::b58_to_b256_be(in, outBuf);
331 b256Result[i] = r.value();
336 b58Result[i].
begin(), b58Result[i].
end());
339 BEAST_EXPECT(s.
size());
340 b256Result[i] = outBuf.subspan(0, s.
size());
345 if (BEAST_EXPECT(b256Result[0].
size() == b256Result[1].
size()))
349 b256Result[0].
data(),
350 b256Result[1].
data(),
351 b256Result[0].
size()) == 0))
353 printAsInt(b256Result[0], b256Result[1]);
365 for (
int i = 0; i < 2; ++i)
368 b58ResultBuf[i].
data(), b58ResultBuf[i].
size()};
371 auto const r = ripple::b58_fast::encodeBase58Token(
372 tokType, b256Data, outBuf);
374 b58Result[i] = r.value();
379 tokType, b256Data.data(), b256Data.size());
380 BEAST_EXPECT(s.
size());
381 b58Result[i] = outBuf.subspan(0, s.
size());
385 if (BEAST_EXPECT(b58Result[0].
size() == b58Result[1].
size()))
391 b58Result[0].
size()) == 0))
393 printAsChar(b58Result[0], b58Result[1]);
397 for (
int i = 0; i < 2; ++i)
400 b256ResultBuf[i].
data(), b256ResultBuf[i].
size()};
405 b58Result[i].
data() + b58Result[i].
size());
406 auto const r = ripple::b58_fast::decodeBase58Token(
407 tokType, in, outBuf);
409 b256Result[i] = r.value();
414 b58Result[i].
begin(), b58Result[i].
end());
417 BEAST_EXPECT(s.
size());
418 b256Result[i] = outBuf.subspan(0, s.
size());
423 if (BEAST_EXPECT(b256Result[0].
size() == b256Result[1].
size()))
427 b256Result[0].
data(),
428 b256Result[1].
data(),
429 b256Result[0].
size()) == 0))
431 printAsInt(b256Result[0], b256Result[1]);
438 testRawEncode(b256Data);
439 testTokenEncode(tokType, b256Data);
444 for (
int i = 0; i < numTokenTypeIndexes; ++i)
447 auto const [tokType, tokSize] = tokenTypeAndSize(i);
448 for (
int d = 0; d <= 255; ++d)
457 for (
int i = 0; i < iters; ++i)
460 auto const [tokType, b256Data] = randomB256TestData(b256DataBuf);
461 testIt(tokType, b256Data);
468 testMultiprecision();
469 testFastMatchesRef();
473BEAST_DEFINE_TESTSUITE(base58, basics,
ripple);
std::string decodeBase58(std::string const &s)
std::string encodeBase58(void const *message, std::size_t size, void *temp, std::size_t temp_size)
std::string encodeBase58Token(TokenType type, void const *token, std::size_t size)
std::string decodeBase58Token(std::string const &s, TokenType type)
auto const data
General field definitions, or fields used in multiple transaction namespaces.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
int run(int argc, char **argv)