Skip to content

Commit eef328b

Browse files
committed
Modernize and clean up hashing infrastructure:
The hardened hash implementation carried dead weight: SipHash compatibility code that never saw use, plus template indirection now superseded by inline variables. Separately, base_uint_hasher in RWDBFactory had a bug: it would instantiate a new hardened hasher per operation. Since nothing used this type anyway, it's been removed entirely.
1 parent f14b2b7 commit eef328b

File tree

7 files changed

+81
-397
lines changed

7 files changed

+81
-397
lines changed

Builds/CMake/RippledCore.cmake

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,6 @@ if (tests)
812812
src/test/basics/base_uint_test.cpp
813813
src/test/basics/contract_test.cpp
814814
src/test/basics/FeeUnits_test.cpp
815-
src/test/basics/hardened_hash_test.cpp
816815
src/test/basics/join_test.cpp
817816
src/test/basics/mulDiv_test.cpp
818817
src/test/basics/tagged_integer_test.cpp

src/ripple/basics/hardened_hash.h

Lines changed: 22 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -22,43 +22,25 @@
2222

2323
#include <ripple/beast/hash/hash_append.h>
2424
#include <ripple/beast/hash/xxhasher.h>
25+
#include <ripple/beast/xor_shift_engine.h>
2526

26-
#include <cstdint>
27-
#include <functional>
28-
#include <mutex>
27+
#include <atomic>
2928
#include <random>
30-
#include <type_traits>
31-
#include <unordered_map>
32-
#include <unordered_set>
33-
#include <utility>
3429

