From b5462f52460e7c4f982dec8396e46b5928c638a3 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Tue, 26 Feb 2019 14:13:19 +0100 Subject: [PATCH] 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. --- src/Makefile.am | 2 ++ src/saltedhasher.cpp | 12 +++++++ src/saltedhasher.h | 75 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 src/saltedhasher.cpp create mode 100644 src/saltedhasher.h diff --git a/src/Makefile.am b/src/Makefile.am index b295405a5..04a5efa3a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -201,6 +201,7 @@ BITCOIN_CORE_H = \ rpc/protocol.h \ rpc/server.h \ rpc/register.h \ + saltedhasher.h \ scheduler.h \ script/sigcache.h \ script/sign.h \ @@ -463,6 +464,7 @@ libdash_common_a_SOURCES = \ netaddress.cpp \ netbase.cpp \ protocol.cpp \ + saltedhasher.cpp \ scheduler.cpp \ script/sign.cpp \ script/standard.cpp \ diff --git a/src/saltedhasher.cpp b/src/saltedhasher.cpp new file mode 100644 index 000000000..ec3c819f2 --- /dev/null +++ b/src/saltedhasher.cpp @@ -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 + +SaltedHasherBase::SaltedHasherBase() : k0(GetRand(std::numeric_limits::max())), k1(GetRand(std::numeric_limits::max())) {} + +SaltedHasherBase StaticSaltedHasher::s; diff --git a/src/saltedhasher.h b/src/saltedhasher.h new file mode 100644 index 000000000..ffd5cd638 --- /dev/null +++ b/src/saltedhasher.h @@ -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 struct SaltedHasherImpl; + +template +struct SaltedHasherImpl> +{ + static std::size_t CalcHash(const std::pair& v, uint64_t k0, uint64_t k1) + { + return SipHashUint256Extra(k0, k1, v.first, (uint32_t) v.second); + } +}; + +template +struct SaltedHasherImpl> +{ + static std::size_t CalcHash(const std::pair& v, uint64_t k0, uint64_t k1) + { + return SipHashUint256Extra(k0, k1, v.second, (uint32_t) v.first); + } +}; + +template<> +struct SaltedHasherImpl +{ + 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 +struct SaltedHasher +{ + S s; + std::size_t operator()(const T& v) const + { + return SaltedHasherImpl::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 + std::size_t operator()(const T& v) const + { + return SaltedHasherImpl::CalcHash(v, s.k0, s.k1); + } +}; + +#endif//SALTEDHASHER_H