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);
186 bigInt[bigInt.size() - 1] -= 1;
188 auto const boostBigInt = multiprecision_utils::toBoostMP(
191 auto const refAdd = boostBigInt + d;
193 auto const result = b58_fast::detail::inplace_bigint_add(
195 BEAST_EXPECT(result == TokenCodecErrc::success);
196 auto const foundAdd = multiprecision_utils::toBoostMP(bigInt);
197 BEAST_EXPECT(refAdd == foundAdd);
199 for (
int i = 0; i < iters; ++i)
205 auto const boostBigInt = multiprecision_utils::toBoostMP(
208 auto const refAdd = boostBigInt + d;
210 auto const result = b58_fast::detail::inplace_bigint_add(
212 BEAST_EXPECT(result == TokenCodecErrc::overflowAdd);
213 auto const foundAdd = multiprecision_utils::toBoostMP(bigInt);
214 BEAST_EXPECT(refAdd != foundAdd);
216 for (
int i = 0; i < iters; ++i)
219 auto bigInt = multiprecision_utils::randomBigInt( 2);
222 bigInt[bigInt.size() - 1] = 0;
223 auto const boostBigInt = multiprecision_utils::toBoostMP(
226 auto const refMul = boostBigInt * d;
228 auto const result = b58_fast::detail::inplace_bigint_mul(
230 BEAST_EXPECT(result == TokenCodecErrc::success);
231 auto const foundMul = multiprecision_utils::toBoostMP(bigInt);
232 BEAST_EXPECT(refMul == foundMul);
234 for (
int i = 0; i < iters; ++i)
239 auto const boostBigInt = multiprecision_utils::toBoostMP(
242 auto const refMul = boostBigInt * d;
244 auto const result = b58_fast::detail::inplace_bigint_mul(
246 BEAST_EXPECT(result == TokenCodecErrc::inputTooLarge);
247 auto const foundMul = multiprecision_utils::toBoostMP(bigInt);
248 BEAST_EXPECT(refMul != foundMul);
255 testcase(
"fast_matches_ref");
262 for (
int i = 0; i < 2; ++i)
267 auto const r = xrpl::b58_fast::detail::b256_to_b58_be(b256Data, outBuf);
269 b58Result[i] = r.value();
275 b256Data.data(), b256Data.size(), tmpBuf.data(), tmpBuf.size());
276 BEAST_EXPECT(s.
size());
277 b58Result[i] = outBuf.subspan(0, s.
size());
281 if (BEAST_EXPECT(b58Result[0].
size() == b58Result[1].
size()))
286 printAsChar(b58Result[0], b58Result[1]);
290 for (
int i = 0; i < 2; ++i)
296 b58Result[i].
data(), b58Result[i].
data() + b58Result[i].
size());
297 auto const r = xrpl::b58_fast::detail::b58_to_b256_be(in, outBuf);
299 b256Result[i] = r.value();
305 BEAST_EXPECT(s.
size());
306 b256Result[i] = outBuf.subspan(0, s.
size());
311 if (BEAST_EXPECT(b256Result[0].
size() == b256Result[1].
size()))
317 printAsInt(b256Result[0], b256Result[1]);
329 for (
int i = 0; i < 2; ++i)
334 auto const r = xrpl::b58_fast::encodeBase58Token(tokType, b256Data, outBuf);
336 b58Result[i] = r.value();
342 BEAST_EXPECT(s.
size());
343 b58Result[i] = outBuf.subspan(0, s.
size());
347 if (BEAST_EXPECT(b58Result[0].
size() == b58Result[1].
size()))
352 printAsChar(b58Result[0], b58Result[1]);
356 for (
int i = 0; i < 2; ++i)
362 b58Result[i].
data(), b58Result[i].
data() + b58Result[i].
size());
363 auto const r = xrpl::b58_fast::decodeBase58Token(tokType, in, outBuf);
365 b256Result[i] = r.value();
371 BEAST_EXPECT(s.
size());
372 b256Result[i] = outBuf.subspan(0, s.
size());
377 if (BEAST_EXPECT(b256Result[0].
size() == b256Result[1].
size()))
383 printAsInt(b256Result[0], b256Result[1]);
389 testRawEncode(b256Data);
390 testTokenEncode(tokType, b256Data);
395 for (
int i = 0; i < numTokenTypeIndexes; ++i)
398 auto const [tokType, tokSize] = tokenTypeAndSize(i);
399 for (
int d = 0; d <= 255; ++d)
401 memset(b256DataBuf.data(), d, tokSize);
402 testIt(tokType,
std::span(b256DataBuf.data(), tokSize));
408 for (
int i = 0; i < iters; ++i)
411 auto const [tokType, b256Data] = randomB256TestData(b256DataBuf);
412 testIt(tokType, b256Data);
419 testMultiprecision();
420 testFastMatchesRef();
424BEAST_DEFINE_TESTSUITE(base58, basics,
xrpl);
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.
int run(int argc, char **argv)
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.