Skip to content

Commit

Permalink
Implement std::unordered_map/set compatible hasher classes for salted…
Browse files Browse the repository at this point in the history
… 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.
  • Loading branch information
codablock committed Feb 27, 2019
1 parent c52e840 commit b5462f5
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down Expand Up @@ -463,6 +464,7 @@ libdash_common_a_SOURCES = \
netaddress.cpp \
netbase.cpp \
protocol.cpp \
saltedhasher.cpp \
scheduler.cpp \
script/sign.cpp \
script/standard.cpp \
Expand Down
12 changes: 12 additions & 0 deletions src/saltedhasher.cpp
Original file line number Diff line number Diff line change
@@ -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 changes: 75 additions & 0 deletions src/saltedhasher.h
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit b5462f5

Please sign in to comment.