aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2014-07-09 17:25:09 +0200
committerPieter Wuille <pieter.wuille@gmail.com>2014-07-14 16:13:08 +0200
commitbc42503f6ab304608c321986a870795e45f5a016 (patch)
treecbb104bd5010fd817a460c89b10470e8b60f9ea7
parentbdd5b587fc7fd1b4dda479c4aad15c874b22e8f3 (diff)
Use unordered_map for CCoinsViewCache with salted hash
-rw-r--r--src/coins.cpp8
-rw-r--r--src/coins.h15
-rw-r--r--src/uint256.cpp43
-rw-r--r--src/uint256.h4
4 files changed, 66 insertions, 4 deletions
diff --git a/src/coins.cpp b/src/coins.cpp
index 13a4ea95cd..e76d8c7ef2 100644
--- a/src/coins.cpp
+++ b/src/coins.cpp
@@ -4,6 +4,8 @@
#include "coins.h"
+#include "random.h"
+
#include <assert.h>
// calculate number of bytes for the bitmask, and its number of non-zero bytes
@@ -69,6 +71,8 @@ void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
bool CCoinsViewBacked::BatchWrite(const CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
bool CCoinsViewBacked::GetStats(CCoinsStats &stats) { return base->GetStats(stats); }
+CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {}
+
CCoinsViewCache::CCoinsViewCache(CCoinsView &baseIn, bool fDummy) : CCoinsViewBacked(baseIn), hashBlock(0) { }
bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) {
@@ -84,8 +88,8 @@ bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) {
}
CCoinsMap::iterator CCoinsViewCache::FetchCoins(const uint256 &txid) {
- CCoinsMap::iterator it = cacheCoins.lower_bound(txid);
- if (it != cacheCoins.end() && it->first == txid)
+ CCoinsMap::iterator it = cacheCoins.find(txid);
+ if (it != cacheCoins.end())
return it;
CCoins tmp;
if (!base->GetCoins(txid,tmp))
diff --git a/src/coins.h b/src/coins.h
index c57a5ec722..9f90fe6bd0 100644
--- a/src/coins.h
+++ b/src/coins.h
@@ -13,6 +13,7 @@
#include <stdint.h>
#include <boost/foreach.hpp>
+#include <boost/unordered_map.hpp>
/** pruned version of CTransaction: only retains metadata and unspent transaction outputs
*
@@ -239,7 +240,19 @@ public:
}
};
-typedef std::map<uint256,CCoins> CCoinsMap;
+class CCoinsKeyHasher
+{
+private:
+ uint256 salt;
+
+public:
+ CCoinsKeyHasher();
+ uint64_t operator()(const uint256& key) const {
+ return key.GetHash(salt);
+ }
+};
+
+typedef boost::unordered_map<uint256, CCoins, CCoinsKeyHasher> CCoinsMap;
struct CCoinsStats
{
diff --git a/src/uint256.cpp b/src/uint256.cpp
index 3392f1e9bc..08c05594fd 100644
--- a/src/uint256.cpp
+++ b/src/uint256.cpp
@@ -290,3 +290,46 @@ uint32_t uint256::GetCompact(bool fNegative) const
nCompact |= (fNegative && (nCompact & 0x007fffff) ? 0x00800000 : 0);
return nCompact;
}
+
+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;
+ a = b = c = 0xdeadbeef + (WIDTH << 2);
+
+ 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 82db7758c9..ad0a56f447 100644
--- a/src/uint256.h
+++ b/src/uint256.h
@@ -21,7 +21,7 @@ public:
template<unsigned int BITS>
class base_uint
{
-private:
+protected:
enum { WIDTH=BITS/32 };
uint32_t pn[WIDTH];
public:
@@ -322,6 +322,8 @@ public:
// implementation accident.
uint256& SetCompact(uint32_t nCompact, bool *pfNegative = NULL, bool *pfOverflow = NULL);
uint32_t GetCompact(bool fNegative = false) const;
+
+ uint64_t GetHash(const uint256& salt) const;
};
#endif