From bc42503f6ab304608c321986a870795e45f5a016 Mon Sep 17 00:00:00 2001
From: Pieter Wuille <pieter.wuille@gmail.com>
Date: Wed, 9 Jul 2014 17:25:09 +0200
Subject: [PATCH] Use unordered_map for CCoinsViewCache with salted hash

---
 src/coins.cpp   |  8 ++++++--
 src/coins.h     | 15 ++++++++++++++-
 src/uint256.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++
 src/uint256.h   |  4 +++-
 4 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/src/coins.cpp b/src/coins.cpp
index 13a4ea95c..e76d8c7ef 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 c57a5ec72..9f90fe6bd 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 3392f1e9b..08c05594f 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 82db7758c..ad0a56f44 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