28#include <xrpl/basics/Expected.h> 
   29#include <xrpl/basics/safe_cast.h> 
   30#include <xrpl/beast/utility/instrumentation.h> 
   31#include <xrpl/protocol/detail/b58_utils.h> 
   32#include <xrpl/protocol/detail/token_errors.h> 
   33#include <xrpl/protocol/digest.h> 
   34#include <xrpl/protocol/tokens.h> 
   36#include <boost/container/small_vector.hpp> 
   37#include <boost/endian/conversion.hpp> 
  143    "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz";
 
  154template <
class Hasher>
 
  155static typename Hasher::result_type
 
  160    return static_cast<typename Hasher::result_type
>(h);
 
 
  168static typename Hasher::result_type
 
  171    return digest<Hasher>(v.
data(), v.
size());
 
 
  175template <
class Hasher, 
class... Args>
 
  176static typename Hasher::result_type
 
  179    return digest<Hasher>(digest<Hasher>(args...));
 
 
  194    auto const h = digest2<sha256_hasher>(message, size);
 
 
  202    return b58_fast::encodeBase58Token(type, token, size);
 
 
  212    return b58_fast::decodeBase58Token(s, type);
 
 
  229    auto pbegin = 
reinterpret_cast<unsigned char const*
>(message);
 
  230    auto const pend = pbegin + size;
 
  234    while (pbegin != pend && *pbegin == 0)
 
  240    auto const b58begin = 
reinterpret_cast<unsigned char*
>(temp);
 
  241    auto const b58end = b58begin + temp_size;
 
  245    while (pbegin != pend)
 
  249        for (
auto iter = b58end; iter != b58begin; --iter)
 
  251            carry += 256 * (iter[-1]);
 
  252            iter[-1] = carry % 58;
 
  256            carry == 0, 
"ripple::b58_ref::detail::encodeBase58 : zero carry");
 
  261    auto iter = b58begin;
 
  262    while (iter != b58end && *iter == 0)
 
  267    str.
reserve(zeroes + (b58end - iter));
 
  269    while (iter != b58end)
 
 
  277    auto psz = 
reinterpret_cast<unsigned char const*
>(s.
c_str());
 
  278    auto remain = s.
size();
 
  300        for (
auto iter = b256.
rbegin(); iter != b256.
rend(); ++iter)
 
  307            carry == 0, 
"ripple::b58_ref::detail::decodeBase58 : zero carry");
 
  313        b256.
begin(), b256.
end(), [](
unsigned char c) { return c != 0; });
 
  316    result.
assign(zeroes, 0x00);
 
  317    while (iter != b256.
end())
 
 
  328    auto const expanded = 1 + size + 4;
 
  333    auto const bufsize = expanded * 3;
 
  335    boost::container::small_vector<std::uint8_t, 1024> buf(bufsize);
 
  339    buf[0] = safe_cast<std::underlying_type_t<TokenType>>(type);
 
  342    checksum(buf.data() + 1 + size, buf.data(), 1 + size);
 
  345        buf.data(), expanded, buf.data() + expanded, bufsize - expanded);
 
 
  358    if (type != safe_cast<TokenType>(
static_cast<std::uint8_t>(ret[0])))
 
 
  378B58Result<std::span<std::uint8_t>>
 
  383    if (input.
size() > 38)
 
  385        return Unexpected(TokenCodecErrc::inputTooLarge);
 
  388    auto count_leading_zeros =
 
  391        for (
auto const& c : col)
 
  402    auto const input_zeros = count_leading_zeros(input);
 
  403    input = input.
subspan(input_zeros);
 
  412        for (
int i = 0; i < base_2_64_coeff_buf.size(); ++i)
 
  414            if (i * 8 >= input.
size())
 
  418            auto const src_i_end = input.
size() - i * 8;
 
  422                    &base_2_64_coeff_buf[num_coeff], &input[src_i_end - 8], 8);
 
  423                boost::endian::big_to_native_inplace(
 
  424                    base_2_64_coeff_buf[num_coeff]);
 
  429                for (
int bi = 0; bi < src_i_end; ++bi)
 
  434                base_2_64_coeff_buf[num_coeff] = be;
 
  438        return std::span(base_2_64_coeff_buf.data(), num_coeff);
 
  448    while (cur_2_64_end > 0)
 
  450        base_58_10_coeff[num_58_10_coeffs] =
 
  451            ripple::b58_fast::detail::inplace_bigint_div_rem(
 
  452                base_2_64_coeff.
subspan(0, cur_2_64_end), B_58_10);
 
  453        num_58_10_coeffs += 1;
 
  454        if (base_2_64_coeff[cur_2_64_end - 1] == 0)
 
  468    bool skip_zeros = 
