Skip to content

Commit

Permalink
Merge pull request #1562 from evoskuil/master
Browse files Browse the repository at this point in the history
Complete shani integration.
  • Loading branch information
evoskuil authored Dec 7, 2024
2 parents 0cdbe08 + d7c9261 commit 9b16970
Show file tree
Hide file tree
Showing 10 changed files with 613 additions and 286 deletions.
40 changes: 29 additions & 11 deletions include/bitcoin/system/hash/sha/algorithm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ class algorithm
static void accumulate(state_t& state, iblocks_t&& blocks) NOEXCEPT;
static constexpr void accumulate(state_t& state, const block_t& block) NOEXCEPT;
static constexpr digest_t normalize(const state_t& state) NOEXCEPT;

template <size_t Blocks>
static constexpr digest_t finalize(state_t& state) NOEXCEPT;
static constexpr digest_t finalize(state_t& state, size_t blocks) NOEXCEPT;
static constexpr digest_t finalize_second(const state_t& state) NOEXCEPT;
static constexpr digest_t finalize_double(state_t& state, size_t blocks) NOEXCEPT;
Expand Down Expand Up @@ -166,9 +169,6 @@ class algorithm
template <typename xWord, if_extended<xWord> = true>
using wstate_t = std_array<xWord, sizeof(state_t) / sizeof(xWord)>;

////template <typename xWord, if_extended<xWord> = true>
////using wblock_t = std_array<xWord, sizeof(block_t) / sizeof(xWord)>;

/// Other types.
/// -----------------------------------------------------------------------

Expand Down Expand Up @@ -232,8 +232,8 @@ class algorithm
/// -----------------------------------------------------------------------

INLINE static constexpr void input(buffer_t& buffer, const block_t& block) NOEXCEPT;
INLINE static constexpr void input_left(buffer_t& buffer, const half_t& half) NOEXCEPT;
INLINE static constexpr void input_right(buffer_t& buffer, const half_t& half) NOEXCEPT;
INLINE static constexpr void input_left(auto& buffer, const half_t& half) NOEXCEPT;
INLINE static constexpr void input_right(auto& buffer, const half_t& half) NOEXCEPT;
INLINE static constexpr digest_t output(const state_t& state) NOEXCEPT;

/// Padding.
Expand All @@ -260,7 +260,8 @@ class algorithm
/// Double hashing.
/// -----------------------------------------------------------------------

static constexpr void reinput(auto& buffer, const auto& state) NOEXCEPT;
static constexpr void reinput_left(auto& buffer, const auto& left) NOEXCEPT;
static constexpr void reinput_right(auto& buffer, const auto& right) NOEXCEPT;

/// Iteration (message scheduling vectorized for multiple blocks).
/// -----------------------------------------------------------------------
Expand Down Expand Up @@ -385,13 +386,30 @@ class algorithm
xint128_t message) NOEXCEPT;

