aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/build-unix.md4
-rw-r--r--doc/gitian-building.md4
-rwxr-xr-xqa/pull-tester/rpc-tests.py4
-rwxr-xr-xqa/rpc-tests/test_framework/test_framework.py2
-rw-r--r--src/Makefile.bench.include3
-rw-r--r--src/bench/rollingbloom.cpp43
-rw-r--r--src/bloom.cpp40
-rw-r--r--src/bloom.h13
-rw-r--r--src/main.cpp23
-rw-r--r--src/main.h2
-rw-r--r--src/test/bloom_tests.cpp5
-rw-r--r--src/test/coins_tests.cpp3
-rw-r--r--src/txmempool.cpp4
13 files changed, 98 insertions, 52 deletions
diff --git a/doc/build-unix.md b/doc/build-unix.md
index 27c57088af..bd89978cc2 100644
--- a/doc/build-unix.md
+++ b/doc/build-unix.md
@@ -128,7 +128,7 @@ Dependency Build Instructions: Fedora
-------------------------------------
Build requirements:
- sudo dnf install libtool make autoconf automake openssl-devel libevent-devel boost-devel libdb4-devel libdb4-cxx-devel
+ sudo dnf install gcc-c++ libtool make autoconf automake openssl-devel libevent-devel boost-devel libdb4-devel libdb4-cxx-devel
Optional:
@@ -136,7 +136,7 @@ Optional:
To build with Qt 5 (recommended) you need the following:
- sudo dnf install qt5-qttools-devel qtr5-qtbase-devel protobuf-devel
+ sudo dnf install qt5-qttools-devel qt5-qtbase-devel protobuf-devel
libqrencode (optional) can be installed with:
diff --git a/doc/gitian-building.md b/doc/gitian-building.md
index 13f8ad316b..791f209bb1 100644
--- a/doc/gitian-building.md
+++ b/doc/gitian-building.md
@@ -443,8 +443,8 @@ Then when building, override the remote URLs that gbuild would otherwise pull fr
cd /some/root/path/
git clone https://github.com/bitcoin-core/bitcoin-detached-sigs.git
-BTCPATH=/some/root/path/bitcoin.git
-SIGPATH=/some/root/path/bitcoin-detached-sigs.git
+BTCPATH=/some/root/path/bitcoin
+SIGPATH=/some/root/path/bitcoin-detached-sigs
./bin/gbuild --url bitcoin=${BTCPATH},signature=${SIGPATH} ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml
```
diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py
index c6f91f8cb3..10c3799b86 100755
--- a/qa/pull-tester/rpc-tests.py
+++ b/qa/pull-tester/rpc-tests.py
@@ -90,9 +90,9 @@ if ENABLE_ZMQ:
try:
import zmq
except ImportError as e:
- print("ERROR: \"import zmq\" failed. Set ENABLE_ZMQ=0 or " \
+ print("WARNING: \"import zmq\" failed. Set ENABLE_ZMQ=0 or " \
"to run zmq tests, see dependency info in /qa/README.md.")
- raise e
+ ENABLE_ZMQ=0
#Tests
testScripts = [
diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py
index 103d9a068a..4e72463096 100755
--- a/qa/rpc-tests/test_framework/test_framework.py
+++ b/qa/rpc-tests/test_framework/test_framework.py
@@ -102,7 +102,7 @@ class BitcoinTestFramework(object):
help="Leave bitcoinds and test.* datadir on exit or error")
parser.add_option("--noshutdown", dest="noshutdown", default=False, action="store_true",
help="Don't stop bitcoinds after the test execution")
- parser.add_option("--srcdir", dest="srcdir", default="../../src",
+ parser.add_option("--srcdir", dest="srcdir", default=os.path.normpath(os.path.dirname(os.path.realpath(__file__))+"/../../../src"),
help="Source directory containing bitcoind/bitcoin-cli (default: %default)")
parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"),
help="Root directory for datadirs")
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index 8e7b59b461..24e2b3e0c8 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -7,7 +7,8 @@ bench_bench_bitcoin_SOURCES = \
bench/bench_bitcoin.cpp \
bench/bench.cpp \
bench/bench.h \
- bench/Examples.cpp
+ bench/Examples.cpp \
+ bench/rollingbloom.cpp
bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/
bench_bench_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
diff --git a/src/bench/rollingbloom.cpp b/src/bench/rollingbloom.cpp
new file mode 100644
index 0000000000..73c02cf718
--- /dev/null
+++ b/src/bench/rollingbloom.cpp
@@ -0,0 +1,43 @@
+// Copyright (c) 2016 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <iostream>
+
+#include "bench.h"
+#include "bloom.h"
+#include "utiltime.h"
+
+static void RollingBloom(benchmark::State& state)
+{
+ CRollingBloomFilter filter(120000, 0.000001);
+ std::vector<unsigned char> data(32);
+ uint32_t count = 0;
+ uint32_t nEntriesPerGeneration = (120000 + 1) / 2;
+ uint32_t countnow = 0;
+ uint64_t match = 0;
+ while (state.KeepRunning()) {
+ count++;
+ data[0] = count;
+ data[1] = count >> 8;
+ data[2] = count >> 16;
+ data[3] = count >> 24;
+ if (countnow == nEntriesPerGeneration) {
+ int64_t b = GetTimeMicros();
+ filter.insert(data);
+ int64_t e = GetTimeMicros();
+ std::cout << "RollingBloom-refresh,1," << (e-b)*0.000001 << "," << (e-b)*0.000001 << "," << (e-b)*0.000001 << "\n";
+ countnow = 0;
+ } else {
+ filter.insert(data);
+ }
+ countnow++;
+ data[0] = count >> 24;
+ data[1] = count >> 16;
+ data[2] = count >> 8;
+ data[3] = count;
+ match += filter.contains(data);
+ }
+}
+
+BENCHMARK(RollingBloom);
diff --git a/src/bloom.cpp b/src/bloom.cpp
index 4e6f0e5d2d..fd328e8e96 100644
--- a/src/bloom.cpp
+++ b/src/bloom.cpp
@@ -234,14 +234,18 @@ CRollingBloomFilter::CRollingBloomFilter(unsigned int nElements, double fpRate)
*/
uint32_t nFilterBits = (uint32_t)ceil(-1.0 * nHashFuncs * nMaxElements / log(1.0 - exp(logFpRate / nHashFuncs)));
data.clear();
- /* We store up to 16 'bits' per data element. */
- data.resize((nFilterBits + 15) / 16);
+ /* For each data element we need to store 2 bits. If both bits are 0, the
+ * bit is treated as unset. If the bits are (01), (10), or (11), the bit is
+ * treated as set in generation 1, 2, or 3 respectively.
+ * These bits are stored in separate integers: position P corresponds to bit
+ * (P & 63) of the integers data[(P >> 6) * 2] and data[(P >> 6) * 2 + 1]. */
+ data.resize(((nFilterBits + 63) / 64) << 1);
reset();
}
/* Similar to CBloomFilter::Hash */
-inline unsigned int CRollingBloomFilter::Hash(unsigned int nHashNum, const std::vector<unsigned char>& vDataToHash) const {
- return MurmurHash3(nHashNum * 0xFBA4C795 + nTweak, vDataToHash) % (data.size() * 16);
+static inline uint32_t RollingBloomHash(unsigned int nHashNum, uint32_t nTweak, const std::vector<unsigned char>& vDataToHash) {
+ return MurmurHash3(nHashNum * 0xFBA4C795 + nTweak, vDataToHash);
}
void CRollingBloomFilter::insert(const std::vector<unsigned char>& vKey)
@@ -252,18 +256,25 @@ void CRollingBloomFilter::insert(const std::vector<unsigned char>& vKey)
if (nGeneration == 4) {
nGeneration = 1;
}
+ uint64_t nGenerationMask1 = -(uint64_t)(nGeneration & 1);
+ uint64_t nGenerationMask2 = -(uint64_t)(nGeneration >> 1);
/* Wipe old entries that used this generation number. */
- for (uint32_t p = 0; p < data.size() * 16; p++) {
- if (get(p) == nGeneration) {
- put(p, 0);
- }
+ for (uint32_t p = 0; p < data.size(); p += 2) {
+ uint64_t p1 = data[p], p2 = data[p + 1];
+ uint64_t mask = (p1 ^ nGenerationMask1) | (p2 ^ nGenerationMask2);
+ data[p] = p1 & mask;
+ data[p + 1] = p2 & mask;
}
}
nEntriesThisGeneration++;
for (int n = 0; n < nHashFuncs; n++) {
- uint32_t h = Hash(n, vKey);
- put(h, nGeneration);
+ uint32_t h = RollingBloomHash(n, nTweak, vKey);
+ int bit = h & 0x3F;
+ uint32_t pos = (h >> 6) % data.size();
+ /* The lowest bit of pos is ignored, and set to zero for the first bit, and to one for the second. */
+ data[pos & ~1] = (data[pos & ~1] & ~(((uint64_t)1) << bit)) | ((uint64_t)(nGeneration & 1)) << bit;
+ data[pos | 1] = (data[pos | 1] & ~(((uint64_t)1) << bit)) | ((uint64_t)(nGeneration >> 1)) << bit;
}
}
@@ -276,8 +287,11 @@ void CRollingBloomFilter::insert(const uint256& hash)
bool CRollingBloomFilter::contains(const std::vector<unsigned char>& vKey) const
{
for (int n = 0; n < nHashFuncs; n++) {
- uint32_t h = Hash(n, vKey);
- if (get(h) == 0) {
+ uint32_t h = RollingBloomHash(n, nTweak, vKey);
+ int bit = h & 0x3F;
+ uint32_t pos = (h >> 6) % data.size();
+ /* If the relevant bit is not set in either data[pos & ~1] or data[pos | 1], the filter does not contain vKey */
+ if (!(((data[pos & ~1] | data[pos | 1]) >> bit) & 1)) {
return false;
}
}
@@ -295,7 +309,7 @@ void CRollingBloomFilter::reset()
nTweak = GetRand(std::numeric_limits<unsigned int>::max());
nEntriesThisGeneration = 0;
nGeneration = 1;
- for (std::vector<uint32_t>::iterator it = data.begin(); it != data.end(); it++) {
+ for (std::vector<uint64_t>::iterator it = data.begin(); it != data.end(); it++) {
*it = 0;
}
}
diff --git a/src/bloom.h b/src/bloom.h
index b0ad8b875d..ad6de625d8 100644
--- a/src/bloom.h
+++ b/src/bloom.h
@@ -135,20 +135,9 @@ private:
int nEntriesPerGeneration;
int nEntriesThisGeneration;
int nGeneration;
- std::vector<uint32_t> data;
+ std::vector<uint64_t> data;
unsigned int nTweak;
int nHashFuncs;
-
- unsigned int Hash(unsigned int nHashNum, const std::vector<unsigned char>& vDataToHash) const;
-
- inline int get(uint32_t position) const {
- return (data[(position >> 4) % data.size()] >> (2 * (position & 0xF))) & 0x3;
- }
-
- inline void put(uint32_t position, uint32_t val) {
- uint32_t& cell = data[(position >> 4) % data.size()];
- cell = (cell & ~(((uint32_t)3) << (2 * (position & 0xF)))) | (val << (2 * (position & 0xF)));
- }
};
#endif // BITCOIN_BLOOM_H
diff --git a/src/main.cpp b/src/main.cpp
index 92a38f230f..ebe91f7fa9 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1593,7 +1593,7 @@ bool fLargeWorkForkFound = false;
bool fLargeWorkInvalidChainFound = false;
CBlockIndex *pindexBestForkTip = NULL, *pindexBestForkBase = NULL;
-static void AlertNotify(const std::string& strMessage, bool fThread)
+static void AlertNotify(const std::string& strMessage)
{
uiInterface.NotifyAlertChanged();
std::string strCmd = GetArg("-alertnotify", "");
@@ -1607,10 +1607,7 @@ static void AlertNotify(const std::string& strMessage, bool fThread)
safeStatus = singleQuote+safeStatus+singleQuote;
boost::replace_all(strCmd, "%s", safeStatus);
- if (fThread)
- boost::thread t(runCommand, strCmd); // thread runs free
- else
- runCommand(strCmd);
+ boost::thread t(runCommand, strCmd); // thread runs free
}
void CheckForkWarningConditions()
@@ -1632,7 +1629,7 @@ void CheckForkWarningConditions()
{
std::string warning = std::string("'Warning: Large-work fork detected, forking after block ") +
pindexBestForkBase->phashBlock->ToString() + std::string("'");
- AlertNotify(warning, true);
+ AlertNotify(warning);
}
if (pindexBestForkTip && pindexBestForkBase)
{
@@ -1744,7 +1741,7 @@ void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state
}
}
-void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight)
+void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txundo, int nHeight)
{
// mark inputs spent
if (!tx.IsCoinBase()) {
@@ -1770,10 +1767,10 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
inputs.ModifyNewCoins(tx.GetHash(), tx.IsCoinBase())->FromTx(tx, nHeight);
}
-void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, int nHeight)
+void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight)
{
CTxUndo txundo;
- UpdateCoins(tx, state, inputs, txundo, nHeight);
+ UpdateCoins(tx, inputs, txundo, nHeight);
}
bool CScriptCheck::operator()() {
@@ -2163,7 +2160,7 @@ void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const
if (!strWarning.empty())
{
strMiscWarning = strWarning;
- AlertNotify(strWarning, true);
+ AlertNotify(strWarning);
lastAlertTime = now;
}
}
@@ -2385,7 +2382,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
if (i > 0) {
blockundo.vtxundo.push_back(CTxUndo());
}
- UpdateCoins(tx, state, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight);
+ UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight);
vPos.push_back(std::make_pair(tx.GetHash(), pos));
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
@@ -2598,7 +2595,7 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) {
if (state == THRESHOLD_ACTIVE) {
strMiscWarning = strprintf(_("Warning: unknown new rules activated (versionbit %i)"), bit);
if (!fWarned) {
- AlertNotify(strMiscWarning, true);
+ AlertNotify(strMiscWarning);
fWarned = true;
}
} else {
@@ -2620,7 +2617,7 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) {
// strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user:
strMiscWarning = _("Warning: Unknown block versions being mined! It's possible unknown rules are in effect");
if (!fWarned) {
- AlertNotify(strMiscWarning, true);
+ AlertNotify(strMiscWarning);
fWarned = true;
}
}
diff --git a/src/main.h b/src/main.h
index bdf7f5a687..3cc16fd8f4 100644
--- a/src/main.h
+++ b/src/main.h
@@ -338,7 +338,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
unsigned int flags, bool cacheStore, std::vector<CScriptCheck> *pvChecks = NULL);
/** Apply the effects of this transaction on the UTXO set represented by view */
-void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, int nHeight);
+void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight);
/** Context-independent validity checks */
bool CheckTransaction(const CTransaction& tx, CValidationState& state);
diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp
index 9557000ddc..042fad42da 100644
--- a/src/test/bloom_tests.cpp
+++ b/src/test/bloom_tests.cpp
@@ -514,11 +514,14 @@ BOOST_AUTO_TEST_CASE(rolling_bloom)
if (i >= 100)
BOOST_CHECK(rb1.contains(data[i-100]));
rb1.insert(data[i]);
+ BOOST_CHECK(rb1.contains(data[i]));
}
// Insert 999 more random entries:
for (int i = 0; i < 999; i++) {
- rb1.insert(RandomData());
+ std::vector<unsigned char> d = RandomData();
+ rb1.insert(d);
+ BOOST_CHECK(rb1.contains(d));
}
// Sanity check to make sure the filter isn't just filling up:
nHits = 0;
diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp
index 129ce04e0b..e692326559 100644
--- a/src/test/coins_tests.cpp
+++ b/src/test/coins_tests.cpp
@@ -297,8 +297,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
CCoins &coins = result[tx.GetHash()];
coins.FromTx(tx, height);
- CValidationState dummy;
- UpdateCoins(tx, dummy, *(stack.back()), height);
+ UpdateCoins(tx, *(stack.back()), height);
}
// Once every 1000 iterations and at the end, verify the full cache.
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index a6070f5264..aa5df6ca4e 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -720,7 +720,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
else {
CValidationState state;
assert(CheckInputs(tx, state, mempoolDuplicate, false, 0, false, NULL));
- UpdateCoins(tx, state, mempoolDuplicate, 1000000);
+ UpdateCoins(tx, mempoolDuplicate, 1000000);
}
}
unsigned int stepsSinceLastRemove = 0;
@@ -734,7 +734,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
assert(stepsSinceLastRemove < waitingOnDependants.size());
} else {
assert(CheckInputs(entry->GetTx(), state, mempoolDuplicate, false, 0, false, NULL));
- UpdateCoins(entry->GetTx(), state, mempoolDuplicate, 1000000);
+ UpdateCoins(entry->GetTx(), mempoolDuplicate, 1000000);
stepsSinceLastRemove = 0;
}
}