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
78 auto& rng = randEngine();
80 auto [tokType, tokSize] = randomTokenTypeAndSize();
81 std::generate(d.begin(), d.begin() + tokSize, [&] { return dist(rng); });
82 return {tokType, d.subspan(0, tokSize)};
94 auto sa = asString(a);
95 auto sb = asString(b);
96 std::cerr <<
"\n\n" << sa <<
"\n" << sb <<
"\n";
110 auto sa = asString(a);
111 auto sb = asString(b);
112 std::cerr <<
"\n\n" << sa <<
"\n" << sb <<
"\n";
117namespace multiprecision_utils {
119boost::multiprecision::checked_uint512_t
122 boost::multiprecision::checked_uint512_t mbp = 0;
123 for (
auto i =
in.rbegin(); i !=
in.rend(); ++i)
134 auto eng = randEngine();
137 auto const numCoeff = numCoeffDist(eng);
140 for (
int i = 0; i < numCoeff; ++i)
153 testcase(
"b58_multiprecision");
155 using namespace boost::multiprecision;
158 auto eng = randEngine();
161 for (
int i = 0; i < iters; ++i)
166 auto bigInt = multiprecision_utils::randomBigInt();
167 auto const boostBigInt =
170 auto const refDiv = boostBigInt / d;
171 auto const refMod = boostBigInt % d;
174 b58_fast::detail::inplace_bigint_div_rem(
std::span<uint64_t>(bigInt.data(), bigInt.size()), d);
175 auto const foundDiv = multiprecision_utils::toBoostMP(bigInt);
177 BEAST_EXPECT(foundDiv == refDiv);
179 for (
int i = 0; i < iters; ++i)
182 auto bigInt = multiprecision_utils::randomBigInt( 2);
185 bigInt[bigInt.size() - 1] -= 1;
187 auto const boostBigInt =
190 auto const refAdd = boostBigInt + d;
193 b58_fast::detail::inplace_bigint_add(
std::span<uint64_t>(bigInt.data(), bigInt.size()), d);
194 BEAST_EXPECT(result == TokenCodecErrc::success);
195 auto const foundAdd = multiprecision_utils::toBoostMP(bigInt);
196 BEAST_EXPECT(refAdd == foundAdd);
198 for (
int i = 0; i < iters; ++i)
204 auto const boostBigInt =
207 auto const refAdd = boostBigInt + d;
210 b58_fast::detail::inplace_bigint_add(
std::span<uint64_t>(bigInt.data(), bigInt.size()), d);
211 BEAST_EXPECT(result == TokenCodecErrc::overflowAdd);
212 auto const foundAdd = multiprecision_utils::toBoostMP(bigInt);
213 BEAST_EXPECT(refAdd != foundAdd);
215 for (
int i = 0; i < iters; ++i)
218 auto bigInt = multiprecision_utils::randomBigInt( 2);
221 bigInt[bigInt.size() - 1] = 0;
222 auto const boostBigInt =
225 auto const refMul = boostBigInt * d;
228 b58_fast::detail::inplace_bigint_mul(
std::span<uint64_t>(bigInt.data(), bigInt.size()), d);
229 BEAST_EXPECT(result == TokenCodecErrc::success);
230 auto const foundMul = multiprecision_utils::toBoostMP(bigInt);
231 BEAST_EXPECT(refMul == foundMul);
233 for (
int i = 0; i < iters; ++i)
238 auto const boostBigInt =
241 auto const refMul = boostBigInt * d;
244 b58_fast::detail::inplace_bigint_mul(
std::span<uint64_t>(bigInt.data(), bigInt.size()), d);
245 BEAST_EXPECT(result == TokenCodecErrc::inputTooLarge);
246 auto const foundMul = multiprecision_utils::toBoostMP(bigInt);
247 BEAST_EXPECT(refMul != foundMul);
254 testcase(
"fast_matches_ref");
261 for (
int i = 0; i < 2; ++i)
266 auto const r = xrpl::b58_fast::detail::b256_to_b58_be(b256Data, outBuf);
268 b58Result[i] = r.value();
274 b256Data.data(), b256Data.size(), tmpBuf.
data(), tmpBuf.
size());
275 BEAST_EXPECT(s.
size());
276 b58Result[i] = outBuf.subspan(0, s.
size());
280 if (BEAST_EXPECT(b58Result[0].
size() == b58Result[1].
size()))
282 if (!BEAST_EXPECT(
memcmp(b58Result[0].
data(), b58Result[1].
data(), b58Result[0].
size()) == 0))
284 printAsChar(b58Result[0], b58Result[1]);
288 for (
int i = 0; i < 2; ++i)
294 auto const r = xrpl::b58_fast::detail::b58_to_b256_be(in, outBuf);
296 b256Result[i] = r.value();
302 BEAST_EXPECT(s.
size());
303 b256Result[i] = outBuf.subspan(0, s.
size());
308 if (BEAST_EXPECT(b256Result[0].
size() == b256Result[1].
size()))
310 if (!BEAST_EXPECT(
memcmp(b256Result[0].
data(), b256Result[1].
data(), b256Result[0].
size()) == 0))
312 printAsInt(b256Result[0], b256Result[1]);
323 for (
int i = 0; i < 2; ++i)
328 auto const r = xrpl::b58_fast::encodeBase58Token(tokType, b256Data, outBuf);
330 b58Result[i] = r.value();
335 BEAST_EXPECT(s.
size());
336 b58Result[i] = outBuf.subspan(0, s.
size());
340 if (BEAST_EXPECT(b58Result[0].
size() == b58Result[1].
size()))
342 if (!BEAST_EXPECT(
memcmp(b58Result[0].
data(), b58Result[1].
data(), b58Result[0].
size()) == 0))
344 printAsChar(b58Result[0], b58Result[1]);
348 for (
int i = 0; i < 2; ++i)
354 auto const r = xrpl::b58_fast::decodeBase58Token(tokType, in, outBuf);
356 b256Result[i] = r.value();
362 BEAST_EXPECT(s.
size());
363 b256Result[i] = outBuf.subspan(0, s.
size());
368 if (BEAST_EXPECT(b256Result[0].
size() == b256Result[1].
size()))
370 if (!BEAST_EXPECT(
memcmp(b256Result[0].
data(), b256Result[1].
data(), b256Result[0].
size()) == 0))
372 printAsInt(b256Result[0], b256Result[1]);
378 testRawEncode(b256Data);
379 testTokenEncode(tokType, b256Data);
384 for (
int i = 0; i < numTokenTypeIndexes; ++i)
387 auto const [tokType, tokSize] = tokenTypeAndSize(i);
388 for (
int d = 0; d <= 255; ++d)
397 for (
int i = 0; i < iters; ++i)
400 auto const [tokType, b256Data] = randomB256TestData(b256DataBuf);
401 testIt(tokType, b256Data);
408 testMultiprecision();
409 testFastMatchesRef();
413BEAST_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.