template <bool Swap>
INLINE static void native_rounds(xint128_t& lo, xint128_t& hi,
static void native_rounds(xint128_t& lo, xint128_t& hi,
const block_t& block) NOEXCEPT;

static void native_(state_t& state, iblocks_t& blocks) NOEXCEPT;
static void native_(state_t& state, const block_t& block) NOEXCEPT;
INLINE static void native_preswapped(state_t& state,
const words_t& block) NOEXCEPT;
template <bool Swap>
static void native_transform(state_t& state, const auto& block) NOEXCEPT;
static void native_transform(state_t& state, iblocks_t& blocks) NOEXCEPT;

template <size_t Blocks>
static digest_t native_finalize(state_t& state) NOEXCEPT;
static digest_t native_finalize(state_t& state, size_t blocks) NOEXCEPT;
static digest_t native_finalize(state_t& state, const words_t& pad) NOEXCEPT;

static digest_t native_finalize_second(const state_t& half) NOEXCEPT;
static digest_t native_finalize_double(state_t& half, size_t blocks) NOEXCEPT;

////static digest_t native_hash(const block_t& block) NOEXCEPT;
static digest_t native_hash(const half_t& half) NOEXCEPT;
static digest_t native_hash(const half_t& left, const half_t& right) NOEXCEPT;

static digest_t native_double_hash(const block_t& block) NOEXCEPT;
static digest_t native_double_hash(const half_t& half) NOEXCEPT;
static digest_t native_double_hash(const half_t& left, const half_t& right) NOEXCEPT;



public:
/// Summary public values.
Expand Down
1 change: 0 additions & 1 deletion include/bitcoin/system/have.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@

/// XCPU architecture intrinsics sse41, avx2, avx512f, sha-ni.
/// This assumes that avx512 implies avx2 and that all imply sse41.
/// All require runtime evaluation for the binary is portable across XCPUs.
#if defined(HAVE_XCPU)
// TODO: CLANG/GCC compile test and set -msse4 -mavx2 -mavx512f -msha.
#if defined(WITH_SHANI)
Expand Down
238 changes: 153 additions & 85 deletions include/bitcoin/system/impl/hash/sha/algorithm_double.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
// Double hashing.
// ============================================================================
// No hash(state_t) optimizations for sha160 (requires chunk_t/half_t).
// State input directly to buffer (reinput) eliminates two endianness calls.
// State put directly to buffer (reinput) eliminates two endianness transforms.

namespace libbitcoin {
namespace system {
Expand All @@ -33,30 +33,57 @@ namespace sha {

TEMPLATE
INLINE constexpr void CLASS::
reinput(auto& buffer, const auto& state) NOEXCEPT
reinput_left(auto& buffer, const auto& left) NOEXCEPT
{
static_assert(SHA::strength != 160);
using words = decltype(buffer);
static_assert(array_count<words> >= SHA::state_words);

if (std::is_constant_evaluated())
{
buffer[0] = state[0];
buffer[1] = state[1];
buffer[2] = state[2];
buffer[3] = state[3];
buffer[4] = state[4];
buffer[5] = state[5];
buffer[6] = state[6];
buffer[7] = state[7];
buffer.at(0) = left.at(0);
buffer.at(1) = left.at(1);
buffer.at(2) = left.at(2);
buffer.at(3) = left.at(3);
buffer.at(4) = left.at(4);
buffer.at(5) = left.at(5);
buffer.at(6) = left.at(6);
buffer.at(7) = left.at(7);
}
else
{
using word = array_element<decltype(state)>;
array_cast<word, SHA::state_words>(buffer) = state;
using word = array_element<words>;
array_cast<word, SHA::state_words>(buffer) = left;
}
}

TEMPLATE
INLINE constexpr void CLASS::
reinput_right(auto& buffer, const auto& right) NOEXCEPT
{
using words = decltype(buffer);
static_assert(array_count<words> >= SHA::state_words);

if (std::is_constant_evaluated())
{
buffer.at(8) = right.at(0);
buffer.at(9) = right.at(1);
buffer.at(10) = right.at(2);
buffer.at(11) = right.at(3);
buffer.at(12) = right.at(4);
buffer.at(13) = right.at(5);
buffer.at(14) = right.at(6);
buffer.at(15) = right.at(7);
}
else
{
using word = array_element<words>;
array_cast<word, SHA::state_words, SHA::state_words>(buffer) = right;
}
}

// public
// ----------------------------------------------------------------------------
// These benefit from avoiding state endian transition and reusing buffer.

TEMPLATE
template <size_t Size>
Expand All @@ -68,18 +95,18 @@ double_hash(const ablocks_t<Size>& blocks) NOEXCEPT
auto state = H::get;
iterate(state, blocks);

buffer_t buffer{};
schedule_n<Size>(buffer);
compress(state, buffer);

// Second hash
reinput(buffer, state);
pad_half(buffer);
schedule(buffer);
state = H::get;
compress(state, buffer);

return output(state);
if (std::is_constant_evaluated())
{
return finalize_double(state, Size);
}
else if constexpr (native && SHA::strength == 256)
{
return native_finalize_double(state, Size);
}
else
{
return finalize_double(state, Size);
}
}

TEMPLATE
Expand All @@ -94,18 +121,14 @@ double_hash(iblocks_t&& blocks) NOEXCEPT
auto state = H::get;
iterate(state, blocks);

buffer_t buffer{};
schedule_n(buffer, count);
compress(state, buffer);

// Second hash
reinput(buffer, state);
pad_half(buffer);
schedule(buffer);
state = H::get;
compress(state, buffer);

return output(state);
if constexpr (native && SHA::strength == 256)
{
return native_finalize_double(state, count);
}
else
{
return finalize_double(state, count);
}
}

TEMPLATE
Expand All @@ -114,23 +137,38 @@ double_hash(const block_t& block) NOEXCEPT
{
static_assert(is_same_type<state_t, chunk_t>);

auto state = H::get;
const auto hash2 = [](const block_t& block) NOEXCEPT
{
auto state = H::get;
buffer_t buffer{};
input(buffer, block);
schedule(buffer);
compress(state, buffer);
schedule_1(buffer);
compress(state, buffer);

// Second hash
reinput_left(buffer, state);
pad_half(buffer);
schedule(buffer);
state = H::get;
compress(state, buffer);

return output(state);
};

buffer_t buffer{};
input(buffer, block);
schedule(buffer);
compress(state, buffer);
schedule_1(buffer);
compress(state, buffer);

// Second hash
reinput(buffer, state);
pad_half(buffer);
schedule(buffer);
state = H::get;
compress(state, buffer);

return output(state);
if (std::is_constant_evaluated())
{
return hash2(block);
}
else if constexpr (native && SHA::strength == 256)
{
return native_double_hash(block);
}
else
{
return hash2(block);
}
}

TEMPLATE
Expand All @@ -139,22 +177,37 @@ double_hash(const half_t& half) NOEXCEPT
{
static_assert(is_same_type<state_t, chunk_t>);

auto state = H::get;

buffer_t buffer{};
input_left(buffer, half);
pad_half(buffer);
schedule(buffer);
compress(state, buffer);

// Second hash
reinput(buffer, state);
pad_half(buffer);
schedule(buffer);
state = H::get;
compress(state, buffer);
const auto hash2 = [](const half_t& half) NOEXCEPT
{
auto state = H::get;
buffer_t buffer{};
input_left(buffer, half);
pad_half(buffer);
schedule(buffer);
compress(state, buffer);

// Second hash
reinput_left(buffer, state);
pad_half(buffer);
schedule(buffer);
state = H::get;
compress(state, buffer);

return output(state);
};

return output(state);
if (std::is_constant_evaluated())
{
return hash2(half);
}
else if constexpr (native && SHA::strength == 256)
{
return native_double_hash(half);
}
else
{
return hash2(half);
}
}

TEMPLATE
Expand All @@ -163,24 +216,39 @@ double_hash(const half_t& left, const half_t& right) NOEXCEPT
{
static_assert(is_same_type<state_t, chunk_t>);

auto state = H::get;
const auto hash2 = [](const half_t& left, const half_t& right) NOEXCEPT
{
auto state = H::get;
buffer_t buffer{};
input_left(buffer, left);
input_right(buffer, right);
schedule(buffer);
compress(state, buffer);
schedule_1(buffer);
compress(state, buffer);

// Second hash
reinput_left(buffer, state);
pad_half(buffer);
schedule(buffer);
state = H::get;
compress(state, buffer);

return output(state);
};

buffer_t buffer{};
input_left(buffer, left);
input_right(buffer, right);
schedule(buffer);
compress(state, buffer);
schedule_1(buffer);
compress(state, buffer);

// Second hash
reinput(buffer, state);
pad_half(buffer);
schedule(buffer);
state = H::get;
compress(state, buffer);

return output(state);
if (std::is_constant_evaluated())
{
return hash2(left, right);
}
else if constexpr (native && SHA::strength == 256)
{
return native_double_hash(left, right);
}
else
{
return hash2(left, right);
}
}

} // namespace sha
Expand Down
Loading

0 comments on commit 9b16970

Please sign in to comment.