aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2016-05-06 20:47:12 +0200
committerPieter Wuille <pieter.wuille@gmail.com>2016-05-17 20:04:46 +0200
commit382c871d28b95cc52309a128edd8dc23822bcd60 (patch)
treeb1a769dd5188ad4785e73006941b4f20d5fdc82f
parent0b1295b066b9369decb2e664e60b0129dbc30dfb (diff)
downloadbitcoin-382c871d28b95cc52309a128edd8dc23822bcd60.tar.xz
Use SipHash-2-4 for CCoinsCache index
This is ~1.7x slower than the Lookup3-of-Xor-with-salt construct we were using before, but it is a primitive designed for exactly this.
-rw-r--r--src/coins.cpp6
-rw-r--r--src/coins.h14
-rw-r--r--src/uint256.cpp64
-rw-r--r--src/uint256.h5
4 files changed, 13 insertions, 76 deletions
diff --git a/src/coins.cpp b/src/coins.cpp
index 1c329740b4..b7dd293d69 100644
--- a/src/coins.cpp
+++ b/src/coins.cpp
@@ -56,7 +56,11 @@ void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
CCoinsViewCursor *CCoinsViewBacked::Cursor() const { return base->Cursor(); }
-CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {}
+SaltedTxidHasher::SaltedTxidHasher()
+{
+ GetRandBytes((unsigned char*)&k0, sizeof(k0));
+ GetRandBytes((unsigned char*)&k1, sizeof(k1));
+}
CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), hasModifier(false), cachedCoinsUsage(0) { }
diff --git a/src/coins.h b/src/coins.h
index d72f885473..1dd908700b 100644
--- a/src/coins.h
+++ b/src/coins.h
@@ -8,6 +8,7 @@
#include "compressor.h"
#include "core_memusage.h"
+#include "hash.h"
#include "memusage.h"
#include "serialize.h"
#include "uint256.h"
@@ -264,21 +265,22 @@ public:
}
};
-class CCoinsKeyHasher
+class SaltedTxidHasher
{
private:
- uint256 salt;
+ /** Salt */
+ uint64_t k0, k1;
public:
- CCoinsKeyHasher();
+ SaltedTxidHasher();
/**
* This *must* return size_t. With Boost 1.46 on 32-bit systems the
* unordered_map will behave unpredictably if the custom hasher returns a
* uint64_t, resulting in failures when syncing the chain (#4634).
*/
- size_t operator()(const uint256& key) const {
- return key.GetHash(salt);
+ size_t operator()(const uint256& txid) const {
+ return SipHashUint256(k0, k1, txid);
}
};
@@ -295,7 +297,7 @@ struct CCoinsCacheEntry
CCoinsCacheEntry() : coins(), flags(0) {}
};
-typedef boost::unordered_map<uint256, CCoinsCacheEntry, CCoinsKeyHasher> CCoinsMap;
+typedef boost::unordered_map<uint256, CCoinsCacheEntry, SaltedTxidHasher> CCoinsMap;
/** Cursor for iterating over CoinsView state */
class CCoinsViewCursor
diff --git a/src/uint256.cpp b/src/uint256.cpp
index c58c88bf4a..f22ddcd1ef 100644
--- a/src/uint256.cpp
+++ b/src/uint256.cpp
@@ -80,67 +80,3 @@ template std::string base_blob<256>::GetHex() const;
template std::string base_blob<256>::ToString() const;
template void base_blob<256>::SetHex(const char*);
template void base_blob<256>::SetHex(const std::string&);
-
-static void inline HashMix(uint32_t& a, uint32_t& b, uint32_t& c)
-{
- // Taken from lookup3, by Bob Jenkins.
- a -= c;
- a ^= ((c << 4) | (c >> 28));
- c += b;
- b -= a;
- b ^= ((a << 6) | (a >> 26));
- a += c;
- c -= b;
- c ^= ((b << 8) | (b >> 24));
- b += a;
- a -= c;
- a ^= ((c << 16) | (c >> 16));
- c += b;
- b -= a;
- b ^= ((a << 19) | (a >> 13));
- a += c;
- c -= b;
- c ^= ((b << 4) | (b >> 28));
- b += a;
-}
-
-static void inline HashFinal(uint32_t& a, uint32_t& b, uint32_t& c)
-{
- // Taken from lookup3, by Bob Jenkins.
- c ^= b;
- c -= ((b << 14) | (b >> 18));
- a ^= c;
- a -= ((c << 11) | (c >> 21));
- b ^= a;
- b -= ((a << 25) | (a >> 7));
- c ^= b;
- c -= ((b << 16) | (b >> 16));
- a ^= c;
- a -= ((c << 4) | (c >> 28));
- b ^= a;
- b -= ((a << 14) | (a >> 18));
- c ^= b;
- c -= ((b << 24) | (b >> 8));
-}
-
-uint64_t uint256::GetHash(const uint256& salt) const
-{
- uint32_t a, b, c;
- const uint32_t *pn = (const uint32_t*)data;
- const uint32_t *salt_pn = (const uint32_t*)salt.data;
- a = b = c = 0xdeadbeef + WIDTH;
-
- a += pn[0] ^ salt_pn[0];
- b += pn[1] ^ salt_pn[1];
- c += pn[2] ^ salt_pn[2];
- HashMix(a, b, c);
- a += pn[3] ^ salt_pn[3];
- b += pn[4] ^ salt_pn[4];
- c += pn[5] ^ salt_pn[5];
- HashMix(a, b, c);
- a += pn[6] ^ salt_pn[6];
- b += pn[7] ^ salt_pn[7];
- HashFinal(a, b, c);
-
- return ((((uint64_t)b) << 32) | c);
-}
diff --git a/src/uint256.h b/src/uint256.h
index af1f3ab7d9..dd8432d74c 100644
--- a/src/uint256.h
+++ b/src/uint256.h
@@ -140,11 +140,6 @@ public:
{
return ReadLE64(data);
}
-
- /** A more secure, salted hash function.
- * @note This hash is not stable between little and big endian.
- */
- uint64_t GetHash(const uint256& salt) const;
};
/* uint256 from const char *.