Skip to content

Commit 7d21df5

Browse files
committed
Add optimized single byte hash function.
1 parent 506cdb5 commit 7d21df5

4 files changed

Lines changed: 58 additions & 1 deletion

File tree

include/bitcoin/system/hash/sha/algorithm.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class algorithm
7777
using iblocks_t = iterable<block_t>;
7878
using digests_t = std::vector<digest_t>;
7979

80-
/// Constants.
80+
/// Count types.
8181
/// -----------------------------------------------------------------------
8282

8383
/// count_t is uint64_t (sha160/256) or uint128_t (sha512).
@@ -92,12 +92,14 @@ class algorithm
9292

9393
/// Single hashing.
9494
/// -----------------------------------------------------------------------
95+
9596
template <size_t Size>
9697
static constexpr digest_t hash(const ablocks_t<Size>& blocks) NOEXCEPT;
9798
static constexpr digest_t hash(const block_t& block) NOEXCEPT;
9899
static constexpr digest_t hash(const half_t& half) NOEXCEPT;
99100
static constexpr digest_t hash(const half_t& left, const half_t& right) NOEXCEPT;
100101
static constexpr digest_t hash(const quart_t& left, const quart_t& right) NOEXCEPT;
102+
static constexpr digest_t hash(uint8_t byte) NOEXCEPT;
101103
static digest_t hash(iblocks_t&& blocks) NOEXCEPT;
102104

103105
/// Double hashing (sha256/512).
@@ -407,6 +409,7 @@ class algorithm
407409
static digest_t native_hash(const block_t& block) NOEXCEPT;
408410
static digest_t native_hash(const half_t& half) NOEXCEPT;
409411
static digest_t native_hash(const half_t& left, const half_t& right) NOEXCEPT;
412+
static digest_t native_hash(uint8_t byte) NOEXCEPT;
410413

411414
static digest_t native_double_hash(const block_t& block) NOEXCEPT;
412415
static digest_t native_double_hash(const half_t& half) NOEXCEPT;

include/bitcoin/system/impl/hash/sha/algorithm_native.ipp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,19 @@ native_hash(const half_t& left, const half_t& right) NOEXCEPT
344344
return native_finalize<one>(state);
345345
}
346346

347+
TEMPLATE
348+
typename CLASS::digest_t CLASS::
349+
native_hash(uint8_t byte) NOEXCEPT
350+
{
351+
constexpr auto pad = bit_hi<uint8_t>;
352+
353+
block_t block{};
354+
block.at(0) = byte;
355+
block.at(1) = pad;
356+
block.at(63) = byte_bits;
357+
return native_hash(block);
358+
}
359+
347360
// Double hash functions start with BE data and end with BE digest_t.
348361
// ----------------------------------------------------------------------------
349362

include/bitcoin/system/impl/hash/sha/algorithm_single.ipp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,39 @@ hash(const quart_t& left, const quart_t& right) NOEXCEPT
161161
}
162162
}
163163

164+
TEMPLATE
165+
constexpr typename CLASS::digest_t CLASS::
166+
hash(uint8_t byte) NOEXCEPT
167+
{
168+
const auto hasher = [](uint8_t byte) NOEXCEPT
169+
{
170+
// Shift the pad sentinel one byte to make room for the value.
171+
// Byte swapped for the sake of simplicity and will be reversed below.
172+
constexpr auto pad = shift_left<word_t>(bit_hi<uint8_t>, byte_bits);
173+
174+
auto state = H::get;
175+
buffer_t buffer{};
176+
buffer.at(0) = byteswap(bit_or<word_t>(pad, byte));
177+
buffer.at(15) = byte_bits;
178+
schedule(buffer);
179+
compress(state, buffer);
180+
return output(state);
181+
};
182+
183+
if (std::is_constant_evaluated())
184+
{
185+
return hasher(byte);
186+
}
187+
else if constexpr (native && SHA::strength == 256)
188+
{
189+
return native_hash(byte);
190+
}
191+
else
192+
{
193+
return hasher(byte);
194+
}
195+
}
196+
164197
} // namespace sha
165198
} // namespace system
166199
} // namespace libbitcoin

test/hash/sha/sha256.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,14 @@ BOOST_AUTO_TEST_CASE(sha256__hash__quart_blocks__expected)
201201
BOOST_CHECK_EQUAL(sha256::hash(sha256::quart_t{ 0 }, sha256::quart_t{ 0 }), expected);
202202
}
203203

204+
BOOST_AUTO_TEST_CASE(sha256__hash__byte__expected)
205+
{
206+
// github.com/mit-dci/rustreexo/blob/main/src/accumulator/node_hash.rs#L338
207+
constexpr auto expected = base16_array("6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d");
208+
static_assert(sha256::hash(0) == expected);
209+
BOOST_CHECK_EQUAL(sha256::hash(0), expected);
210+
}
211+
204212
// sha256::double_hash
205213
BOOST_AUTO_TEST_CASE(sha256__double_hash__full_block__expected)
206214
{

0 commit comments

Comments
 (0)