Implement std::unordered_map/set compatible hasher classes for salted hashes

Allows convenient salted hashing with unordered maps and sets. Useful when
there is a risk of unbalanced hash buckets slowing things down, e.g. when
externally supplied hashes are used as keys into a map.
This commit is contained in:
Alexander Block 2019-02-26 14:13:19 +01:00
parent c52e8402c0
commit b5462f5246
3 changed files with 89 additions and 0 deletions

View File

@ -201,6 +201,7 @@ BITCOIN_CORE_H = \
rpc/protocol.h \ rpc/protocol.h \
rpc/server.h \ rpc/server.h \
rpc/register.h \ rpc/register.h \
saltedhasher.h \
scheduler.h \ scheduler.h \
script/sigcache.h \ script/sigcache.h \
script/sign.h \ script/sign.h \
@ -463,6 +464,7 @@ libdash_common_a_SOURCES = \
netaddress.cpp \ netaddress.cpp \
netbase.cpp \ netbase.cpp \
protocol.cpp \ protocol.cpp \
saltedhasher.cpp \
scheduler.cpp \ scheduler.cpp \
script/sign.cpp \ script/sign.cpp \
script/standard.cpp \ script/standard.cpp \

12
src/saltedhasher.cpp Normal file
View File

@ -0,0 +1,12 @@
// Copyright (c) 2019 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "saltedhasher.h"
#include "random.h"
#include <limits>
SaltedHasherBase::SaltedHasherBase() : k0(GetRand(std::numeric_limits<uint64_t>::max())), k1(GetRand(std::numeric_limits<uint64_t>::max())) {}
SaltedHasherBase StaticSaltedHasher::s;

75
src/saltedhasher.h Normal file
View File

@ -0,0 +1,75 @@
// Copyright (c) 2019 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef SALTEDHASHER_H
#define SALTEDHASHER_H
#include "hash.h"
#include "uint256.h"
/** Helper classes for std::unordered_map and std::unordered_set hashing */
template<typename T> struct SaltedHasherImpl;
template<typename N>
struct SaltedHasherImpl<std::pair<uint256, N>>
{
static std::size_t CalcHash(const std::pair<uint256, N>& v, uint64_t k0, uint64_t k1)
{
return SipHashUint256Extra(k0, k1, v.first, (uint32_t) v.second);
}
};
template<typename N>
struct SaltedHasherImpl<std::pair<N, uint256>>
{
static std::size_t CalcHash(const std::pair<N, uint256>& v, uint64_t k0, uint64_t k1)
{
return SipHashUint256Extra(k0, k1, v.second, (uint32_t) v.first);
}
};
template<>
struct SaltedHasherImpl<uint256>
{
static std::size_t CalcHash(const uint256& v, uint64_t k0, uint64_t k1)
{
return SipHashUint256(k0, k1, v);
}
};
struct SaltedHasherBase
{
/** Salt */
const uint64_t k0, k1;
SaltedHasherBase();
};
/* Allows each instance of unordered maps/sest to have their own salt */
template<typename T, typename S>
struct SaltedHasher
{
S s;
std::size_t operator()(const T& v) const
{
return SaltedHasherImpl<T>::CalcHash(v, s.k0, s.k1);
}
};
/* Allows to use a static salt for all instances. The salt is a random value set at startup
* (through static initialization)
*/
struct StaticSaltedHasher
{
static SaltedHasherBase s;
template<typename T>
std::size_t operator()(const T& v) const
{
return SaltedHasherImpl<T>::CalcHash(v, s.k0, s.k1);
}
};
#endif//SALTEDHASHER_H