mirror of
https://github.com/wownero/wownero.git
synced 2026-10-17 07:31:35 +02:00
Optimize hashing of generic types
Use a proper hash function instead of f(x)=x to achieve better distribution of hash values (cherry picked from commit 5eeff1d9c15dfdce6ade9bed455e8fdaab777b31)
This commit is contained in:
@@ -32,9 +32,13 @@
|
|||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sodium/crypto_verify_32.h>
|
#include <sodium/crypto_verify_32.h>
|
||||||
|
#include <sodium/crypto_shorthash_siphash24.h>
|
||||||
|
|
||||||
|
#include "random.h"
|
||||||
|
|
||||||
#define CRYPTO_MAKE_COMPARABLE(type) \
|
#define CRYPTO_MAKE_COMPARABLE(type) \
|
||||||
namespace crypto { \
|
namespace crypto { \
|
||||||
@@ -57,22 +61,29 @@ namespace crypto { \
|
|||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace crypto {
|
||||||
|
inline std::size_t siphash_to_size_t(const void *data, std::size_t length) {
|
||||||
|
static_assert(sizeof(crypto_siphash_key) == crypto_shorthash_siphash24_KEYBYTES,
|
||||||
|
"crypto_siphash_key size must match the SipHash-2-4 key length");
|
||||||
|
static_assert(sizeof(std::uint64_t) == crypto_shorthash_siphash24_BYTES,
|
||||||
|
"std::uint64_t size must match the SipHash-2-4 digest length");
|
||||||
|
std::uint64_t h;
|
||||||
|
crypto_shorthash_siphash24(reinterpret_cast<unsigned char*>(&h), static_cast<const unsigned char*>(data), length, crypto_siphash_key);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define CRYPTO_DEFINE_HASH_FUNCTIONS(type) \
|
#define CRYPTO_DEFINE_HASH_FUNCTIONS(type) \
|
||||||
namespace crypto { \
|
namespace crypto { \
|
||||||
static_assert(sizeof(std::size_t) <= sizeof(type), "Size of " #type " must be at least that of size_t"); \
|
|
||||||
inline std::size_t hash_value(const type &_v) { \
|
inline std::size_t hash_value(const type &_v) { \
|
||||||
std::size_t h; \
|
return siphash_to_size_t(std::addressof(_v), sizeof(_v)); \
|
||||||
memcpy(&h, std::addressof(_v), sizeof(h)); \
|
|
||||||
return h; \
|
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
namespace std { \
|
namespace std { \
|
||||||
template<> \
|
template<> \
|
||||||
struct hash<crypto::type> { \
|
struct hash<crypto::type> { \
|
||||||
std::size_t operator()(const crypto::type &_v) const { \
|
std::size_t operator()(const crypto::type &_v) const { \
|
||||||
std::size_t h; \
|
return ::crypto::siphash_to_size_t(std::addressof(_v), sizeof(_v)); \
|
||||||
memcpy(&h, std::addressof(_v), sizeof(h)); \
|
|
||||||
return h; \
|
|
||||||
} \
|
} \
|
||||||
}; \
|
}; \
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ static void generate_system_random_bytes(size_t n, void *result) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static union hash_state state;
|
static union hash_state state;
|
||||||
|
unsigned char crypto_siphash_key[16];
|
||||||
|
|
||||||
#if !defined(NDEBUG)
|
#if !defined(NDEBUG)
|
||||||
static volatile int curstate; /* To catch thread safety problems. */
|
static volatile int curstate; /* To catch thread safety problems. */
|
||||||
@@ -107,10 +108,12 @@ FINALIZER(deinit_random) {
|
|||||||
curstate = 0;
|
curstate = 0;
|
||||||
#endif
|
#endif
|
||||||
memset(&state, 0, sizeof(union hash_state));
|
memset(&state, 0, sizeof(union hash_state));
|
||||||
|
memset(crypto_siphash_key, 0, sizeof(crypto_siphash_key));
|
||||||
}
|
}
|
||||||
|
|
||||||
INITIALIZER(init_random) {
|
INITIALIZER(init_random) {
|
||||||
generate_system_random_bytes(32, &state);
|
generate_system_random_bytes(32, &state);
|
||||||
|
generate_system_random_bytes(sizeof(crypto_siphash_key), crypto_siphash_key);
|
||||||
REGISTER_FINALIZER(deinit_random);
|
REGISTER_FINALIZER(deinit_random);
|
||||||
#if !defined(NDEBUG)
|
#if !defined(NDEBUG)
|
||||||
assert(curstate == 0);
|
assert(curstate == 0);
|
||||||
|
|||||||
@@ -32,5 +32,15 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
void generate_random_bytes_not_thread_safe(size_t n, void *result);
|
void generate_random_bytes_not_thread_safe(size_t n, void *result);
|
||||||
void add_extra_entropy_not_thread_safe(const void *ptr, size_t bytes);
|
void add_extra_entropy_not_thread_safe(const void *ptr, size_t bytes);
|
||||||
|
|
||||||
|
extern unsigned char crypto_siphash_key[16];
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -789,7 +789,7 @@ inline std::ostream &operator <<(std::ostream &o, const rct::key &v) {
|
|||||||
|
|
||||||
namespace std
|
namespace std
|
||||||
{
|
{
|
||||||
template<> struct hash<rct::key> { std::size_t operator()(const rct::key &k) const { return reinterpret_cast<const std::size_t&>(k); } };
|
template<> struct hash<rct::key> { std::size_t operator()(const rct::key &k) const { return ::crypto::siphash_to_size_t(&k, sizeof(k)); } };
|
||||||
}
|
}
|
||||||
|
|
||||||
BLOB_SERIALIZER(rct::key);
|
BLOB_SERIALIZER(rct::key);
|
||||||
|
|||||||
Reference in New Issue
Block a user