28 #include <ripple/protocol/tokens.h>
30 #include <ripple/basics/safe_cast.h>
31 #include <ripple/protocol/digest.h>
32 #include <ripple/protocol/impl/b58_utils.h>
34 #include <boost/container/small_vector.hpp>
35 #include <boost/endian.hpp>
36 #include <boost/endian/conversion.hpp>
139 "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz";
150 template <
class Hasher>
151 static typename Hasher::result_type
156 return static_cast<typename Hasher::result_type
>(h);
164 static typename Hasher::result_type
167 return digest<Hasher>(v.
data(), v.
size());
171 template <
class Hasher,
class... Args>
172 static typename Hasher::result_type
175 return digest<Hasher>(digest<Hasher>(args...));
190 auto const h = digest2<sha256_hasher>(message, size);
198 return b58_fast::encodeBase58Token(type, token, size);
208 return b58_fast::decodeBase58Token(s, type);
225 auto pbegin =
reinterpret_cast<unsigned char const*
>(message);
226 auto const pend = pbegin + size;
230 while (pbegin != pend && *pbegin == 0)
236 auto const b58begin =
reinterpret_cast<unsigned char*
>(temp);
237 auto const b58end = b58begin + temp_size;
241 while (pbegin != pend)
245 for (
auto iter = b58end; iter != b58begin; --iter)
247 carry += 256 * (iter[-1]);
248 iter[-1] = carry % 58;
256 auto iter = b58begin;
257 while (iter != b58end && *iter == 0)
262 str.
reserve(zeroes + (b58end - iter));
264 while (iter != b58end)
272 auto psz =
reinterpret_cast<unsigned char const*
>(s.
c_str());
273 auto remain = s.
size();
295 for (
auto iter = b256.
rbegin(); iter != b256.
rend(); ++iter)
307 b256.
begin(), b256.
end(), [](
unsigned char c) { return c != 0; });
310 result.
assign(zeroes, 0x00);
311 while (iter != b256.
end())
322 auto const expanded = 1 + size + 4;
327 auto const bufsize = expanded * 3;
329 boost::container::small_vector<std::uint8_t, 1024> buf(bufsize);
333 buf[0] = safe_cast<std::underlying_type_t<TokenType>>(type);
336 checksum(buf.data() + 1 + size, buf.data(), 1 + size);
339 buf.data(), expanded, buf.data() + expanded, bufsize - expanded);
352 if (type != safe_cast<TokenType>(
static_cast<std::uint8_t>(ret[0])))
372 B58Result<std::span<std::uint8_t>>
377 if (input.
size() > 38)
382 auto count_leading_zeros =
385 for (
auto const& c : col)
396 auto const input_zeros = count_leading_zeros(input);
397 input = input.
subspan(input_zeros);
406 for (
int i = 0; i < base_2_64_coeff_buf.size(); ++i)
408 if (i * 8 >= input.
size())
412 auto const src_i_end = input.
size() - i * 8;
416 &base_2_64_coeff_buf[num_coeff], &input[src_i_end - 8], 8);
417 boost::endian::big_to_native_inplace(
418 base_2_64_coeff_buf[num_coeff]);
423 for (
int bi = 0; bi < src_i_end; ++bi)
428 base_2_64_coeff_buf[num_coeff] = be;
432 return std::span(base_2_64_coeff_buf.data(), num_coeff);
442 while (cur_2_64_end > 0)
444 base_58_10_coeff[num_58_10_coeffs] =
445 ripple::b58_fast::detail::inplace_bigint_div_rem(
446 base_2_64_coeff.
subspan(0, cur_2_64_end), B_58_10);
447 num_58_10_coeffs += 1;
448 if (base_2_64_coeff[cur_2_64_end - 1] == 0)
462 bool skip_zeros =
true;
463 auto out_index = input_zeros;
464 for (
int i = num_58_10_coeffs - 1; i >= 0; --i)
466 if (skip_zeros && base_58_10_coeff[i] == 0)
471 ripple::b58_fast::detail::b58_10_to_b58_be(base_58_10_coeff[i]);
476 to_skip = count_leading_zeros(b58_be_s);
478 if (
out.size() < (i + 1) * 10 - to_skip)
483 for (
auto b58_coeff : b58_be_s.subspan(to_skip))
485 out[out_index] = ::ripple::alphabetForward[b58_coeff];
490 return out.subspan(0, out_index);
494 B58Result<std::span<std::uint8_t>>
501 if (input.
size() > 52)
510 auto count_leading_zeros = [&](
auto const& col) ->
std::size_t {
512 for (
auto const& c : col)
523 auto const input_zeros = count_leading_zeros(input);
529 auto [num_full_coeffs, partial_coeff_len] =
530 ripple::b58_fast::detail::div_rem(input.
size(), 10);
531 auto const num_partial_coeffs = partial_coeff_len ? 1 : 0;
532 auto const num_b_58_10_coeffs = num_full_coeffs + num_partial_coeffs;
533 assert(num_b_58_10_coeffs <= b_58_10_coeff.size());
534 for (
auto c : input.
substr(0, partial_coeff_len))
536 auto cur_val = ::ripple::alphabetReverse[c];
541 b_58_10_coeff[0] *= 58;
542 b_58_10_coeff[0] += cur_val;
544 for (
int i = 0; i < 10; ++i)
546 for (
int j = 0; j < num_full_coeffs; ++j)
548 auto c = input[partial_coeff_len + j * 10 + i];
549 auto cur_val = ::ripple::alphabetReverse[c];
554 b_58_10_coeff[num_partial_coeffs + j] *= 58;
555 b_58_10_coeff[num_partial_coeffs + j] += cur_val;
563 result[0] = b_58_10_coeff[0];
565 for (
int i = 1; i < num_b_58_10_coeffs; ++i)
568 ripple::b58_fast::detail::inplace_bigint_mul(
569 std::span(&result[0], cur_result_size + 1), B_58_10);
570 ripple::b58_fast::detail::inplace_bigint_add(
571 std::span(&result[0], cur_result_size + 1), c);
572 if (result[cur_result_size] != 0)
574 cur_result_size += 1;
578 auto cur_out_i = input_zeros;
583 auto skip_zero =
true;
585 for (
int i = 0; i < 8; ++i)
600 if ((cur_out_i + 8 * (cur_result_size - 1)) >
out.size())
605 for (
int i = cur_result_size - 2; i >= 0; --i)
608 boost::endian::native_to_big_inplace(c);
609 memcpy(&out[cur_out_i], &c, 8);
613 return out.subspan(0, cur_out_i);
617 B58Result<std::span<std::uint8_t>>
625 if (input.
size() > tmpBufSize - 5)
629 if (input.
size() == 0)
637 size_t const checksum_i = input.
size() + 1;
641 return detail::b256_to_b58_be(b58Span, out);
648 B58Result<std::span<std::uint8_t>>
655 auto const decodeResult =
661 auto const ret = decodeResult.value();
680 if (outBuf.
size() < outSize)
683 std::copy(ret.begin() + 1, ret.begin() + outSize + 1, outBuf.
begin());
684 return outBuf.
subspan(0, outSize);
702 auto r = b58_fast::encodeBase58Token(type, inSp, outSp);
705 sr.
resize(r.value().size());
718 auto r = b58_fast::decodeBase58Token(type, s, outSp);
721 sr.
resize(r.value().size());