aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/base58_tests.cpp2
-rw-r--r--src/test/blockencodings_tests.cpp6
-rw-r--r--src/test/cuckoocache_tests.cpp394
-rw-r--r--src/test/data/tx_valid.json2
-rw-r--r--src/test/mempool_tests.cpp42
-rw-r--r--src/test/miner_tests.cpp2
-rw-r--r--src/test/script_tests.cpp6
-rw-r--r--src/test/test_bitcoin.cpp4
-rw-r--r--src/test/test_bitcoin_fuzzy.cpp256
9 files changed, 684 insertions, 30 deletions
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp
index ac3ab4c83f..04a6506655 100644
--- a/src/test/base58_tests.cpp
+++ b/src/test/base58_tests.cpp
@@ -39,7 +39,7 @@ BOOST_AUTO_TEST_CASE(base58_EncodeBase58)
std::vector<unsigned char> sourcedata = ParseHex(test[0].get_str());
std::string base58string = test[1].get_str();
BOOST_CHECK_MESSAGE(
- EncodeBase58(begin_ptr(sourcedata), end_ptr(sourcedata)) == base58string,
+ EncodeBase58(sourcedata.data(), sourcedata.data() + sourcedata.size()) == base58string,
strTest);
}
}
diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp
index b013cda6d7..7478758f73 100644
--- a/src/test/blockencodings_tests.cpp
+++ b/src/test/blockencodings_tests.cpp
@@ -80,9 +80,9 @@ BOOST_AUTO_TEST_CASE(SimpleRoundTripTest)
BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1);
- std::vector<CTransactionRef> removed;
- pool.removeRecursive(*block.vtx[2], &removed);
- BOOST_CHECK_EQUAL(removed.size(), 1);
+ size_t poolSize = pool.size();
+ pool.removeRecursive(*block.vtx[2]);
+ BOOST_CHECK_EQUAL(pool.size(), poolSize - 1);
CBlock block2;
std::vector<CTransactionRef> vtx_missing;
diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp
new file mode 100644
index 0000000000..1bc50d5ea9
--- /dev/null
+++ b/src/test/cuckoocache_tests.cpp
@@ -0,0 +1,394 @@
+// Copyright (c) 2012-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 <boost/test/unit_test.hpp>
+#include "cuckoocache.h"
+#include "test/test_bitcoin.h"
+#include "random.h"
+#include <thread>
+#include <boost/thread.hpp>
+
+
+/** Test Suite for CuckooCache
+ *
+ * 1) All tests should have a deterministic result (using insecure rand
+ * with deterministic seeds)
+ * 2) Some test methods are templated to allow for easier testing
+ * against new versions / comparing
+ * 3) Results should be treated as a regression test, ie, did the behavior
+ * change significantly from what was expected. This can be OK, depending on
+ * the nature of the change, but requires updating the tests to reflect the new
+ * expected behavior. For example improving the hit rate may cause some tests
+ * using BOOST_CHECK_CLOSE to fail.
+ *
+ */
+FastRandomContext insecure_rand(true);
+
+BOOST_AUTO_TEST_SUITE(cuckoocache_tests);
+
+
+/** insecure_GetRandHash fills in a uint256 from insecure_rand
+ */
+void insecure_GetRandHash(uint256& t)
+{
+ uint32_t* ptr = (uint32_t*)t.begin();
+ for (uint8_t j = 0; j < 8; ++j)
+ *(ptr++) = insecure_rand.rand32();
+}
+
+/** Definition copied from /src/script/sigcache.cpp
+ */
+class uint256Hasher
+{
+public:
+ template <uint8_t hash_select>
+ uint32_t operator()(const uint256& key) const
+ {
+ static_assert(hash_select <8, "SignatureCacheHasher only has 8 hashes available.");
+ uint32_t u;
+ std::memcpy(&u, key.begin() + 4 * hash_select, 4);
+ return u;
+ }
+};
+
+
+/* Test that no values not inserted into the cache are read out of it.
+ *
+ * There are no repeats in the first 200000 insecure_GetRandHash calls
+ */
+BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes)
+{
+ insecure_rand = FastRandomContext(true);
+ CuckooCache::cache<uint256, uint256Hasher> cc{};
+ cc.setup_bytes(32 << 20);
+ uint256 v;
+ for (int x = 0; x < 100000; ++x) {
+ insecure_GetRandHash(v);
+ cc.insert(v);
+ }
+ for (int x = 0; x < 100000; ++x) {
+ insecure_GetRandHash(v);
+ BOOST_CHECK(!cc.contains(v, false));
+ }
+};
+
+/** This helper returns the hit rate when megabytes*load worth of entries are
+ * inserted into a megabytes sized cache
+ */
+template <typename Cache>
+double test_cache(size_t megabytes, double load)
+{
+ insecure_rand = FastRandomContext(true);
+ std::vector<uint256> hashes;
+ Cache set{};
+ size_t bytes = megabytes * (1 << 20);
+ set.setup_bytes(bytes);
+ uint32_t n_insert = static_cast<uint32_t>(load * (bytes / sizeof(uint256)));
+ hashes.resize(n_insert);
+ for (uint32_t i = 0; i < n_insert; ++i) {
+ uint32_t* ptr = (uint32_t*)hashes[i].begin();
+ for (uint8_t j = 0; j < 8; ++j)
+ *(ptr++) = insecure_rand.rand32();
+ }
+ /** We make a copy of the hashes because future optimizations of the
+ * cuckoocache may overwrite the inserted element, so the test is
+ * "future proofed".
+ */
+ std::vector<uint256> hashes_insert_copy = hashes;
+ /** Do the insert */
+ for (uint256& h : hashes_insert_copy)
+ set.insert(h);
+ /** Count the hits */
+ uint32_t count = 0;
+ for (uint256& h : hashes)
+ count += set.contains(h, false);
+ double hit_rate = ((double)count) / ((double)n_insert);
+ return hit_rate;
+}
+
+/** The normalized hit rate for a given load.
+ *
+ * The semantics are a little confusing, so please see the below
+ * explanation.
+ *
+ * Examples:
+ *
+ * 1) at load 0.5, we expect a perfect hit rate, so we multiply by
+ * 1.0
+ * 2) at load 2.0, we expect to see half the entries, so a perfect hit rate
+ * would be 0.5. Therefore, if we see a hit rate of 0.4, 0.4*2.0 = 0.8 is the
+ * normalized hit rate.
+ *
+ * This is basically the right semantics, but has a bit of a glitch depending on
+ * how you measure around load 1.0 as after load 1.0 your normalized hit rate
+ * becomes effectively perfect, ignoring freshness.
+ */
+double normalize_hit_rate(double hits, double load)
+{
+ return hits * std::max(load, 1.0);
+}
+
+/** Check the hit rate on loads ranging from 0.1 to 2.0 */
+BOOST_AUTO_TEST_CASE(cuckoocache_hit_rate_ok)
+{
+ /** Arbitrarily selected Hit Rate threshold that happens to work for this test
+ * as a lower bound on performance.
+ */
+ double HitRateThresh = 0.98;
+ size_t megabytes = 32;
+ for (double load = 0.1; load < 2; load *= 2) {
+ double hits = test_cache<CuckooCache::cache<uint256, uint256Hasher>>(megabytes, load);
+ BOOST_CHECK(normalize_hit_rate(hits, load) > HitRateThresh);
+ }
+}
+
+
+/** This helper checks that erased elements are preferentially inserted onto and
+ * that the hit rate of "fresher" keys is reasonable*/
+template <typename Cache>
+void test_cache_erase(size_t megabytes)
+{
+ double load = 1;
+ insecure_rand = FastRandomContext(true);
+ std::vector<uint256> hashes;
+ Cache set{};
+ size_t bytes = megabytes * (1 << 20);
+ set.setup_bytes(bytes);
+ uint32_t n_insert = static_cast<uint32_t>(load * (bytes / sizeof(uint256)));
+ hashes.resize(n_insert);
+ for (uint32_t i = 0; i < n_insert; ++i) {
+ uint32_t* ptr = (uint32_t*)hashes[i].begin();
+ for (uint8_t j = 0; j < 8; ++j)
+ *(ptr++) = insecure_rand.rand32();
+ }
+ /** We make a copy of the hashes because future optimizations of the
+ * cuckoocache may overwrite the inserted element, so the test is
+ * "future proofed".
+ */
+ std::vector<uint256> hashes_insert_copy = hashes;
+
+ /** Insert the first half */
+ for (uint32_t i = 0; i < (n_insert / 2); ++i)
+ set.insert(hashes_insert_copy[i]);
+ /** Erase the first quarter */
+ for (uint32_t i = 0; i < (n_insert / 4); ++i)
+ set.contains(hashes[i], true);
+ /** Insert the second half */
+ for (uint32_t i = (n_insert / 2); i < n_insert; ++i)
+ set.insert(hashes_insert_copy[i]);
+
+ /** elements that we marked erased but that are still there */
+ size_t count_erased_but_contained = 0;
+ /** elements that we did not erase but are older */
+ size_t count_stale = 0;
+ /** elements that were most recently inserted */
+ size_t count_fresh = 0;
+
+ for (uint32_t i = 0; i < (n_insert / 4); ++i)
+ count_erased_but_contained += set.contains(hashes[i], false);
+ for (uint32_t i = (n_insert / 4); i < (n_insert / 2); ++i)
+ count_stale += set.contains(hashes[i], false);
+ for (uint32_t i = (n_insert / 2); i < n_insert; ++i)
+ count_fresh += set.contains(hashes[i], false);
+
+ double hit_rate_erased_but_contained = double(count_erased_but_contained) / (double(n_insert) / 4.0);
+ double hit_rate_stale = double(count_stale) / (double(n_insert) / 4.0);
+ double hit_rate_fresh = double(count_fresh) / (double(n_insert) / 2.0);
+
+ // Check that our hit_rate_fresh is perfect
+ BOOST_CHECK_EQUAL(hit_rate_fresh, 1.0);
+ // Check that we have a more than 2x better hit rate on stale elements than
+ // erased elements.
+ BOOST_CHECK(hit_rate_stale > 2 * hit_rate_erased_but_contained);
+}
+
+BOOST_AUTO_TEST_CASE(cuckoocache_erase_ok)
+{
+ size_t megabytes = 32;
+ test_cache_erase<CuckooCache::cache<uint256, uint256Hasher>>(megabytes);
+}
+
+template <typename Cache>
+void test_cache_erase_parallel(size_t megabytes)
+{
+ double load = 1;
+ insecure_rand = FastRandomContext(true);
+ std::vector<uint256> hashes;
+ Cache set{};
+ size_t bytes = megabytes * (1 << 20);
+ set.setup_bytes(bytes);
+ uint32_t n_insert = static_cast<uint32_t>(load * (bytes / sizeof(uint256)));
+ hashes.resize(n_insert);
+ for (uint32_t i = 0; i < n_insert; ++i) {
+ uint32_t* ptr = (uint32_t*)hashes[i].begin();
+ for (uint8_t j = 0; j < 8; ++j)
+ *(ptr++) = insecure_rand.rand32();
+ }
+ /** We make a copy of the hashes because future optimizations of the
+ * cuckoocache may overwrite the inserted element, so the test is
+ * "future proofed".
+ */
+ std::vector<uint256> hashes_insert_copy = hashes;
+ boost::shared_mutex mtx;
+
+ {
+ /** Grab lock to make sure we release inserts */
+ boost::unique_lock<boost::shared_mutex> l(mtx);
+ /** Insert the first half */
+ for (uint32_t i = 0; i < (n_insert / 2); ++i)
+ set.insert(hashes_insert_copy[i]);
+ }
+
+ /** Spin up 3 threads to run contains with erase.
+ */
+ std::vector<std::thread> threads;
+ /** Erase the first quarter */
+ for (uint32_t x = 0; x < 3; ++x)
+ /** Each thread is emplaced with x copy-by-value
+ */
+ threads.emplace_back([&, x] {
+ boost::shared_lock<boost::shared_mutex> l(mtx);
+ size_t ntodo = (n_insert/4)/3;
+ size_t start = ntodo*x;
+ size_t end = ntodo*(x+1);
+ for (uint32_t i = start; i < end; ++i)
+ set.contains(hashes[i], true);
+ });
+
+ /** Wait for all threads to finish
+ */
+ for (std::thread& t : threads)
+ t.join();
+ /** Grab lock to make sure we observe erases */
+ boost::unique_lock<boost::shared_mutex> l(mtx);
+ /** Insert the second half */
+ for (uint32_t i = (n_insert / 2); i < n_insert; ++i)
+ set.insert(hashes_insert_copy[i]);
+
+ /** elements that we marked erased but that are still there */
+ size_t count_erased_but_contained = 0;
+ /** elements that we did not erase but are older */
+ size_t count_stale = 0;
+ /** elements that were most recently inserted */
+ size_t count_fresh = 0;
+
+ for (uint32_t i = 0; i < (n_insert / 4); ++i)
+ count_erased_but_contained += set.contains(hashes[i], false);
+ for (uint32_t i = (n_insert / 4); i < (n_insert / 2); ++i)
+ count_stale += set.contains(hashes[i], false);
+ for (uint32_t i = (n_insert / 2); i < n_insert; ++i)
+ count_fresh += set.contains(hashes[i], false);
+
+ double hit_rate_erased_but_contained = double(count_erased_but_contained) / (double(n_insert) / 4.0);
+ double hit_rate_stale = double(count_stale) / (double(n_insert) / 4.0);
+ double hit_rate_fresh = double(count_fresh) / (double(n_insert) / 2.0);
+
+ // Check that our hit_rate_fresh is perfect
+ BOOST_CHECK_EQUAL(hit_rate_fresh, 1.0);
+ // Check that we have a more than 2x better hit rate on stale elements than
+ // erased elements.
+ BOOST_CHECK(hit_rate_stale > 2 * hit_rate_erased_but_contained);
+}
+BOOST_AUTO_TEST_CASE(cuckoocache_erase_parallel_ok)
+{
+ size_t megabytes = 32;
+ test_cache_erase_parallel<CuckooCache::cache<uint256, uint256Hasher>>(megabytes);
+}
+
+
+template <typename Cache>
+void test_cache_generations()
+{
+ // This test checks that for a simulation of network activity, the fresh hit
+ // rate is never below 99%, and the number of times that it is worse than
+ // 99.9% are less than 1% of the time.
+ double min_hit_rate = 0.99;
+ double tight_hit_rate = 0.999;
+ double max_rate_less_than_tight_hit_rate = 0.01;
+ // A cache that meets this specification is therefore shown to have a hit
+ // rate of at least tight_hit_rate * (1 - max_rate_less_than_tight_hit_rate) +
+ // min_hit_rate*max_rate_less_than_tight_hit_rate = 0.999*99%+0.99*1% == 99.89%
+ // hit rate with low variance.
+
+ // We use deterministic values, but this test has also passed on many
+ // iterations with non-deterministic values, so it isn't "overfit" to the
+ // specific entropy in FastRandomContext(true) and implementation of the
+ // cache.
+ insecure_rand = FastRandomContext(true);
+
+ // block_activity models a chunk of network activity. n_insert elements are
+ // adde to the cache. The first and last n/4 are stored for removal later
+ // and the middle n/2 are not stored. This models a network which uses half
+ // the signatures of recently (since the last block) added transactions
+ // immediately and never uses the other half.
+ struct block_activity {
+ std::vector<uint256> reads;
+ block_activity(uint32_t n_insert, Cache& c) : reads()
+ {
+ std::vector<uint256> inserts;
+ inserts.resize(n_insert);
+ reads.reserve(n_insert / 2);
+ for (uint32_t i = 0; i < n_insert; ++i) {
+ uint32_t* ptr = (uint32_t*)inserts[i].begin();
+ for (uint8_t j = 0; j < 8; ++j)
+ *(ptr++) = insecure_rand.rand32();
+ }
+ for (uint32_t i = 0; i < n_insert / 4; ++i)
+ reads.push_back(inserts[i]);
+ for (uint32_t i = n_insert - (n_insert / 4); i < n_insert; ++i)
+ reads.push_back(inserts[i]);
+ for (auto h : inserts)
+ c.insert(h);
+ }
+ };
+
+ const uint32_t BLOCK_SIZE = 10000;
+ // We expect window size 60 to perform reasonably given that each epoch
+ // stores 45% of the cache size (~472k).
+ const uint32_t WINDOW_SIZE = 60;
+ const uint32_t POP_AMOUNT = (BLOCK_SIZE / WINDOW_SIZE) / 2;
+ const double load = 10;
+ const size_t megabytes = 32;
+ const size_t bytes = megabytes * (1 << 20);
+ const uint32_t n_insert = static_cast<uint32_t>(load * (bytes / sizeof(uint256)));
+
+ std::vector<block_activity> hashes;
+ Cache set{};
+ set.setup_bytes(bytes);
+ hashes.reserve(n_insert / BLOCK_SIZE);
+ std::deque<block_activity> last_few;
+ uint32_t out_of_tight_tolerance = 0;
+ uint32_t total = n_insert / BLOCK_SIZE;
+ // we use the deque last_few to model a sliding window of blocks. at each
+ // step, each of the last WINDOW_SIZE block_activities checks the cache for
+ // POP_AMOUNT of the hashes that they inserted, and marks these erased.
+ for (uint32_t i = 0; i < total; ++i) {
+ if (last_few.size() == WINDOW_SIZE)
+ last_few.pop_front();
+ last_few.emplace_back(BLOCK_SIZE, set);
+ uint32_t count = 0;
+ for (auto& act : last_few)
+ for (uint32_t k = 0; k < POP_AMOUNT; ++k) {
+ count += set.contains(act.reads.back(), true);
+ act.reads.pop_back();
+ }
+ // We use last_few.size() rather than WINDOW_SIZE for the correct
+ // behavior on the first WINDOW_SIZE iterations where the deque is not
+ // full yet.
+ double hit = (double(count)) / (last_few.size() * POP_AMOUNT);
+ // Loose Check that hit rate is above min_hit_rate
+ BOOST_CHECK(hit > min_hit_rate);
+ // Tighter check, count number of times we are less than tight_hit_rate
+ // (and implicityly, greater than min_hit_rate)
+ out_of_tight_tolerance += hit < tight_hit_rate;
+ }
+ // Check that being out of tolerance happens less than
+ // max_rate_less_than_tight_hit_rate of the time
+ BOOST_CHECK(double(out_of_tight_tolerance) / double(total) < max_rate_less_than_tight_hit_rate);
+}
+BOOST_AUTO_TEST_CASE(cuckoocache_generations)
+{
+ test_cache_generations<CuckooCache::cache<uint256, uint256Hasher>>();
+}
+
+BOOST_AUTO_TEST_SUITE_END();
diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json
index 27acb2f16a..a3f47fcee2 100644
--- a/src/test/data/tx_valid.json
+++ b/src/test/data/tx_valid.json
@@ -478,7 +478,7 @@
["1b2a9a426ba603ba357ce7773cb5805cb9c7c2b386d100d1fc9263513188e680", 0, "0x00 0x20 0xd9bbfbe56af7c4b7f960a70d7ea107156913d9e5a26b0a71429df5e097ca6537", 16777215]],
"01000000000102e9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff80e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffff0280969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac80969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac02483045022100f6a10b8604e6dc910194b79ccfc93e1bc0ec7c03453caaa8987f7d6c3413566002206216229ede9b4d6ec2d325be245c5b508ff0339bf1794078e20bfe0babc7ffe683270063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac024730440220032521802a76ad7bf74d0e2c218b72cf0cbc867066e2e53db905ba37f130397e02207709e2188ed7f08f4c952d9d13986da504502b8c3be59617e043552f506c46ff83275163ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac00000000", "P2SH,WITNESS"],
-["BIP143 example: Same as the previous example with input-output paris swapped"],
+["BIP143 example: Same as the previous example with input-output pairs swapped"],
[[["1b2a9a426ba603ba357ce7773cb5805cb9c7c2b386d100d1fc9263513188e680", 0, "0x00 0x20 0xd9bbfbe56af7c4b7f960a70d7ea107156913d9e5a26b0a71429df5e097ca6537", 16777215],
["01c0cf7fba650638e55eb91261b183251fbb466f90dff17f10086817c542b5e9", 0, "0x00 0x20 0xba468eea561b26301e4cf69fa34bde4ad60c81e70f059f045ca9a79931004a4d", 16777215]],
"0100000000010280e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffffe9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff0280969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac80969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac024730440220032521802a76ad7bf74d0e2c218b72cf0cbc867066e2e53db905ba37f130397e02207709e2188ed7f08f4c952d9d13986da504502b8c3be59617e043552f506c46ff83275163ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac02483045022100f6a10b8604e6dc910194b79ccfc93e1bc0ec7c03453caaa8987f7d6c3413566002206216229ede9b4d6ec2d325be245c5b508ff0339bf1794078e20bfe0babc7ffe683270063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac00000000", "P2SH,WITNESS"],
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
index d4c6b0f2be..84871600b2 100644
--- a/src/test/mempool_tests.cpp
+++ b/src/test/mempool_tests.cpp
@@ -55,17 +55,17 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
CTxMemPool testPool(CFeeRate(0));
- std::vector<CTransactionRef> removed;
// Nothing in pool, remove should do nothing:
- testPool.removeRecursive(txParent, &removed);
- BOOST_CHECK_EQUAL(removed.size(), 0);
+ unsigned int poolSize = testPool.size();
+ testPool.removeRecursive(txParent);
+ BOOST_CHECK_EQUAL(testPool.size(), poolSize);
// Just the parent:
testPool.addUnchecked(txParent.GetHash(), entry.FromTx(txParent));
- testPool.removeRecursive(txParent, &removed);
- BOOST_CHECK_EQUAL(removed.size(), 1);
- removed.clear();
+ poolSize = testPool.size();
+ testPool.removeRecursive(txParent);
+ BOOST_CHECK_EQUAL(testPool.size(), poolSize - 1);
// Parent, children, grandchildren:
testPool.addUnchecked(txParent.GetHash(), entry.FromTx(txParent));
@@ -75,19 +75,21 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
testPool.addUnchecked(txGrandChild[i].GetHash(), entry.FromTx(txGrandChild[i]));
}
// Remove Child[0], GrandChild[0] should be removed:
- testPool.removeRecursive(txChild[0], &removed);
- BOOST_CHECK_EQUAL(removed.size(), 2);
- removed.clear();
+ poolSize = testPool.size();
+ testPool.removeRecursive(txChild[0]);
+ BOOST_CHECK_EQUAL(testPool.size(), poolSize - 2);
// ... make sure grandchild and child are gone:
- testPool.removeRecursive(txGrandChild[0], &removed);
- BOOST_CHECK_EQUAL(removed.size(), 0);
- testPool.removeRecursive(txChild[0], &removed);
- BOOST_CHECK_EQUAL(removed.size(), 0);
+ poolSize = testPool.size();
+ testPool.removeRecursive(txGrandChild[0]);
+ BOOST_CHECK_EQUAL(testPool.size(), poolSize);
+ poolSize = testPool.size();
+ testPool.removeRecursive(txChild[0]);
+ BOOST_CHECK_EQUAL(testPool.size(), poolSize);
// Remove parent, all children/grandchildren should go:
- testPool.removeRecursive(txParent, &removed);
- BOOST_CHECK_EQUAL(removed.size(), 5);
+ poolSize = testPool.size();
+ testPool.removeRecursive(txParent);
+ BOOST_CHECK_EQUAL(testPool.size(), poolSize - 5);
BOOST_CHECK_EQUAL(testPool.size(), 0);
- removed.clear();
// Add children and grandchildren, but NOT the parent (simulate the parent being in a block)
for (int i = 0; i < 3; i++)
@@ -97,10 +99,10 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
}
// Now remove the parent, as might happen if a block-re-org occurs but the parent cannot be
// put into the mempool (maybe because it is non-standard):
- testPool.removeRecursive(txParent, &removed);
- BOOST_CHECK_EQUAL(removed.size(), 6);
+ poolSize = testPool.size();
+ testPool.removeRecursive(txParent);
+ BOOST_CHECK_EQUAL(testPool.size(), poolSize - 6);
BOOST_CHECK_EQUAL(testPool.size(), 0);
- removed.clear();
}
template<typename name>
@@ -417,7 +419,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
/* after tx6 is mined, tx7 should move up in the sort */
std::vector<CTransactionRef> vtx;
vtx.push_back(MakeTransactionRef(tx6));
- pool.removeForBlock(vtx, 1, NULL, false);
+ pool.removeForBlock(vtx, 1);
sortedOrder.erase(sortedOrder.begin()+1);
// Ties are broken by hash
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index bc1bdd8874..892e731a7a 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -224,7 +224,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
pblock->nNonce = blockinfo[i].nonce;
std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(*pblock);
- BOOST_CHECK(ProcessNewBlock(chainparams, shared_pblock, true, NULL, NULL));
+ BOOST_CHECK(ProcessNewBlock(chainparams, shared_pblock, true, NULL));
pblock->hashPrevBlock = pblock->GetHash();
}
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index eb324d5a6b..d7f3a3a657 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -176,10 +176,10 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScript
int libconsensus_flags = flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_ALL;
if (libconsensus_flags == flags) {
if (flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS) {
- BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(begin_ptr(scriptPubKey), scriptPubKey.size(), txCredit.vout[0].nValue, (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, NULL) == expect, message);
+ BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(scriptPubKey.data(), scriptPubKey.size(), txCredit.vout[0].nValue, (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, NULL) == expect, message);
} else {
- BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(begin_ptr(scriptPubKey), scriptPubKey.size(), 0, (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, NULL) == expect, message);
- BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script(begin_ptr(scriptPubKey), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, NULL) == expect,message);
+ BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(scriptPubKey.data(), scriptPubKey.size(), 0, (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, NULL) == expect, message);
+ BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, NULL) == expect,message);
}
}
#endif
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 139389117a..2a5a78de02 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -20,6 +20,7 @@
#include "ui_interface.h"
#include "rpc/server.h"
#include "rpc/register.h"
+#include "script/sigcache.h"
#include "test/testutil.h"
@@ -40,6 +41,7 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
ECC_Start();
SetupEnvironment();
SetupNetworking();
+ InitSignatureCache();
fPrintToDebugLog = false; // don't want to write to debug.log file
fCheckBlockIndex = true;
SelectParams(chainName);
@@ -128,7 +130,7 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>&
while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(block);
- ProcessNewBlock(chainparams, shared_pblock, true, NULL, NULL);
+ ProcessNewBlock(chainparams, shared_pblock, true, NULL);
CBlock result = block;
return result;
diff --git a/src/test/test_bitcoin_fuzzy.cpp b/src/test/test_bitcoin_fuzzy.cpp
new file mode 100644
index 0000000000..e1abde16f4
--- /dev/null
+++ b/src/test/test_bitcoin_fuzzy.cpp
@@ -0,0 +1,256 @@
+// Copyright (c) 2009-2015 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#if defined(HAVE_CONFIG_H)
+#include "config/bitcoin-config.h"
+#endif
+
+#include "consensus/merkle.h"
+#include "primitives/block.h"
+#include "script/script.h"
+#include "addrman.h"
+#include "chain.h"
+#include "coins.h"
+#include "compressor.h"
+#include "net.h"
+#include "protocol.h"
+#include "streams.h"
+#include "undo.h"
+#include "version.h"
+
+#include <stdint.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <vector>
+
+enum TEST_ID {
+ CBLOCK_DESERIALIZE=0,
+ CTRANSACTION_DESERIALIZE,
+ CBLOCKLOCATOR_DESERIALIZE,
+ CBLOCKMERKLEROOT,
+ CADDRMAN_DESERIALIZE,
+ CBLOCKHEADER_DESERIALIZE,
+ CBANENTRY_DESERIALIZE,
+ CTXUNDO_DESERIALIZE,
+ CBLOCKUNDO_DESERIALIZE,
+ CCOINS_DESERIALIZE,
+ CNETADDR_DESERIALIZE,
+ CSERVICE_DESERIALIZE,
+ CMESSAGEHEADER_DESERIALIZE,
+ CADDRESS_DESERIALIZE,
+ CINV_DESERIALIZE,
+ CBLOOMFILTER_DESERIALIZE,
+ CDISKBLOCKINDEX_DESERIALIZE,
+ CTXOUTCOMPRESSOR_DESERIALIZE,
+ TEST_ID_END
+};
+
+bool read_stdin(std::vector<char> &data) {
+ char buffer[1024];
+ ssize_t length=0;
+ while((length = read(STDIN_FILENO, buffer, 1024)) > 0) {
+ data.insert(data.end(), buffer, buffer+length);
+
+ if (data.size() > (1<<20)) return false;
+ }
+ return length==0;
+}
+
+int main(int argc, char **argv)
+{
+ std::vector<char> buffer;
+ if (!read_stdin(buffer)) return 0;
+
+ if (buffer.size() < sizeof(uint32_t)) return 0;
+
+ uint32_t test_id = 0xffffffff;
+ memcpy(&test_id, &buffer[0], sizeof(uint32_t));
+ buffer.erase(buffer.begin(), buffer.begin() + sizeof(uint32_t));
+
+ if (test_id >= TEST_ID_END) return 0;
+
+ CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
+ try {
+ int nVersion;
+ ds >> nVersion;
+ ds.SetVersion(nVersion);
+ } catch (const std::ios_base::failure& e) {
+ return 0;
+ }
+
+ switch(test_id) {
+ case CBLOCK_DESERIALIZE:
+ {
+ try
+ {
+ CBlock block;
+ ds >> block;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CTRANSACTION_DESERIALIZE:
+ {
+ try
+ {
+ CTransaction tx(deserialize, ds);
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CBLOCKLOCATOR_DESERIALIZE:
+ {
+ try
+ {
+ CBlockLocator bl;
+ ds >> bl;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CBLOCKMERKLEROOT:
+ {
+ try
+ {
+ CBlock block;
+ ds >> block;
+ bool mutated;
+ BlockMerkleRoot(block, &mutated);
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CADDRMAN_DESERIALIZE:
+ {
+ try
+ {
+ CAddrMan am;
+ ds >> am;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CBLOCKHEADER_DESERIALIZE:
+ {
+ try
+ {
+ CBlockHeader bh;
+ ds >> bh;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CBANENTRY_DESERIALIZE:
+ {
+ try
+ {
+ CBanEntry be;
+ ds >> be;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CTXUNDO_DESERIALIZE:
+ {
+ try
+ {
+ CTxUndo tu;
+ ds >> tu;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CBLOCKUNDO_DESERIALIZE:
+ {
+ try
+ {
+ CBlockUndo bu;
+ ds >> bu;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CCOINS_DESERIALIZE:
+ {
+ try
+ {
+ CCoins block;
+ ds >> block;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CNETADDR_DESERIALIZE:
+ {
+ try
+ {
+ CNetAddr na;
+ ds >> na;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CSERVICE_DESERIALIZE:
+ {
+ try
+ {
+ CService s;
+ ds >> s;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CMESSAGEHEADER_DESERIALIZE:
+ {
+ CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00};
+ try
+ {
+ CMessageHeader mh(pchMessageStart);
+ ds >> mh;
+ if (!mh.IsValid(pchMessageStart)) {return 0;}
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CADDRESS_DESERIALIZE:
+ {
+ try
+ {
+ CAddress a;
+ ds >> a;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CINV_DESERIALIZE:
+ {
+ try
+ {
+ CInv i;
+ ds >> i;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CBLOOMFILTER_DESERIALIZE:
+ {
+ try
+ {
+ CBloomFilter bf;
+ ds >> bf;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CDISKBLOCKINDEX_DESERIALIZE:
+ {
+ try
+ {
+ CDiskBlockIndex dbi;
+ ds >> dbi;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CTXOUTCOMPRESSOR_DESERIALIZE:
+ {
+ CTxOut to;
+ try
+ {
+ ds >> to;
+ } catch (const std::ios_base::failure& e) {return 0;}
+
+ CTxOutCompressor toc(to);
+ break;
+ }
+ default:
+ return 0;
+ }
+ return 0;
+}
+