true;
 
  469    auto out_index = input_zeros;
 
  470    for (
int i = num_58_10_coeffs - 1; i >= 0; --i)
 
  472        if (skip_zeros && base_58_10_coeff[i] == 0)
 
  477        if (base_58_10_coeff[i] >= B_58_10)
 
  479            return Unexpected(TokenCodecErrc::inputTooLarge);
 
  482            ripple::b58_fast::detail::b58_10_to_b58_be(base_58_10_coeff[i]);
 
  487            to_skip = count_leading_zeros(b58_be_s);
 
  489            if (
out.size() < (i + 1) * 10 - to_skip)
 
  491                return Unexpected(TokenCodecErrc::outputTooSmall);
 
  494        for (
auto b58_coeff : b58_be_s.subspan(to_skip))
 
  501    return out.subspan(0, out_index);
 
  505B58Result<std::span<std::uint8_t>>
 
  512    if (input.
size() > 52)
 
  514        return Unexpected(TokenCodecErrc::inputTooLarge);
 
  518        return Unexpected(TokenCodecErrc::outputTooSmall);
 
  521    auto count_leading_zeros = [&](
auto const& col) -> 
std::size_t {
 
  523        for (
auto const& c : col)
 
  534    auto const input_zeros = count_leading_zeros(input);
 
  540    auto [num_full_coeffs, partial_coeff_len] =
 
  541        ripple::b58_fast::detail::div_rem(input.
size(), 10);
 
  542    auto const num_partial_coeffs = partial_coeff_len ? 1 : 0;
 
  543    auto const num_b_58_10_coeffs = num_full_coeffs + num_partial_coeffs;
 
  545        num_b_58_10_coeffs <= b_58_10_coeff.size(),
 
  546        "ripple::b58_fast::detail::b58_to_b256_be : maximum coeff");
 
  547    for (
unsigned char c : input.substr(0, partial_coeff_len))
 
  552            return Unexpected(TokenCodecErrc::invalidEncodingChar);
 
  554        b_58_10_coeff[0] *= 58;
 
  555        b_58_10_coeff[0] += cur_val;
 
  557    for (
int i = 0; i < 10; ++i)
 
  559        for (
int j = 0; j < num_full_coeffs; ++j)
 
  561            unsigned char c = input[partial_coeff_len + j * 10 + i];
 
  565                return Unexpected(TokenCodecErrc::invalidEncodingChar);
 
  567            b_58_10_coeff[num_partial_coeffs + j] *= 58;
 
  568            b_58_10_coeff[num_partial_coeffs + j] += cur_val;
 
  576    result[0] = b_58_10_coeff[0];
 
  578    for (
int i = 1; i < num_b_58_10_coeffs; ++i)
 
  583            auto code = ripple::b58_fast::detail::inplace_bigint_mul(
 
  584                std::span(&result[0], cur_result_size + 1), B_58_10);
 
  585            if (code != TokenCodecErrc::success)
 
  591            auto code = ripple::b58_fast::detail::inplace_bigint_add(
 
  592                std::span(&result[0], cur_result_size + 1), c);
 
  593            if (code != TokenCodecErrc::success)
 
  598        if (result[cur_result_size] != 0)
 
  600            cur_result_size += 1;
 
  604    auto cur_out_i = input_zeros;
 
  609        auto skip_zero = 
true;
 
  611        for (
int i = 0; i < 8; ++i)
 
  626    if ((cur_out_i + 8 * (cur_result_size - 1)) > 
out.size())
 
  628        return Unexpected(TokenCodecErrc::outputTooSmall);
 
  631    for (
int i = cur_result_size - 2; i >= 0; --i)
 
  634        boost::endian::native_to_big_inplace(c);
 
  635        memcpy(&out[cur_out_i], &c, 8);
 
  639    return out.subspan(0, cur_out_i);
 
  643B58Result<std::span<std::uint8_t>>
 
  645    TokenType token_type,
 
  651    if (input.
size() > tmpBufSize - 5)
 
  653        return Unexpected(TokenCodecErrc::inputTooLarge);
 
  655    if (input.
size() == 0)
 
  657        return Unexpected(TokenCodecErrc::inputTooSmall);
 
  663    size_t const checksum_i = input.
size() + 1;
 
  667    return detail::b256_to_b58_be(b58Span, out);
 
  674B58Result<std::span<std::uint8_t>>
 
  681    auto const decodeResult =
 
  687    auto const ret = decodeResult.value();
 
  691        return Unexpected(TokenCodecErrc::inputTooSmall);
 
  695        return Unexpected(TokenCodecErrc::mismatchedTokenType);
 
  702        return Unexpected(TokenCodecErrc::mismatchedChecksum);
 
  706    if (outBuf.
size() < outSize)
 
  707        return Unexpected(TokenCodecErrc::outputTooSmall);
 
  709    std::copy(ret.begin() + 1, ret.begin() + outSize + 1, outBuf.
begin());
 
  710    return outBuf.
subspan(0, outSize);
 
  728    auto r = b58_fast::encodeBase58Token(type, inSp, outSp);
 
  731    sr.
resize(r.value().size());
 
  744    auto r = b58_fast::decodeBase58Token(type, s, outSp);
 
  747    sr.
resize(r.value().size());
 
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)
 
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
 
static constexpr std::array< int, 256 > const alphabetReverse
 
std::string encodeBase58Token(TokenType type, void const *token, std::size_t size)
Encode data in Base58Check format using XRPL alphabet.
 
std::string decodeBase58Token(std::string const &s, TokenType type)
 
static Hasher::result_type digest(void const *data, std::size_t size) noexcept
 
static Hasher::result_type digest2(Args const &... args)
 
Unexpected(E(&)[N]) -> Unexpected< E const * >
 
static void checksum(void *out, void const *message, std::size_t size)
Calculate a 4-byte checksum of the data.
 
static constexpr char const  * alphabetForward