Skip to content

Commit

Permalink
[fold] Fix bug with all zero data; Expose and test detail functions
Browse files Browse the repository at this point in the history
  • Loading branch information
seelabs committed Feb 22, 2023
1 parent 0d7ee11 commit 42c9503
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 35 deletions.
52 changes: 24 additions & 28 deletions src/ripple/protocol/impl/tokens.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,31 @@ checksum(void* out, void const* message, std::size_t size)
std::memcpy(out, h.data(), 4);
}

[[nodiscard]] std::string
encodeBase58Token(TokenType type, void const* token, std::size_t size)
{
#ifndef _MSC_VER
return b58_fast::encodeBase58Token(type, token, size);
#else
return b58_ref::encodeBase58Token(type, token, size);
#endif
}

[[nodiscard]] std::string
decodeBase58Token(std::string const& s, TokenType type)
{
#ifndef _MSC_VER
return b58_fast::decodeBase58Token(s, type);
#else
return b58_ref::decodeBase58Token_ms(s, type);
#endif
}

namespace b58_ref {

namespace detail {

static std::string
std::string
encodeBase58(
void const* message,
std::size_t size,
Expand Down Expand Up @@ -144,7 +166,7 @@ encodeBase58(
return str;
}

static std::string
std::string
decodeBase58(std::string const& s)
{
auto psz = reinterpret_cast<unsigned char const*>(s.c_str());
Expand Down Expand Up @@ -193,27 +215,6 @@ decodeBase58(std::string const& s)

} // namespace detail

[[nodiscard]] std::string
encodeBase58Token(TokenType type, void const* token, std::size_t size)
{
#ifndef _MSC_VER
return b58_fast::encodeBase58Token(type, token, size);
#else
return b58_ref::encodeBase58Token(type, token, size);
#endif
}

[[nodiscard]] std::string
decodeBase58Token(std::string const& s, TokenType type)
{
#ifndef _MSC_VER
return b58_fast::decodeBase58Token(s, type);
#else
return b58_ref::decodeBase58Token_ms(s, type);
#endif
}

namespace b58_ref {
std::string
encodeBase58Token(TokenType type, void const* token, std::size_t size)
{
Expand Down Expand Up @@ -478,11 +479,6 @@ b58_to_b256(std::string_view input, std::span<std::uint8_t> out)
for (int i = 0; i < 8; ++i)
{
std::uint8_t const b = (c >> (8 * (7 - i))) & 0xff;
if (i == 7)
{
// handle the all zero case - write the last zero
skip_zero = false;
}
if (skip_zero)
{
if (b == 0)
Expand Down
22 changes: 22 additions & 0 deletions src/ripple/protocol/tokens.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,19 @@ encodeBase58Token(TokenType type, void const* token, std::size_t size);

[[nodiscard]] std::string
decodeBase58Token(std::string const& s, TokenType type);

namespace detail {
// Expose detail functions for unit tests only
std::string
encodeBase58(
void const* message,
std::size_t size,
void* temp,
std::size_t temp_size);

std::string
decodeBase58(std::string const& s);
} // namespace detail
} // namespace b58_ref

#ifndef _MSC_VER
Expand All @@ -104,6 +117,15 @@ encodeBase58Token(TokenType type, void const* token, std::size_t size);
[[nodiscard]] std::string
decodeBase58Token(std::string const& s, TokenType type);

namespace detail {
// Expose detail functions for unit tests only
B58Result<std::span<std::uint8_t>>
b256_to_b58(std::span<std::uint8_t const> input, std::span<std::uint8_t> out);

B58Result<std::span<std::uint8_t>>
b58_to_b256(std::string_view input, std::span<std::uint8_t> out);
} // namespace detail

} // namespace b58_fast
#endif
} // namespace ripple
Expand Down
100 changes: 93 additions & 7 deletions src/test/basics/base58_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,15 +238,93 @@ class base58_test : public beast::unit_test::suite
testFastMatchesRef()
{
testcase("fast_matches_ref");
std::array<std::uint8_t, 128> b256DataBuf;
std::array<std::uint8_t, 64> b58ResultBuf[2];
std::array<std::span<std::uint8_t>, 2> b58Result;
auto testRawEncode = [&](std::span<std::uint8_t> const& b256Data) {
std::array<std::uint8_t, 64> b58ResultBuf[2];
std::array<std::span<std::uint8_t>, 2> b58Result;

std::array<std::uint8_t, 64> b256ResultBuf[2];
std::array<std::span<std::uint8_t>, 2> b256Result;
std::array<std::uint8_t, 64> b256ResultBuf[2];
std::array<std::span<std::uint8_t>, 2> b256Result;
for (int i = 0; i < 2; ++i)
{
auto const outBuf =
std::span(b58ResultBuf[i].data(), b58ResultBuf[i].size());
if (i == 0)
{
auto const r =
ripple::b58_fast::detail::b256_to_b58(b256Data, outBuf);
BEAST_EXPECT(r);
b58Result[i] = r.value();
}
else
{
std::array<std::uint8_t, 128> tmpBuf;
auto const s = ripple::b58_ref::detail::encodeBase58(
b256Data.data(),
b256Data.size(),
tmpBuf.data(),
tmpBuf.size());
BEAST_EXPECT(s.size());
b58Result[i] = outBuf.subspan(0, s.size());
std::copy(s.begin(), s.end(), b58Result[i].begin());
}
}
if (BEAST_EXPECT(b58Result[0].size() == b58Result[1].size()))
{
if (!BEAST_EXPECT(
memcmp(
b58Result[0].data(),
b58Result[1].data(),
b58Result[0].size()) == 0))
{
printAsChar(b58Result[0], b58Result[1]);
}
}

auto testIt = [&](ripple::TokenType const tokType,
std::span<std::uint8_t> const& b256Data) {
for (int i = 0; i < 2; ++i)
{
auto const outBuf =
std::span(b256ResultBuf[i].data(), b256ResultBuf[i].size());
if (i == 0)
{
std::string const in(
b58Result[i].data(),
b58Result[i].data() + b58Result[i].size());
auto const r =
ripple::b58_fast::detail::b58_to_b256(in, outBuf);
BEAST_EXPECT(r);
b256Result[i] = r.value();
}
else
{
std::string const st(
b58Result[i].begin(), b58Result[i].end());
auto const s = ripple::b58_ref::detail::decodeBase58(st);
BEAST_EXPECT(s.size());
b256Result[i] = outBuf.subspan(0, s.size());
std::copy(s.begin(), s.end(), b256Result[i].begin());
}
}

if (BEAST_EXPECT(b256Result[0].size() == b256Result[1].size()))
{
if (!BEAST_EXPECT(
memcmp(
b256Result[0].data(),
b256Result[1].data(),
b256Result[0].size()) == 0))
{
printAsInt(b256Result[0], b256Result[1]);
}
}
};

auto testTokenEncode = [&](ripple::TokenType const tokType,
std::span<std::uint8_t> const& b256Data) {
std::array<std::uint8_t, 64> b58ResultBuf[2];
std::array<std::span<std::uint8_t>, 2> b58Result;

std::array<std::uint8_t, 64> b256ResultBuf[2];
std::array<std::span<std::uint8_t>, 2> b256Result;
for (int i = 0; i < 2; ++i)
{
auto const outBuf =
Expand Down Expand Up @@ -318,10 +396,17 @@ class base58_test : public beast::unit_test::suite
}
};

auto testIt = [&](ripple::TokenType const tokType,
std::span<std::uint8_t> const& b256Data) {
testRawEncode(b256Data);
testTokenEncode(tokType, b256Data);
};

// test every token type with data where every byte is the same and the
// bytes range from 0-255
for (int i = 0; i < numTokenTypeIndexes; ++i)
{
std::array<std::uint8_t, 128> b256DataBuf;
auto const [tokType, tokSize] = tokenTypeAndSize(i);
for (int d = 0; d < 255; ++d)
{
Expand All @@ -334,6 +419,7 @@ class base58_test : public beast::unit_test::suite
constexpr std::size_t iters = 1000000;
for (int i = 0; i < iters; ++i)
{
std::array<std::uint8_t, 128> b256DataBuf;
auto const [tokType, b256Data] = randomB256TestData(
std::span(b256DataBuf.data(), b256DataBuf.size()));
testIt(tokType, b256Data);
Expand Down

0 comments on commit 42c9503

Please sign in to comment.