3#include <xrpl/beast/unit_test.h>
4#include <xrpl/protocol/detail/b58_utils.h>
5#include <xrpl/protocol/tokens.h>
7#include <boost/multiprecision/cpp_int.hpp>
8#include <boost/random.hpp>
20[[nodiscard]]
inline auto
30constexpr int numTokenTypeIndexes = 9;
32[[nodiscard]]
inline auto
35 assert(i < numTokenTypeIndexes);
60 "Invalid token selection passed to tokenTypeAndSize() "
65[[nodiscard]]
inline auto
69 auto& rng = randEngine();
71 return tokenTypeAndSize(d(rng));
75[[nodiscard]]
inline auto
79 auto& rng = randEngine();
81 auto [tokType, tokSize] = randomTokenTypeAndSize();
82 std::generate(d.begin(), d.begin() + tokSize, [&] { return dist(rng); });
83 return {tokType, d.subspan(0, tokSize)};
95 auto sa = asString(a);
96 auto sb = asString(b);
97 std::cerr <<
"\n\n" << sa <<
"\n" << sb <<
"\n";
111 auto sa = asString(a);
112 auto sb = asString(b);
113 std::cerr <<
"\n\n" << sa <<
"\n" << sb <<
"\n";
118namespace multiprecision_utils {
120boost::multiprecision::checked_uint512_t
123 boost::multiprecision::checked_uint512_t mbp = 0;
124 for (
auto i =
in.rbegin(); i !=
in.rend(); ++i)
135 auto eng = randEngine();
138 auto const numCoeff = numCoeffDist(eng);
141 for (
int i = 0; i < numCoeff; ++i)
154 testcase(
"b58_multiprecision");
156 using namespace boost::multiprecision;
159 auto eng = randEngine();
162 for (
int i = 0; i < iters; ++i)
167 auto bigInt = multiprecision_utils::randomBigInt();
168 auto const boostBigInt = multiprecision_utils::toBoostMP(
171 auto const refDiv = boostBigInt / d;
172 auto const refMod = boostBigInt % d;
174 auto const mod = b58_fast::detail::inplace_bigint_div_rem(
176 auto const foundDiv = multiprecision_utils::toBoostMP(bigInt);
178 BEAST_EXPECT(foundDiv == refDiv);
180 for (
int i = 0; i < iters; ++i)
183 auto bigInt = multiprecision_utils::randomBigInt( 2);
184 if (bigInt[bigInt.size() - 1] ==
187 bigInt[bigInt.size() - 1] -= 1;
189 auto const boostBigInt = multiprecision_utils::toBoostMP(
192 auto const refAdd = boostBigInt + d;
194 auto const result = b58_fast::detail::inplace_bigint_add(
196 BEAST_EXPECT(result == TokenCodecErrc::success);
197 auto const foundAdd = multiprecision_utils::toBoostMP(bigInt);
198 BEAST_EXPECT(refAdd == foundAdd);
200 for (
int i = 0; i < iters; ++i)
207 auto const boostBigInt = multiprecision_utils::toBoostMP(
210 auto const refAdd = boostBigInt + d;
212 auto const result = b58_fast::detail::inplace_bigint_add(
214 BEAST_EXPECT(result == TokenCodecErrc::overflowAdd);
215 auto const foundAdd = multiprecision_utils::toBoostMP(bigInt);
216 BEAST_EXPECT(refAdd != foundAdd);
218 for (
int i = 0; i < iters; ++i)
221 auto bigInt = multiprecision_utils::randomBigInt( 2);
224 bigInt[bigInt.size() - 1] = 0;
225 auto const boostBigInt = multiprecision_utils::toBoostMP(
228 auto const refMul = boostBigInt * d;
230 auto const result = b58_fast::detail::inplace_bigint_mul(
232 BEAST_EXPECT(result == TokenCodecErrc::success);
233 auto const foundMul = multiprecision_utils::toBoostMP(bigInt);
234 BEAST_EXPECT(refMul == foundMul);
236 for (
int i = 0; i < iters; ++i)
242 auto const boostBigInt = multiprecision_utils::toBoostMP(
245 auto const refMul = boostBigInt * d;
247 auto const result = b58_fast::detail::inplace_bigint_mul(
249 BEAST_EXPECT(result == TokenCodecErrc::inputTooLarge);
250 auto const foundMul = multiprecision_utils::toBoostMP(bigInt);
251 BEAST_EXPECT(refMul != foundMul);
258 testcase(
"fast_matches_ref");
265 for (
int i = 0; i < 2; ++i)
270 auto const r = ripple::b58_fast::detail::b256_to_b58_be(
273 b58Result[i] = r.value();
283 BEAST_EXPECT(s.
size());
284 b58Result[i] = outBuf.subspan(0, s.
size());
288 if (BEAST_EXPECT(b58Result[0].
size() == b58Result[1].
size()))
294 b58Result[0].
size()) == 0))
296 printAsChar(b58Result[0], b58Result[1]);
300 for (
int i = 0; i < 2; ++i)
303 b256ResultBuf[i].
data(), b256ResultBuf[i].
size()};
308 b58Result[i].
data() + b58Result[i].
size());
310 ripple::b58_fast::detail::b58_to_b256_be(in, outBuf);
312 b256Result[i] = r.value();
317 b58Result[i].
begin(), b58Result[i].
end());
320 BEAST_EXPECT(s.
size());
321 b256Result[i] = outBuf.subspan(0, s.
size());
326 if (BEAST_EXPECT(b256Result[0].
size() == b256Result[1].
size()))
330 b256Result[0].
data(),
331 b256Result[1].
data(),
332 b256Result[0].
size()) == 0))
334 printAsInt(b256Result[0], b256Result[1]);
346 for (
int i = 0; i < 2; ++i)
349 b58ResultBuf[i].
data(), b58ResultBuf[i].
size()};
352 auto const r = ripple::b58_fast::encodeBase58Token(
353 tokType, b256Data, outBuf);
355 b58Result[i] = r.value();
360 tokType, b256Data.data(), b256Data.size());
361 BEAST_EXPECT(s.
size());
362 b58Result[i] = outBuf.subspan(0, s.
size());
366 if (BEAST_EXPECT(b58Result[0].
size() == b58Result[1].
size()))
372 b58Result[0].
size()) == 0))
374 printAsChar(b58Result[0], b58Result[1]);
378 for (
int i = 0; i < 2; ++i)
381 b256ResultBuf[i].
data(), b256ResultBuf[i].
size()};
386 b58Result[i].
data() + b58Result[i].
size());
387 auto const r = ripple::b58_fast::decodeBase58Token(
388 tokType, in, outBuf);
390 b256Result[i] = r.value();
395 b58Result[i].
begin(), b58Result[i].
end());
398 BEAST_EXPECT(s.
size());
399 b256Result[i] = outBuf.subspan(0, s.
size());
404 if (BEAST_EXPECT(b256Result[0].
size() == b256Result[1].
size()))
408 b256Result[0].
data(),
409 b256Result[1].
data(),
410 b256Result[0].
size()) == 0))
412 printAsInt(b256Result[0], b256Result[1]);
419 testRawEncode(b256Data);
420 testTokenEncode(tokType, b256Data);
425 for (
int i = 0; i < numTokenTypeIndexes; ++i)
428 auto const [tokType, tokSize] = tokenTypeAndSize(i);
429 for (
int d = 0; d <= 255; ++d)
438 for (
int i = 0; i < iters; ++i)
441 auto const [tokType, b256Data] = randomB256TestData(b256DataBuf);
442 testIt(tokType, b256Data);
449 testMultiprecision();
450 testFastMatchesRef();
454BEAST_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)