Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[fold] Fix bug with all zero data; Expose and test detail functions
Browse files Browse the repository at this point in the history
seelabs committed Feb 22, 2023

Verified

This commit was signed with the committer’s verified signature. The key has expired.
1 parent 0d7ee11 commit 42c9503
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
@@ -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,
@@ -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());
@@ -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)
{
@@ -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)
22 changes: 22 additions & 0 deletions src/ripple/protocol/tokens.h
Original file line number Diff line number Diff line change
@@ -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
@@ -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
100 changes: 93 additions & 7 deletions src/test/basics/base58_test.cpp
Original file line number Diff line number Diff line change
@@ -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 =
@@ -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)
{
@@ -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);

0 comments on commit 42c9503

Please sign in to comment.