3530
namespace ripple {
3631

3732
namespace detail {
3833

39-
using seed_pair = std::pair<std::uint64_t, std::uint64_t>;
34+
inline std::atomic hardened_hash_seed = []() {
35+
std::uint64_t seed = 0x726661627563794;
4036

41-
template <bool = true>
42-
seed_pair
43-
make_seed_pair() noexcept
44-
{
45-
struct state_t
46-
{
47-
std::mutex mutex;
48-
std::random_device rng;
49-
std::mt19937_64 gen;
50-
std::uniform_int_distribution<std::uint64_t> dist;
51-
52-
state_t() : gen(rng())
53-
{
54-
}
55-
// state_t(state_t const&) = delete;
56-
// state_t& operator=(state_t const&) = delete;
57-
};
58-
static state_t state;
59-
std::lock_guard lock(state.mutex);
60-
return {state.dist(state.gen), state.dist(state.gen)};
61-
}
37+
std::random_device rd;
38+
39+
for (int i = 0; i < 16; ++i)
40+
seed ^= (seed << 6) + rd();
41+
42+
return seed;
43+
}();
6244

6345
} // namespace detail
6446

@@ -95,21 +77,25 @@ make_seed_pair() noexcept
9577
template <class HashAlgorithm = beast::xxhasher>
9678
class hardened_hash
9779
{
98-
private:
99-
detail::seed_pair m_seeds;
80+
std::uint64_t seed_;
10081

10182
public:
102-
using result_type = typename HashAlgorithm::result_type;
103-
104-
hardened_hash() : m_seeds(detail::make_seed_pair<>())
83+
using result_type = HashAlgorithm::result_type;
84+
85+
hardened_hash() noexcept
86+
: seed_(
87+
beast::fmix64(
88+
detail::hardened_hash_seed.fetch_add(
89+
1,
90+
std::memory_order_relaxed)))
10591
{
10692
}
10793

10894
template <class T>
109-
result_type
95+
[[nodiscard]] result_type
11096
operator()(T const& t) const noexcept
11197
{
112-
HashAlgorithm h(m_seeds.first, m_seeds.second);
98+
HashAlgorithm h(seed_);
11399
hash_append(h, t);
114100
return static_cast<result_type>(h);
115101
}

src/ripple/beast/hash/xxhasher.h

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,41 +22,29 @@
2222

2323
#include <ripple/beast/hash/impl/xxhash.h>
2424
#include <boost/endian/conversion.hpp>
25+
#include <concepts>
2526
#include <cstddef>
26-
#include <type_traits>
2727

2828
namespace beast {
2929

3030
class xxhasher
3131
{
32-
private:
3332
// requires 64-bit std::size_t
34-
static_assert(sizeof(std::size_t) == 8, "");
33+
static_assert(sizeof(std::size_t) == 8);
3534

3635
detail::XXH64_state_t state_;
3736

3837
public:
3938
using result_type = std::size_t;
4039

41-
static constexpr auto const endian = boost::endian::order::native;
40+
static constexpr auto endian = boost::endian::order::native;
4241

4342
xxhasher() noexcept
4443
{
4544
detail::XXH64_reset(&state_, 1);
4645
}
4746

48-
template <
49-
class Seed,
50-
std::enable_if_t<std::is_unsigned<Seed>::value>* = nullptr>
51-
explicit xxhasher(Seed seed)
52-
{
53-
detail::XXH64_reset(&state_, seed);
54-
}
55-
56-
template <
57-
class Seed,
58-
std::enable_if_t<std::is_unsigned<Seed>::value>* = nullptr>
59-
xxhasher(Seed seed, Seed)
47+
explicit xxhasher(std::unsigned_integral auto seed) noexcept
6048
{
6149
detail::XXH64_reset(&state_, seed);
6250
}
@@ -67,7 +55,8 @@ class xxhasher
6755
detail::XXH64_update(&state_, key, len);
6856
}
6957

70-
explicit operator std::size_t() noexcept
58+
[[nodiscard]] explicit
59+
operator std::size_t() noexcept
7160
{
7261
return detail::XXH64_digest(&state_);
7362
}

src/ripple/beast/xor_shift_engine.h

Lines changed: 46 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,40 @@
2020
#ifndef BEAST_RANDOM_XOR_SHIFT_ENGINE_H_INCLUDED
2121
#define BEAST_RANDOM_XOR_SHIFT_ENGINE_H_INCLUDED
2222

23+
#include <array>
2324
#include <cstdint>
2425
#include <limits>
25-
#include <stdexcept>
2626

2727
namespace beast {
2828

29-
namespace detail {
29+
/** MurmurHash3 64-bit finalizer (fmix64).
3030
31-
template <class = void>
31+
A bijective mixing function with strong avalanche behavior: every input
32+
bit affects every output bit with probability ~0.5.
33+
34+
Commonly used for:
35+
- Integer hashing
36+
- Seed expansion for PRNGs
37+
- Converting sequential values to uncorrelated values
38+
39+
@param x The input value to mix.
40+
@return The mixed output value.
41+
*/
42+
[[nodiscard]] constexpr std::uint64_t
43+
fmix64(std::uint64_t x) noexcept
44+
{
45+
x = 0xff51afd7ed558ccd * (x ^ (x >> 33));
46+
x = 0xc4ceb9fe1a85ec53 * (x ^ (x >> 33));
47+
return x ^ (x >> 33);
48+
}
49+
50+
/** XOR-shift Generator.
51+
52+
Meets the requirements of UniformRandomNumberGenerator.
53+
54+
Simple and fast RNG based on:
55+
http://xorshift.di.unimi.it/xorshift128plus.c
56+
*/
3257
class xor_shift_engine
3358
{
3459
public:
@@ -38,81 +63,37 @@ class xor_shift_engine
3863
xor_shift_engine&
3964
operator=(xor_shift_engine const&) = default;
4065

41-
explicit xor_shift_engine(result_type val = 1977u);
42-
43-
void
44-
seed(result_type seed);
66+
explicit constexpr xor_shift_engine(result_type val = 1977u) noexcept
67+
: s_{(val * val) + 1, fmix64(val)}
68+
{
69+
}
4570

46-
result_type
47-
operator()();
71+
[[nodiscard]] constexpr result_type
72+
operator()() noexcept
73+
{
74+
result_type s1 = s_[0];
75+
result_type const s0 = s_[1];
76+
s_[0] = s0;
77+
s1 ^= s1 << 23;
78+
return (s_[1] = (s1 ^ s0 ^ (s1 >> 17) ^ (s0 >> 26))) + s0;
79+
}
4880

49-
static result_type constexpr min()
81+
static constexpr result_type
82+
min() noexcept
5083
{
5184
return std::numeric_limits<result_type>::min();
5285
}
5386

54-
static result_type constexpr max()
87+
static constexpr result_type
88+
max() noexcept
5589
{
5690
return std::numeric_limits<result_type>::max();
5791
}
5892

5993
private:
60-
result_type s_[2];
61-
62-
static result_type
63-
murmurhash3(result_type x);
94+
std::array<result_type, 2> s_;
6495
};
6596

66-
template <class _>
67-
xor_shift_engine<_>::xor_shift_engine(result_type val)
68-
{
69-
seed(val);
70-
}
71-
72-
template <class _>
73-
void
74-
xor_shift_engine<_>::seed(result_type seed)
75-
{
76-
if (seed == 0)
77-
throw std::domain_error("invalid seed");
78-
s_[0] = murmurhash3(seed);
79-
s_[1] = murmurhash3(s_[0]);
80-
}
81-
82-
template <class _>
83-
auto
84-
xor_shift_engine<_>::operator()() -> result_type
85-
{
86-
result_type s1 = s_[0];
87-
result_type const s0 = s_[1];
88-
s_[0] = s0;
89-
s1 ^= s1 << 23;
90-
return (s_[1] = (s1 ^ s0 ^ (s1 >> 17) ^ (s0 >> 26))) + s0;
91-
}
92-
93-
template <class _>
94-
auto
95-
xor_shift_engine<_>::murmurhash3(result_type x) -> result_type
96-
{
97-
x ^= x >> 33;
98-
x *= 0xff51afd7ed558ccdULL;
99-
x ^= x >> 33;
100-
x *= 0xc4ceb9fe1a85ec53ULL;
101-
return x ^= x >> 33;
102-
}
103-
104-
} // namespace detail
105-
106-
/** XOR-shift Generator.
107-
108-
Meets the requirements of UniformRandomNumberGenerator.
109-
110-
Simple and fast RNG based on:
111-
http://xorshift.di.unimi.it/xorshift128plus.c
112-
does not accept seed==0
113-
*/
114-
using xor_shift_engine = detail::xor_shift_engine<>;
115-
11697
} // namespace beast
11798

11899
#endif

src/ripple/nodestore/backend/RWDBFactory.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,6 @@ class RWDBBackend : public Backend
2020
beast::Journal journal_;
2121
bool isOpen_{false};
2222

23-
struct base_uint_hasher
24-
{
25-
using result_type = std::size_t;
26-
27-
result_type
28-
operator()(base_uint<256> const& value) const
29-
{
30-
return hardened_hash<>{}(value);
31-
}
32-
};
33-
3423
using DataStore =
3524
std::map<uint256, std::vector<std::uint8_t>>; // Store compressed blob
3625
// data

0 commit comments

Comments
 (0)