diff options
Diffstat (limited to 'src/test')
41 files changed, 659 insertions, 344 deletions
diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index e6b45a3b5e..4a284517a1 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -18,9 +18,6 @@ #include <stdint.h> -#include <boost/assign/list_of.hpp> // for 'map_list_of()' -#include <boost/date_time/posix_time/posix_time_types.hpp> -#include <boost/foreach.hpp> #include <boost/test/unit_test.hpp> // Tests these internal-to-net_processing.cpp methods: @@ -129,7 +126,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) CTransactionRef RandomOrphan() { std::map<uint256, COrphanTx>::iterator it; - it = mapOrphanTransactions.lower_bound(GetRandHash()); + it = mapOrphanTransactions.lower_bound(InsecureRand256()); if (it == mapOrphanTransactions.end()) it = mapOrphanTransactions.begin(); return it->second.tx; @@ -148,7 +145,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) CMutableTransaction tx; tx.vin.resize(1); tx.vin[0].prevout.n = 0; - tx.vin[0].prevout.hash = GetRandHash(); + tx.vin[0].prevout.hash = InsecureRand256(); tx.vin[0].scriptSig << OP_1; tx.vout.resize(1); tx.vout[0].nValue = 1*CENT; diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index dc5372a070..bc6aef2c11 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -27,7 +27,7 @@ public: insecure_rand = FastRandomContext(true); } - int RandomInt(int nMax) + int RandomInt(int nMax) override { state = (CHashWriter(SER_GETHASH, 0) << state).GetHash().GetCheapHash(); return (unsigned int)(state % nMax); diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp index 3f15a0dec1..4a533b5bf2 100644 --- a/src/test/allocator_tests.cpp +++ b/src/test/allocator_tests.cpp @@ -131,7 +131,7 @@ class TestLockedPageAllocator: public LockedPageAllocator { public: TestLockedPageAllocator(int count_in, int lockedcount_in): count(count_in), lockedcount(lockedcount_in) {} - void* AllocateLocked(size_t len, bool *lockingSuccess) + void* AllocateLocked(size_t len, bool *lockingSuccess) override { *lockingSuccess = false; if (count > 0) { @@ -146,10 +146,10 @@ public: } return 0; } - void FreeLocked(void* addr, size_t len) + void FreeLocked(void* addr, size_t len) override { } - size_t GetLimit() + size_t GetLimit() override { return std::numeric_limits<size_t>::max(); } diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp index 45ae7d4636..2c98fbcfd6 100644 --- a/src/test/arith_uint256_tests.cpp +++ b/src/test/arith_uint256_tests.cpp @@ -219,7 +219,7 @@ BOOST_AUTO_TEST_CASE( unaryOperators ) // ! ~ - // Check if doing _A_ _OP_ _B_ results in the same as applying _OP_ onto each -// element of Aarray and Barray, and then converting the result into a arith_uint256. +// element of Aarray and Barray, and then converting the result into an arith_uint256. #define CHECKBITWISEOPERATOR(_A_,_B_,_OP_) \ for (unsigned int i = 0; i < 32; ++i) { TmpArray[i] = _A_##Array[i] _OP_ _B_##Array[i]; } \ BOOST_CHECK(arith_uint256V(std::vector<unsigned char>(TmpArray,TmpArray+32)) == (_A_##L _OP_ _B_##L)); diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index 6cd998990b..b33cdb9fe6 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -15,7 +15,6 @@ #include "utilstrencodings.h" #include "test/test_bitcoin.h" -#include <boost/foreach.hpp> #include <boost/test/unit_test.hpp> #include <univalue.h> diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp index c148ad6d82..6bcd550d7b 100644 --- a/src/test/bip32_tests.cpp +++ b/src/test/bip32_tests.cpp @@ -93,7 +93,7 @@ void RunTest(const TestVector &test) { CExtPubKey pubkey; key.SetMaster(&seed[0], seed.size()); pubkey = key.Neuter(); - BOOST_FOREACH(const TestDerivation &derive, test.vDerive) { + for (const TestDerivation &derive : test.vDerive) { unsigned char data[74]; key.Encode(data); pubkey.Encode(data); diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp index 9e4a56919d..10a40fea3c 100644 --- a/src/test/blockencodings_tests.cpp +++ b/src/test/blockencodings_tests.cpp @@ -30,16 +30,16 @@ static CBlock BuildBlockTestCase() { block.vtx.resize(3); block.vtx[0] = MakeTransactionRef(tx); block.nVersion = 42; - block.hashPrevBlock = GetRandHash(); + block.hashPrevBlock = InsecureRand256(); block.nBits = 0x207fffff; - tx.vin[0].prevout.hash = GetRandHash(); + tx.vin[0].prevout.hash = InsecureRand256(); tx.vin[0].prevout.n = 0; block.vtx[1] = MakeTransactionRef(tx); tx.vin.resize(10); for (size_t i = 0; i < tx.vin.size(); i++) { - tx.vin[i].prevout.hash = GetRandHash(); + tx.vin[i].prevout.hash = InsecureRand256(); tx.vin[i].prevout.n = 0; } block.vtx[2] = MakeTransactionRef(tx); @@ -283,7 +283,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest) block.vtx.resize(1); block.vtx[0] = MakeTransactionRef(std::move(coinbase)); block.nVersion = 42; - block.hashPrevBlock = GetRandHash(); + block.hashPrevBlock = InsecureRand256(); block.nBits = 0x207fffff; bool mutated; @@ -316,7 +316,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest) BOOST_AUTO_TEST_CASE(TransactionsRequestSerializationTest) { BlockTransactionsRequest req1; - req1.blockhash = GetRandHash(); + req1.blockhash = InsecureRand256(); req1.indexes.resize(4); req1.indexes[0] = 0; req1.indexes[1] = 1; diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index 27bc92d670..2085b5cb2b 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -19,7 +19,6 @@ #include <vector> #include <boost/test/unit_test.hpp> -#include <boost/tuple/tuple.hpp> BOOST_FIXTURE_TEST_SUITE(bloom_tests, BasicTestingSetup) @@ -463,7 +462,7 @@ BOOST_AUTO_TEST_CASE(merkle_block_4_test_update_none) static std::vector<unsigned char> RandomData() { - uint256 r = GetRandHash(); + uint256 r = InsecureRand256(); return std::vector<unsigned char>(r.begin(), r.end()); } diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp index 287395c6c6..6ae0bcadd0 100644 --- a/src/test/checkqueue_tests.cpp +++ b/src/test/checkqueue_tests.cpp @@ -160,7 +160,7 @@ void Correct_Queue_range(std::vector<size_t> range) FakeCheckCheckCompletion::n_calls = 0; CCheckQueueControl<FakeCheckCheckCompletion> control(small_queue.get()); while (total) { - vChecks.resize(std::min(total, (size_t) GetRand(10))); + vChecks.resize(std::min(total, (size_t) InsecureRandRange(10))); total -= vChecks.size(); control.Add(vChecks); } @@ -204,7 +204,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Random) { std::vector<size_t> range; range.reserve(100000/1000); - for (size_t i = 2; i < 100000; i += std::max((size_t)1, (size_t)GetRand(std::min((size_t)1000, ((size_t)100000) - i)))) + for (size_t i = 2; i < 100000; i += std::max((size_t)1, (size_t)InsecureRandRange(std::min((size_t)1000, ((size_t)100000) - i)))) range.push_back(i); Correct_Queue_range(range); } @@ -224,7 +224,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Catches_Failure) CCheckQueueControl<FailingCheck> control(fail_queue.get()); size_t remaining = i; while (remaining) { - size_t r = GetRand(10); + size_t r = InsecureRandRange(10); std::vector<FailingCheck> vChecks; vChecks.reserve(r); @@ -286,7 +286,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_UniqueCheck) { CCheckQueueControl<UniqueCheck> control(queue.get()); while (total) { - size_t r = GetRand(10); + size_t r = InsecureRandRange(10); std::vector<UniqueCheck> vChecks; for (size_t k = 0; k < r && total; k++) vChecks.emplace_back(--total); @@ -320,7 +320,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Memory) { CCheckQueueControl<MemoryCheck> control(queue.get()); while (total) { - size_t r = GetRand(10); + size_t r = InsecureRandRange(10); std::vector<MemoryCheck> vChecks; for (size_t k = 0; k < r && total; k++) { total--; @@ -402,12 +402,12 @@ BOOST_AUTO_TEST_CASE(test_CheckQueueControl_Locks) { boost::thread_group tg; std::mutex m; - bool has_lock {false}; - bool has_tried {false}; - bool done {false}; - bool done_ack {false}; std::condition_variable cv; { + bool has_lock {false}; + bool has_tried {false}; + bool done {false}; + bool done_ack {false}; std::unique_lock<std::mutex> l(m); tg.create_thread([&]{ CCheckQueueControl<FakeCheck> control(queue.get()); diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 0ed71b96fc..e24431528a 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -8,7 +8,6 @@ #include "undo.h" #include "utilstrencodings.h" #include "test/test_bitcoin.h" -#include "test/test_random.h" #include "validation.h" #include "consensus/validation.h" @@ -37,35 +36,29 @@ class CCoinsViewTest : public CCoinsView std::map<COutPoint, Coin> map_; public: - bool GetCoin(const COutPoint& outpoint, Coin& coin) const + bool GetCoin(const COutPoint& outpoint, Coin& coin) const override { std::map<COutPoint, Coin>::const_iterator it = map_.find(outpoint); if (it == map_.end()) { return false; } coin = it->second; - if (coin.IsSpent() && insecure_rand() % 2 == 0) { + if (coin.IsSpent() && InsecureRandBool() == 0) { // Randomly return false in case of an empty entry. return false; } return true; } - bool HaveCoin(const COutPoint& outpoint) const - { - Coin coin; - return GetCoin(outpoint, coin); - } + uint256 GetBestBlock() const override { return hashBestBlock_; } - uint256 GetBestBlock() const { return hashBestBlock_; } - - bool BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlock) + bool BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlock) override { for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); ) { if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Same optimization used in CCoinsViewDB is to only write dirty entries. map_[it->first] = it->second.coin; - if (it->second.coin.IsSpent() && insecure_rand() % 3 == 0) { + if (it->second.coin.IsSpent() && InsecureRandRange(3) == 0) { // Randomly delete empty entries on write. map_.erase(it->first); } @@ -100,7 +93,7 @@ public: size_t& usage() { return cachedCoinsUsage; } }; -} +} // namespace BOOST_FIXTURE_TEST_SUITE(coins_tests, BasicTestingSetup) @@ -140,31 +133,45 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) std::vector<uint256> txids; txids.resize(NUM_SIMULATION_ITERATIONS / 8); for (unsigned int i = 0; i < txids.size(); i++) { - txids[i] = GetRandHash(); + txids[i] = InsecureRand256(); } for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) { // Do a random modification. { - uint256 txid = txids[insecure_rand() % txids.size()]; // txid we're going to modify in this iteration. + uint256 txid = txids[InsecureRandRange(txids.size())]; // txid we're going to modify in this iteration. Coin& coin = result[COutPoint(txid, 0)]; - const Coin& entry = (insecure_rand() % 500 == 0) ? AccessByTxid(*stack.back(), txid) : stack.back()->AccessCoin(COutPoint(txid, 0)); + + // Determine whether to test HaveCoin before or after Access* (or both). As these functions + // can influence each other's behaviour by pulling things into the cache, all combinations + // are tested. + bool test_havecoin_before = InsecureRandBits(2) == 0; + bool test_havecoin_after = InsecureRandBits(2) == 0; + + bool result_havecoin = test_havecoin_before ? stack.back()->HaveCoin(COutPoint(txid, 0)) : false; + const Coin& entry = (InsecureRandRange(500) == 0) ? AccessByTxid(*stack.back(), txid) : stack.back()->AccessCoin(COutPoint(txid, 0)); BOOST_CHECK(coin == entry); + BOOST_CHECK(!test_havecoin_before || result_havecoin == !entry.IsSpent()); + + if (test_havecoin_after) { + bool ret = stack.back()->HaveCoin(COutPoint(txid, 0)); + BOOST_CHECK(ret == !entry.IsSpent()); + } - if (insecure_rand() % 5 == 0 || coin.IsSpent()) { + if (InsecureRandRange(5) == 0 || coin.IsSpent()) { Coin newcoin; - newcoin.out.nValue = insecure_rand(); + newcoin.out.nValue = InsecureRand32(); newcoin.nHeight = 1; - if (insecure_rand() % 16 == 0 && coin.IsSpent()) { - newcoin.out.scriptPubKey.assign(1 + (insecure_rand() & 0x3F), OP_RETURN); + if (InsecureRandRange(16) == 0 && coin.IsSpent()) { + newcoin.out.scriptPubKey.assign(1 + InsecureRandBits(6), OP_RETURN); BOOST_CHECK(newcoin.out.scriptPubKey.IsUnspendable()); added_an_unspendable_entry = true; } else { - newcoin.out.scriptPubKey.assign(insecure_rand() & 0x3F, 0); // Random sizes so we can test memory usage accounting + newcoin.out.scriptPubKey.assign(InsecureRandBits(6), 0); // Random sizes so we can test memory usage accounting (coin.IsSpent() ? added_an_entry : updated_an_entry) = true; coin = newcoin; } - stack.back()->AddCoin(COutPoint(txid, 0), std::move(newcoin), !coin.IsSpent() || insecure_rand() & 1); + stack.back()->AddCoin(COutPoint(txid, 0), std::move(newcoin), !coin.IsSpent() || InsecureRand32() & 1); } else { removed_an_entry = true; coin.Clear(); @@ -173,15 +180,15 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) } // One every 10 iterations, remove a random entry from the cache - if (insecure_rand() % 10 == 0) { - COutPoint out(txids[insecure_rand() % txids.size()], 0); - int cacheid = insecure_rand() % stack.size(); + if (InsecureRandRange(10) == 0) { + COutPoint out(txids[InsecureRand32() % txids.size()], 0); + int cacheid = InsecureRand32() % stack.size(); stack[cacheid]->Uncache(out); uncached_an_entry |= !stack[cacheid]->HaveCoinInCache(out); } // Once every 1000 iterations and at the end, verify the full cache. - if (insecure_rand() % 1000 == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { + if (InsecureRandRange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { for (auto it = result.begin(); it != result.end(); it++) { bool have = stack.back()->HaveCoin(it->first); const Coin& coin = stack.back()->AccessCoin(it->first); @@ -194,27 +201,27 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) found_an_entry = true; } } - BOOST_FOREACH(const CCoinsViewCacheTest *test, stack) { + for (const CCoinsViewCacheTest *test : stack) { test->SelfTest(); } } - if (insecure_rand() % 100 == 0) { + if (InsecureRandRange(100) == 0) { // Every 100 iterations, flush an intermediate cache - if (stack.size() > 1 && insecure_rand() % 2 == 0) { - unsigned int flushIndex = insecure_rand() % (stack.size() - 1); + if (stack.size() > 1 && InsecureRandBool() == 0) { + unsigned int flushIndex = InsecureRandRange(stack.size() - 1); stack[flushIndex]->Flush(); } } - if (insecure_rand() % 100 == 0) { + if (InsecureRandRange(100) == 0) { // Every 100 iterations, change the cache stack. - if (stack.size() > 0 && insecure_rand() % 2 == 0) { + if (stack.size() > 0 && InsecureRandBool() == 0) { //Remove the top cache stack.back()->Flush(); delete stack.back(); stack.pop_back(); } - if (stack.size() == 0 || (stack.size() < 4 && insecure_rand() % 2)) { + if (stack.size() == 0 || (stack.size() < 4 && InsecureRandBool())) { //Add a new cache CCoinsView* tip = &base; if (stack.size() > 0) { @@ -254,7 +261,7 @@ UtxoData utxoData; UtxoData::iterator FindRandomFrom(const std::set<COutPoint> &utxoSet) { assert(utxoSet.size()); - auto utxoSetIt = utxoSet.lower_bound(COutPoint(GetRandHash(), 0)); + auto utxoSetIt = utxoSet.lower_bound(COutPoint(InsecureRand256(), 0)); if (utxoSetIt == utxoSet.end()) { utxoSetIt = utxoSet.begin(); } @@ -287,7 +294,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) std::set<COutPoint> utxoset; for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) { - uint32_t randiter = insecure_rand(); + uint32_t randiter = InsecureRand32(); // 19/20 txs add a new transaction if (randiter % 20 < 19) { @@ -295,14 +302,14 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) tx.vin.resize(1); tx.vout.resize(1); tx.vout[0].nValue = i; //Keep txs unique unless intended to duplicate - tx.vout[0].scriptPubKey.assign(insecure_rand() & 0x3F, 0); // Random sizes so we can test memory usage accounting - unsigned int height = insecure_rand(); + tx.vout[0].scriptPubKey.assign(InsecureRand32() & 0x3F, 0); // Random sizes so we can test memory usage accounting + unsigned int height = InsecureRand32(); Coin old_coin; // 2/20 times create a new coinbase if (randiter % 20 < 2 || coinbase_coins.size() < 10) { // 1/10 of those times create a duplicate coinbase - if (insecure_rand() % 10 == 0 && coinbase_coins.size()) { + if (InsecureRandRange(10) == 0 && coinbase_coins.size()) { auto utxod = FindRandomFrom(coinbase_coins); // Reuse the exact same coinbase tx = std::get<0>(utxod->second); @@ -412,7 +419,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) } // Once every 1000 iterations and at the end, verify the full cache. - if (insecure_rand() % 1000 == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { + if (InsecureRandRange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { for (auto it = result.begin(); it != result.end(); it++) { bool have = stack.back()->HaveCoin(it->first); const Coin& coin = stack.back()->AccessCoin(it->first); @@ -422,31 +429,31 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) } // One every 10 iterations, remove a random entry from the cache - if (utxoset.size() > 1 && insecure_rand() % 30 == 0) { - stack[insecure_rand() % stack.size()]->Uncache(FindRandomFrom(utxoset)->first); + if (utxoset.size() > 1 && InsecureRandRange(30) == 0) { + stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(utxoset)->first); } - if (disconnected_coins.size() > 1 && insecure_rand() % 30 == 0) { - stack[insecure_rand() % stack.size()]->Uncache(FindRandomFrom(disconnected_coins)->first); + if (disconnected_coins.size() > 1 && InsecureRandRange(30) == 0) { + stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(disconnected_coins)->first); } - if (duplicate_coins.size() > 1 && insecure_rand() % 30 == 0) { - stack[insecure_rand() % stack.size()]->Uncache(FindRandomFrom(duplicate_coins)->first); + if (duplicate_coins.size() > 1 && InsecureRandRange(30) == 0) { + stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(duplicate_coins)->first); } - if (insecure_rand() % 100 == 0) { + if (InsecureRandRange(100) == 0) { // Every 100 iterations, flush an intermediate cache - if (stack.size() > 1 && insecure_rand() % 2 == 0) { - unsigned int flushIndex = insecure_rand() % (stack.size() - 1); + if (stack.size() > 1 && InsecureRandBool() == 0) { + unsigned int flushIndex = InsecureRandRange(stack.size() - 1); stack[flushIndex]->Flush(); } } - if (insecure_rand() % 100 == 0) { + if (InsecureRandRange(100) == 0) { // Every 100 iterations, change the cache stack. - if (stack.size() > 0 && insecure_rand() % 2 == 0) { + if (stack.size() > 0 && InsecureRandBool() == 0) { stack.back()->Flush(); delete stack.back(); stack.pop_back(); } - if (stack.size() == 0 || (stack.size() < 4 && insecure_rand() % 2)) { + if (stack.size() == 0 || (stack.size() < 4 && InsecureRandBool())) { CCoinsView* tip = &base; if (stack.size() > 0) { tip = stack.back(); @@ -629,7 +636,7 @@ BOOST_AUTO_TEST_CASE(ccoins_access) CheckAccessCoin(ABSENT, VALUE2, VALUE2, FRESH , FRESH ); CheckAccessCoin(ABSENT, VALUE2, VALUE2, DIRTY , DIRTY ); CheckAccessCoin(ABSENT, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH); - CheckAccessCoin(PRUNED, ABSENT, PRUNED, NO_ENTRY , FRESH ); + CheckAccessCoin(PRUNED, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY ); CheckAccessCoin(PRUNED, PRUNED, PRUNED, 0 , 0 ); CheckAccessCoin(PRUNED, PRUNED, PRUNED, FRESH , FRESH ); CheckAccessCoin(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY ); diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 72e562808a..391ad14ffa 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -13,11 +13,9 @@ #include "random.h" #include "utilstrencodings.h" #include "test/test_bitcoin.h" -#include "test/test_random.h" #include <vector> -#include <boost/assign/list_of.hpp> #include <boost/test/unit_test.hpp> #include <openssl/aes.h> #include <openssl/evp.h> @@ -39,7 +37,7 @@ void TestVector(const Hasher &h, const In &in, const Out &out) { Hasher hasher(h); size_t pos = 0; while (pos < in.size()) { - size_t len = insecure_rand() % ((in.size() - pos + 1) / 2 + 1); + size_t len = InsecureRandRange((in.size() - pos + 1) / 2 + 1); hasher.Write((unsigned char*)&in[pos], len); pos += len; if (pos > 0 && pos + 2 * out.size() > in.size() && pos < in.size()) { diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp index 8cae4e66e8..1004482224 100644 --- a/src/test/cuckoocache_tests.cpp +++ b/src/test/cuckoocache_tests.cpp @@ -7,8 +7,6 @@ #include "test/test_bitcoin.h" #include "random.h" #include <thread> -#include <boost/thread.hpp> - /** Test Suite for CuckooCache * @@ -23,18 +21,18 @@ * using BOOST_CHECK_CLOSE to fail. * */ -FastRandomContext insecure_rand(true); +FastRandomContext local_rand_ctx(true); BOOST_AUTO_TEST_SUITE(cuckoocache_tests); -/** insecure_GetRandHash fills in a uint256 from insecure_rand +/** insecure_GetRandHash fills in a uint256 from local_rand_ctx */ void insecure_GetRandHash(uint256& t) { uint32_t* ptr = (uint32_t*)t.begin(); for (uint8_t j = 0; j < 8; ++j) - *(ptr++) = insecure_rand.rand32(); + *(ptr++) = local_rand_ctx.rand32(); } @@ -45,7 +43,7 @@ void insecure_GetRandHash(uint256& t) */ BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes) { - insecure_rand = FastRandomContext(true); + local_rand_ctx = FastRandomContext(true); CuckooCache::cache<uint256, SignatureCacheHasher> cc{}; size_t megabytes = 4; cc.setup_bytes(megabytes << 20); @@ -66,7 +64,7 @@ BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes) template <typename Cache> double test_cache(size_t megabytes, double load) { - insecure_rand = FastRandomContext(true); + local_rand_ctx = FastRandomContext(true); std::vector<uint256> hashes; Cache set{}; size_t bytes = megabytes * (1 << 20); @@ -76,7 +74,7 @@ double test_cache(size_t megabytes, double load) 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(); + *(ptr++) = local_rand_ctx.rand32(); } /** We make a copy of the hashes because future optimizations of the * cuckoocache may overwrite the inserted element, so the test is @@ -137,7 +135,7 @@ template <typename Cache> void test_cache_erase(size_t megabytes) { double load = 1; - insecure_rand = FastRandomContext(true); + local_rand_ctx = FastRandomContext(true); std::vector<uint256> hashes; Cache set{}; size_t bytes = megabytes * (1 << 20); @@ -147,7 +145,7 @@ void test_cache_erase(size_t megabytes) 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(); + *(ptr++) = local_rand_ctx.rand32(); } /** We make a copy of the hashes because future optimizations of the * cuckoocache may overwrite the inserted element, so the test is @@ -200,7 +198,7 @@ template <typename Cache> void test_cache_erase_parallel(size_t megabytes) { double load = 1; - insecure_rand = FastRandomContext(true); + local_rand_ctx = FastRandomContext(true); std::vector<uint256> hashes; Cache set{}; size_t bytes = megabytes * (1 << 20); @@ -210,7 +208,7 @@ void test_cache_erase_parallel(size_t megabytes) 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(); + *(ptr++) = local_rand_ctx.rand32(); } /** We make a copy of the hashes because future optimizations of the * cuckoocache may overwrite the inserted element, so the test is @@ -302,7 +300,7 @@ void test_cache_generations() // 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); + local_rand_ctx = 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 @@ -319,7 +317,7 @@ void test_cache_generations() 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(); + *(ptr++) = local_rand_ctx.rand32(); } for (uint32_t i = 0; i < n_insert / 4; ++i) reads.push_back(inserts[i]); diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index e35a7ce569..698e898231 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -240,7 +240,7 @@ ["0", "IF NOP10 ENDIF 1", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "OK", "Discouraged NOPs are allowed if not executed"], -["0", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "opcodes above NOP10 invalid if executed"], +["0", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "opcodes above MAX_OPCODE invalid if executed"], ["0", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], @@ -878,7 +878,7 @@ "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in redeemScript"], ["0x50","1", "P2SH,STRICTENC", "BAD_OPCODE", "opcode 0x50 is reserved"], -["1", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "opcodes above NOP10 invalid if executed"], +["1", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "opcodes above MAX_OPCODE invalid if executed"], ["1", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], @@ -1001,7 +1001,7 @@ ["1","RESERVED", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED is reserved"], ["1","RESERVED1", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED1 is reserved"], ["1","RESERVED2", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED2 is reserved"], -["1","0xba", "P2SH,STRICTENC", "BAD_OPCODE", "0xba == OP_NOP10 + 1"], +["1","0xba", "P2SH,STRICTENC", "BAD_OPCODE", "0xba == MAX_OPCODE + 1"], ["2147483648", "1ADD 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], ["2147483648", "NEGATE 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], @@ -2506,7 +2506,7 @@ ], ["CHECKSEQUENCEVERIFY tests"], -["", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on a empty stack"], +["", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on an empty stack"], ["-1", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "NEGATIVE_LOCKTIME", "CSV automatically fails if stack top is negative"], ["0x0100", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY,MINIMALDATA", "UNKNOWN_ERROR", "CSV fails if stack top is not minimally encoded"], ["0", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is set and the tx version < 2"], diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json index d70fa54333..e6b382af13 100644 --- a/src/test/data/tx_valid.json +++ b/src/test/data/tx_valid.json @@ -174,7 +174,7 @@ [[["5a6b0021a6042a686b6b94abc36b387bef9109847774e8b1e51eb8cc55c53921", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], "01000000012139c555ccb81ee5b1e87477840991ef7b386bc3ab946b6b682a04a621006b5a01000000fdb40148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f2204148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390175ac4830450220646b72c35beeec51f4d5bc1cbae01863825750d7f490864af354e6ea4f625e9c022100f04b98432df3a9641719dbced53393022e7249fb59db993af1118539830aab870148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a580039017521038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"], -["Finally CHECKMULTISIG removes all signatures prior to hashing the script containing those signatures. In conjunction with the SIGHASH_SINGLE bug this lets us test whether or not FindAndDelete() is actually present in scriptPubKey/redeemScript evaluation by including a signature of the digest 0x01 We can compute in advance for our pubkey, embed it it in the scriptPubKey, and then also using a normal SIGHASH_ALL signature. If FindAndDelete() wasn't run, the 'bugged' signature would still be in the hashed script, and the normal signature would fail."], +["Finally CHECKMULTISIG removes all signatures prior to hashing the script containing those signatures. In conjunction with the SIGHASH_SINGLE bug this lets us test whether or not FindAndDelete() is actually present in scriptPubKey/redeemScript evaluation by including a signature of the digest 0x01 We can compute in advance for our pubkey, embed it in the scriptPubKey, and then also using a normal SIGHASH_ALL signature. If FindAndDelete() wasn't run, the 'bugged' signature would still be in the hashed script, and the normal signature would fail."], ["Here's an example on mainnet within a P2SH redeemScript. Remarkably it's a standard transaction in <0.9"], [[["b5b598de91787439afd5938116654e0b16b7a0d0f82742ba37564219c5afcbf9", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"], diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index c9d9849ada..6ed6e7744e 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -7,8 +7,6 @@ #include "random.h" #include "test/test_bitcoin.h" -#include <boost/assign/std/vector.hpp> // for 'operator+=()' -#include <boost/assert.hpp> #include <boost/test/unit_test.hpp> // Test if a string consists entirely of null characters @@ -26,12 +24,11 @@ BOOST_FIXTURE_TEST_SUITE(dbwrapper_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(dbwrapper) { // Perform tests both obfuscated and non-obfuscated. - for (int i = 0; i < 2; i++) { - bool obfuscate = (bool)i; + for (bool obfuscate : {false, true}) { fs::path ph = fs::temp_directory_path() / fs::unique_path(); CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); char key = 'k'; - uint256 in = GetRandHash(); + uint256 in = InsecureRand256(); uint256 res; // Ensure that we're doing real obfuscation when obfuscate=true @@ -47,17 +44,16 @@ BOOST_AUTO_TEST_CASE(dbwrapper) BOOST_AUTO_TEST_CASE(dbwrapper_batch) { // Perform tests both obfuscated and non-obfuscated. - for (int i = 0; i < 2; i++) { - bool obfuscate = (bool)i; + for (bool obfuscate : {false, true}) { fs::path ph = fs::temp_directory_path() / fs::unique_path(); CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); char key = 'i'; - uint256 in = GetRandHash(); + uint256 in = InsecureRand256(); char key2 = 'j'; - uint256 in2 = GetRandHash(); + uint256 in2 = InsecureRand256(); char key3 = 'k'; - uint256 in3 = GetRandHash(); + uint256 in3 = InsecureRand256(); uint256 res; CDBBatch batch(dbw); @@ -84,20 +80,19 @@ BOOST_AUTO_TEST_CASE(dbwrapper_batch) BOOST_AUTO_TEST_CASE(dbwrapper_iterator) { // Perform tests both obfuscated and non-obfuscated. - for (int i = 0; i < 2; i++) { - bool obfuscate = (bool)i; + for (bool obfuscate : {false, true}) { fs::path ph = fs::temp_directory_path() / fs::unique_path(); CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); // The two keys are intentionally chosen for ordering char key = 'j'; - uint256 in = GetRandHash(); + uint256 in = InsecureRand256(); BOOST_CHECK(dbw.Write(key, in)); char key2 = 'k'; - uint256 in2 = GetRandHash(); + uint256 in2 = InsecureRand256(); BOOST_CHECK(dbw.Write(key2, in2)); - std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper*>(&dbw)->NewIterator()); + std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper&>(dbw).NewIterator()); // Be sure to seek past the obfuscation key (if it exists) it->Seek(key); @@ -132,7 +127,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) // Set up a non-obfuscated wrapper to write some initial data. CDBWrapper* dbw = new CDBWrapper(ph, (1 << 10), false, false, false); char key = 'k'; - uint256 in = GetRandHash(); + uint256 in = InsecureRand256(); uint256 res; BOOST_CHECK(dbw->Write(key, in)); @@ -155,7 +150,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) BOOST_CHECK(!odbw.IsEmpty()); // There should be existing data BOOST_CHECK(is_null_key(dbwrapper_private::GetObfuscateKey(odbw))); // The key should be an empty string - uint256 in2 = GetRandHash(); + uint256 in2 = InsecureRand256(); uint256 res3; // Check that we can write successfully @@ -174,7 +169,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex) // Set up a non-obfuscated wrapper to write some initial data. CDBWrapper* dbw = new CDBWrapper(ph, (1 << 10), false, false, false); char key = 'k'; - uint256 in = GetRandHash(); + uint256 in = InsecureRand256(); uint256 res; BOOST_CHECK(dbw->Write(key, in)); @@ -193,7 +188,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex) BOOST_CHECK(!odbw.Read(key, res2)); BOOST_CHECK(!is_null_key(dbwrapper_private::GetObfuscateKey(odbw))); - uint256 in2 = GetRandHash(); + uint256 in2 = InsecureRand256(); uint256 res3; // Check that we can write successfully @@ -212,13 +207,8 @@ BOOST_AUTO_TEST_CASE(iterator_ordering) BOOST_CHECK(dbw.Write(key, value)); } - std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper*>(&dbw)->NewIterator()); - for (int c=0; c<2; ++c) { - int seek_start; - if (c == 0) - seek_start = 0x00; - else - seek_start = 0x80; + std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper&>(dbw).NewIterator()); + for (int seek_start : {0x00, 0x80}) { it->Seek((uint8_t)seek_start); for (int x=seek_start; x<256; ++x) { uint8_t key; @@ -288,13 +278,8 @@ BOOST_AUTO_TEST_CASE(iterator_string_ordering) } } - std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper*>(&dbw)->NewIterator()); - for (int c=0; c<2; ++c) { - int seek_start; - if (c == 0) - seek_start = 0; - else - seek_start = 5; + std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper&>(dbw).NewIterator()); + for (int seek_start : {0, 5}) { snprintf(buf, sizeof(buf), "%d", seek_start); StringContentsSerializer seek_key(buf); it->Seek(seek_key); diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp index 9f59de3ef5..c79675f5a6 100644 --- a/src/test/getarg_tests.cpp +++ b/src/test/getarg_tests.cpp @@ -9,7 +9,6 @@ #include <vector> #include <boost/algorithm/string.hpp> -#include <boost/foreach.hpp> #include <boost/test/unit_test.hpp> BOOST_FIXTURE_TEST_SUITE(getarg_tests, BasicTestingSetup) @@ -25,7 +24,7 @@ static void ResetArgs(const std::string& strArg) // Convert to char*: std::vector<const char*> vecChar; - BOOST_FOREACH(std::string& s, vecArg) + for (std::string& s : vecArg) vecChar.push_back(s.c_str()); ParseParameters(vecChar.size(), &vecChar[0]); diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp index bb7e473248..05b6b3b1e6 100644 --- a/src/test/hash_tests.cpp +++ b/src/test/hash_tests.cpp @@ -134,7 +134,7 @@ BOOST_AUTO_TEST_CASE(siphash) for (int i = 0; i < 16; ++i) { uint64_t k1 = ctx.rand64(); uint64_t k2 = ctx.rand64(); - uint256 x = GetRandHash(); + uint256 x = InsecureRand256(); uint32_t n = ctx.rand32(); uint8_t nb[4]; WriteLE32(nb, n); diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index f2f06fa8e2..1a1cf4399c 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -4,7 +4,6 @@ #include "consensus/merkle.h" #include "test/test_bitcoin.h" -#include "test/test_random.h" #include <boost/test/unit_test.hpp> @@ -68,7 +67,7 @@ BOOST_AUTO_TEST_CASE(merkle_test) { for (int i = 0; i < 32; i++) { // Try 32 block sizes: all sizes from 0 to 16 inclusive, and then 15 random sizes. - int ntx = (i <= 16) ? i : 17 + (insecure_rand() % 4000); + int ntx = (i <= 16) ? i : 17 + (InsecureRandRange(4000)); // Try up to 3 mutations. for (int mutate = 0; mutate <= 3; mutate++) { int duplicate1 = mutate >= 1 ? 1 << ctz(ntx) : 0; // The last how many transactions to duplicate first. @@ -121,7 +120,7 @@ BOOST_AUTO_TEST_CASE(merkle_test) // If ntx <= 16, try all branches. Otherwise, try 16 random ones. int mtx = loop; if (ntx > 16) { - mtx = insecure_rand() % ntx; + mtx = InsecureRandRange(ntx); } std::vector<uint256> newBranch = BlockMerkleBranch(block, mtx); std::vector<uint256> oldBranch = BlockGetMerkleBranch(block, merkleTree, mtx); diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index a40060e657..eaff2ac70d 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -260,7 +260,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) { tx.vout[0].nValue -= LOWFEE; hash = tx.GetHash(); - bool spendsCoinbase = (i == 0) ? true : false; // only first tx spends coinbase + bool spendsCoinbase = i == 0; // only first tx spends coinbase // If we don't set the # of sig ops in the CTxMemPoolEntry, template creation fails mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; @@ -274,7 +274,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) { tx.vout[0].nValue -= LOWFEE; hash = tx.GetHash(); - bool spendsCoinbase = (i == 0) ? true : false; // only first tx spends coinbase + bool spendsCoinbase = i == 0; // only first tx spends coinbase // If we do set the # of sig ops in the CTxMemPoolEntry, template creation passes mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx)); tx.vin[0].prevout.hash = hash; @@ -295,7 +295,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) { tx.vout[0].nValue -= LOWFEE; hash = tx.GetHash(); - bool spendsCoinbase = (i == 0) ? true : false; // only first tx spends coinbase + bool spendsCoinbase = i == 0; // only first tx spends coinbase mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } @@ -372,7 +372,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) while (chainActive.Tip()->nHeight < 209999) { CBlockIndex* prev = chainActive.Tip(); CBlockIndex* next = new CBlockIndex(); - next->phashBlock = new uint256(GetRandHash()); + next->phashBlock = new uint256(InsecureRand256()); pcoinsTip->SetBestBlock(next->GetBlockHash()); next->pprev = prev; next->nHeight = prev->nHeight + 1; @@ -384,7 +384,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) while (chainActive.Tip()->nHeight < 210000) { CBlockIndex* prev = chainActive.Tip(); CBlockIndex* next = new CBlockIndex(); - next->phashBlock = new uint256(GetRandHash()); + next->phashBlock = new uint256(InsecureRand256()); pcoinsTip->SetBestBlock(next->GetBlockHash()); next->pprev = prev; next->nHeight = prev->nHeight + 1; diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index dd5678ea6e..c686f679c2 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -14,7 +14,6 @@ #include "test/test_bitcoin.h" -#include <boost/foreach.hpp> #include <boost/test/unit_test.hpp> typedef std::vector<unsigned char> valtype; @@ -28,7 +27,7 @@ sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transac CScript result; result << OP_0; // CHECKMULTISIG bug workaround - BOOST_FOREACH(const CKey &key, keys) + for (const CKey &key : keys) { std::vector<unsigned char> vchSig; BOOST_CHECK(key.Sign(hash, vchSig)); diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 66354699b2..095d86834c 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -29,7 +29,7 @@ public: class CAddrManUncorrupted : public CAddrManSerializationMock { public: - void Serialize(CDataStream& s) const + void Serialize(CDataStream& s) const override { CAddrMan::Serialize(s); } @@ -38,7 +38,7 @@ public: class CAddrManCorrupted : public CAddrManSerializationMock { public: - void Serialize(CDataStream& s) const + void Serialize(CDataStream& s) const override { // Produces corrupt output that claims addrman has 20 addrs when it only has one addr. unsigned char nVersion = 1; diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index 1afef5b1ce..1baf7643e5 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -4,10 +4,10 @@ #include "netbase.h" #include "test/test_bitcoin.h" +#include "utilstrencodings.h" #include <string> -#include <boost/assign/list_of.hpp> #include <boost/test/unit_test.hpp> BOOST_FIXTURE_TEST_SUITE(netbase_tests, BasicTestingSetup) @@ -26,6 +26,13 @@ static CSubNet ResolveSubNet(const char* subnet) return ret; } +static CNetAddr CreateInternal(const char* host) +{ + CNetAddr addr; + addr.SetInternal(host); + return addr; +} + BOOST_AUTO_TEST_CASE(netbase_networks) { BOOST_CHECK(ResolveIP("127.0.0.1").GetNetwork() == NET_UNROUTABLE); @@ -33,6 +40,7 @@ BOOST_AUTO_TEST_CASE(netbase_networks) BOOST_CHECK(ResolveIP("8.8.8.8").GetNetwork() == NET_IPV4); BOOST_CHECK(ResolveIP("2001::8888").GetNetwork() == NET_IPV6); BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() == NET_TOR); + BOOST_CHECK(CreateInternal("foo.com").GetNetwork() == NET_INTERNAL); } @@ -59,6 +67,8 @@ BOOST_AUTO_TEST_CASE(netbase_properties) BOOST_CHECK(ResolveIP("8.8.8.8").IsRoutable()); BOOST_CHECK(ResolveIP("2001::1").IsRoutable()); BOOST_CHECK(ResolveIP("127.0.0.1").IsValid()); + BOOST_CHECK(CreateInternal("FD6B:88C0:8724:edb1:8e4:3588:e546:35ca").IsInternal()); + BOOST_CHECK(CreateInternal("bar.com").IsInternal()); } @@ -104,6 +114,11 @@ BOOST_AUTO_TEST_CASE(netbase_lookupnumeric) BOOST_CHECK(TestParse("[::]:8333", "[::]:8333")); BOOST_CHECK(TestParse("[127.0.0.1]", "127.0.0.1:65535")); BOOST_CHECK(TestParse(":::", "[::]:0")); + + // verify that an internal address fails to resolve + BOOST_CHECK(TestParse("[fd6b:88c0:8724:1:2:3:4:5]", "[::]:0")); + // and that a one-off resolves correctly + BOOST_CHECK(TestParse("[fd6c:88c0:8724:1:2:3:4:5]", "[fd6c:88c0:8724:1:2:3:4:5]:65535")); } BOOST_AUTO_TEST_CASE(onioncat_test) @@ -269,19 +284,22 @@ BOOST_AUTO_TEST_CASE(subnet_test) BOOST_AUTO_TEST_CASE(netbase_getgroup) { - BOOST_CHECK(ResolveIP("127.0.0.1").GetGroup() == boost::assign::list_of(0)); // Local -> !Routable() - BOOST_CHECK(ResolveIP("257.0.0.1").GetGroup() == boost::assign::list_of(0)); // !Valid -> !Routable() - BOOST_CHECK(ResolveIP("10.0.0.1").GetGroup() == boost::assign::list_of(0)); // RFC1918 -> !Routable() - BOOST_CHECK(ResolveIP("169.254.1.1").GetGroup() == boost::assign::list_of(0)); // RFC3927 -> !Routable() - BOOST_CHECK(ResolveIP("1.2.3.4").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // IPv4 - BOOST_CHECK(ResolveIP("::FFFF:0:102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6145 - BOOST_CHECK(ResolveIP("64:FF9B::102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6052 - BOOST_CHECK(ResolveIP("2002:102:304:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC3964 - BOOST_CHECK(ResolveIP("2001:0:9999:9999:9999:9999:FEFD:FCFB").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC4380 - BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup() == boost::assign::list_of((unsigned char)NET_TOR)(239)); // Tor - BOOST_CHECK(ResolveIP("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(4)(112)(175)); //he.net - BOOST_CHECK(ResolveIP("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(32)(1)); //IPv6 + BOOST_CHECK(ResolveIP("127.0.0.1").GetGroup() == std::vector<unsigned char>({0})); // Local -> !Routable() + BOOST_CHECK(ResolveIP("257.0.0.1").GetGroup() == std::vector<unsigned char>({0})); // !Valid -> !Routable() + BOOST_CHECK(ResolveIP("10.0.0.1").GetGroup() == std::vector<unsigned char>({0})); // RFC1918 -> !Routable() + BOOST_CHECK(ResolveIP("169.254.1.1").GetGroup() == std::vector<unsigned char>({0})); // RFC3927 -> !Routable() + BOOST_CHECK(ResolveIP("1.2.3.4").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // IPv4 + BOOST_CHECK(ResolveIP("::FFFF:0:102:304").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC6145 + BOOST_CHECK(ResolveIP("64:FF9B::102:304").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC6052 + BOOST_CHECK(ResolveIP("2002:102:304:9999:9999:9999:9999:9999").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC3964 + BOOST_CHECK(ResolveIP("2001:0:9999:9999:9999:9999:FEFD:FCFB").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC4380 + BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_TOR, 239})); // Tor + BOOST_CHECK(ResolveIP("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV6, 32, 1, 4, 112, 175})); //he.net + BOOST_CHECK(ResolveIP("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV6, 32, 1, 32, 1})); //IPv6 + // baz.net sha256 hash: 12929400eb4607c4ac075f087167e75286b179c693eb059a01774b864e8fe505 + std::vector<unsigned char> internal_group = {NET_INTERNAL, 0x12, 0x92, 0x94, 0x00, 0xeb, 0x46, 0x07, 0xc4, 0xac, 0x07}; + BOOST_CHECK(CreateInternal("baz.net").GetGroup() == internal_group); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index a1cb32019a..c1d216d094 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -10,11 +10,9 @@ #include "arith_uint256.h" #include "version.h" #include "test/test_bitcoin.h" -#include "test/test_random.h" #include <vector> -#include <boost/assign/list_of.hpp> #include <boost/test/unit_test.hpp> class CPartialMerkleTreeTester : public CPartialMerkleTree @@ -22,8 +20,8 @@ class CPartialMerkleTreeTester : public CPartialMerkleTree public: // flip one bit in one of the hashes - this should break the authentication void Damage() { - unsigned int n = insecure_rand() % vHash.size(); - int bit = insecure_rand() % 256; + unsigned int n = InsecureRandRange(vHash.size()); + int bit = InsecureRandBits(8); *(vHash[n].begin() + (bit>>3)) ^= 1<<(bit&7); } }; @@ -32,7 +30,7 @@ BOOST_FIXTURE_TEST_SUITE(pmt_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(pmt_test1) { - seed_insecure_rand(false); + SeedInsecureRand(false); static const unsigned int nTxCounts[] = {1, 4, 7, 17, 56, 100, 127, 256, 312, 513, 1000, 4095}; for (int i = 0; i < 12; i++) { @@ -63,7 +61,7 @@ BOOST_AUTO_TEST_CASE(pmt_test1) std::vector<bool> vMatch(nTx, false); std::vector<uint256> vMatchTxid1; for (unsigned int j=0; j<nTx; j++) { - bool fInclude = (insecure_rand() & ((1 << (att/2)) - 1)) == 0; + bool fInclude = InsecureRandBits(att / 2) == 0; vMatch[j] = fInclude; if (fInclude) vMatchTxid1.push_back(vTxid[j]); @@ -110,14 +108,15 @@ BOOST_AUTO_TEST_CASE(pmt_test1) BOOST_AUTO_TEST_CASE(pmt_malleability) { - std::vector<uint256> vTxid = boost::assign::list_of - (ArithToUint256(1))(ArithToUint256(2)) - (ArithToUint256(3))(ArithToUint256(4)) - (ArithToUint256(5))(ArithToUint256(6)) - (ArithToUint256(7))(ArithToUint256(8)) - (ArithToUint256(9))(ArithToUint256(10)) - (ArithToUint256(9))(ArithToUint256(10)); - std::vector<bool> vMatch = boost::assign::list_of(false)(false)(false)(false)(false)(false)(false)(false)(false)(true)(true)(false); + std::vector<uint256> vTxid = { + ArithToUint256(1), ArithToUint256(2), + ArithToUint256(3), ArithToUint256(4), + ArithToUint256(5), ArithToUint256(6), + ArithToUint256(7), ArithToUint256(8), + ArithToUint256(9), ArithToUint256(10), + ArithToUint256(9), ArithToUint256(10), + }; + std::vector<bool> vMatch = {false, false, false, false, false, false, false, false, false, true, true, false}; CPartialMerkleTree tree(vTxid, vMatch); std::vector<unsigned int> vIndex; diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp index 6bfd315647..fd8f7191f4 100644 --- a/src/test/policyestimator_tests.cpp +++ b/src/test/policyestimator_tests.cpp @@ -177,16 +177,6 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) for (int i = 2; i < 9; i++) { // At 9, the original estimate was already at the bottom (b/c scale = 2) BOOST_CHECK(feeEst.estimateFee(i).GetFeePerK() < origFeeEst[i-1] - deltaFee); } - - // Test that if the mempool is limited, estimateSmartFee won't return a value below the mempool min fee - mpool.addUnchecked(tx.GetHash(), entry.Fee(feeV[5]).Time(GetTime()).Height(blocknum).FromTx(tx)); - // evict that transaction which should set a mempool min fee of minRelayTxFee + feeV[5] - mpool.TrimToSize(1); - BOOST_CHECK(mpool.GetMinFee(1).GetFeePerK() > feeV[5]); - for (int i = 1; i < 10; i++) { - BOOST_CHECK(feeEst.estimateSmartFee(i, NULL, mpool).GetFeePerK() >= feeEst.estimateRawFee(i, 0.85, FeeEstimateHorizon::MED_HALFLIFE).GetFeePerK()); - BOOST_CHECK(feeEst.estimateSmartFee(i, NULL, mpool).GetFeePerK() >= mpool.GetMinFee(1).GetFeePerK()); - } } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 3b79f8000d..b9fabd02e4 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -74,9 +74,9 @@ BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test) } for (int j = 0; j < 1000; j++) { - CBlockIndex *p1 = &blocks[GetRand(10000)]; - CBlockIndex *p2 = &blocks[GetRand(10000)]; - CBlockIndex *p3 = &blocks[GetRand(10000)]; + CBlockIndex *p1 = &blocks[InsecureRandRange(10000)]; + CBlockIndex *p2 = &blocks[InsecureRandRange(10000)]; + CBlockIndex *p3 = &blocks[InsecureRandRange(10000)]; int64_t tdiff = GetBlockProofEquivalentTime(*p1, *p2, *p3, chainParams->GetConsensus()); BOOST_CHECK_EQUAL(tdiff, p1->GetBlockTime() - p2->GetBlockTime()); diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index cfed5e347e..345c4a2148 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -5,11 +5,11 @@ #include <vector> #include "prevector.h" +#include "reverse_iterator.h" #include "serialize.h" #include "streams.h" #include "test/test_bitcoin.h" -#include "test/test_random.h" #include <boost/test/unit_test.hpp> @@ -54,16 +54,16 @@ class prevector_tester { local_check(pretype(real_vector.begin(), real_vector.end()) == pre_vector); local_check(pretype(pre_vector.begin(), pre_vector.end()) == pre_vector); size_t pos = 0; - BOOST_FOREACH(const T& v, pre_vector) { + for (const T& v : pre_vector) { local_check(v == real_vector[pos++]); } - BOOST_REVERSE_FOREACH(const T& v, pre_vector) { + for (const T& v : reverse_iterate(pre_vector)) { local_check(v == real_vector[--pos]); } - BOOST_FOREACH(const T& v, const_pre_vector) { + for (const T& v : const_pre_vector) { local_check(v == real_vector[pos++]); } - BOOST_REVERSE_FOREACH(const T& v, const_pre_vector) { + for (const T& v : reverse_iterate(const_pre_vector)) { local_check(v == real_vector[--pos]); } CDataStream ss1(SER_DISK, 0); @@ -188,7 +188,7 @@ public: } prevector_tester() { - seed_insecure_rand(); + SeedInsecureRand(); rand_seed = insecure_rand_seed; rand_cache = insecure_rand_ctx; } @@ -199,67 +199,65 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt) for (int j = 0; j < 64; j++) { prevector_tester<8, int> test; for (int i = 0; i < 2048; i++) { - int r = insecure_rand(); - if ((r % 4) == 0) { - test.insert(insecure_rand() % (test.size() + 1), insecure_rand()); + if (InsecureRandBits(2) == 0) { + test.insert(InsecureRandRange(test.size() + 1), InsecureRand32()); } - if (test.size() > 0 && ((r >> 2) % 4) == 1) { - test.erase(insecure_rand() % test.size()); + if (test.size() > 0 && InsecureRandBits(2) == 1) { + test.erase(InsecureRandRange(test.size())); } - if (((r >> 4) % 8) == 2) { - int new_size = std::max<int>(0, std::min<int>(30, test.size() + (insecure_rand() % 5) - 2)); + if (InsecureRandBits(3) == 2) { + int new_size = std::max<int>(0, std::min<int>(30, test.size() + (InsecureRandRange(5)) - 2)); test.resize(new_size); } - if (((r >> 7) % 8) == 3) { - test.insert(insecure_rand() % (test.size() + 1), 1 + (insecure_rand() % 2), insecure_rand()); + if (InsecureRandBits(3) == 3) { + test.insert(InsecureRandRange(test.size() + 1), 1 + InsecureRandBool(), InsecureRand32()); } - if (((r >> 10) % 8) == 4) { - int del = std::min<int>(test.size(), 1 + (insecure_rand() % 2)); - int beg = insecure_rand() % (test.size() + 1 - del); + if (InsecureRandBits(3) == 4) { + int del = std::min<int>(test.size(), 1 + (InsecureRandBool())); + int beg = InsecureRandRange(test.size() + 1 - del); test.erase(beg, beg + del); } - if (((r >> 13) % 16) == 5) { - test.push_back(insecure_rand()); + if (InsecureRandBits(4) == 5) { + test.push_back(InsecureRand32()); } - if (test.size() > 0 && ((r >> 17) % 16) == 6) { + if (test.size() > 0 && InsecureRandBits(4) == 6) { test.pop_back(); } - if (((r >> 21) % 32) == 7) { + if (InsecureRandBits(5) == 7) { int values[4]; - int num = 1 + (insecure_rand() % 4); + int num = 1 + (InsecureRandBits(2)); for (int k = 0; k < num; k++) { - values[k] = insecure_rand(); + values[k] = InsecureRand32(); } - test.insert_range(insecure_rand() % (test.size() + 1), values, values + num); + test.insert_range(InsecureRandRange(test.size() + 1), values, values + num); } - if (((r >> 26) % 32) == 8) { - int del = std::min<int>(test.size(), 1 + (insecure_rand() % 4)); - int beg = insecure_rand() % (test.size() + 1 - del); + if (InsecureRandBits(5) == 8) { + int del = std::min<int>(test.size(), 1 + (InsecureRandBits(2))); + int beg = InsecureRandRange(test.size() + 1 - del); test.erase(beg, beg + del); } - r = insecure_rand(); - if (r % 32 == 9) { - test.reserve(insecure_rand() % 32); + if (InsecureRandBits(5) == 9) { + test.reserve(InsecureRandBits(5)); } - if ((r >> 5) % 64 == 10) { + if (InsecureRandBits(6) == 10) { test.shrink_to_fit(); } if (test.size() > 0) { - test.update(insecure_rand() % test.size(), insecure_rand()); + test.update(InsecureRandRange(test.size()), InsecureRand32()); } - if (((r >> 11) % 1024) == 11) { + if (InsecureRandBits(10) == 11) { test.clear(); } - if (((r >> 21) % 512) == 12) { - test.assign(insecure_rand() % 32, insecure_rand()); + if (InsecureRandBits(9) == 12) { + test.assign(InsecureRandBits(5), InsecureRand32()); } - if (((r >> 15) % 8) == 3) { + if (InsecureRandBits(3) == 3) { test.swap(); } - if (((r >> 15) % 16) == 8) { + if (InsecureRandBits(4) == 8) { test.copy(); } - if (((r >> 15) % 32) == 18) { + if (InsecureRandBits(5) == 18) { test.move(); } } diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp index 8596734226..132e190051 100644 --- a/src/test/random_tests.cpp +++ b/src/test/random_tests.cpp @@ -25,14 +25,21 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests) BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); BOOST_CHECK_EQUAL(ctx1.rand64(), ctx2.rand64()); BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3)); + BOOST_CHECK(ctx1.randbytes(17) == ctx2.randbytes(17)); + BOOST_CHECK(ctx1.rand256() == ctx2.rand256()); BOOST_CHECK_EQUAL(ctx1.randbits(7), ctx2.randbits(7)); + BOOST_CHECK(ctx1.randbytes(128) == ctx2.randbytes(128)); BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3)); + BOOST_CHECK(ctx1.rand256() == ctx2.rand256()); + BOOST_CHECK(ctx1.randbytes(50) == ctx2.randbytes(50)); // Check that a nondeterministic ones are not FastRandomContext ctx3; FastRandomContext ctx4; BOOST_CHECK(ctx3.rand64() != ctx4.rand64()); // extremely unlikely to be equal + BOOST_CHECK(ctx3.rand256() != ctx4.rand256()); + BOOST_CHECK(ctx3.randbytes(7) != ctx4.randbytes(7)); } BOOST_AUTO_TEST_CASE(fastrandom_randbits) diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 7cf2a744ea..134bd7c609 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -11,7 +11,6 @@ #include "test/test_bitcoin.h" #include <boost/algorithm/string.hpp> -#include <boost/assign/list_of.hpp> #include <boost/test/unit_test.hpp> #include <univalue.h> @@ -324,20 +323,20 @@ BOOST_AUTO_TEST_CASE(rpc_convert_values_generatetoaddress) { UniValue result; - BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("101")("mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a"))); + BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"101", "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a"})); BOOST_CHECK_EQUAL(result[0].get_int(), 101); BOOST_CHECK_EQUAL(result[1].get_str(), "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a"); - BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("101")("mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU"))); + BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"101", "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU"})); BOOST_CHECK_EQUAL(result[0].get_int(), 101); BOOST_CHECK_EQUAL(result[1].get_str(), "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU"); - BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("1")("mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a")("9"))); + BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"1", "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a", "9"})); BOOST_CHECK_EQUAL(result[0].get_int(), 1); BOOST_CHECK_EQUAL(result[1].get_str(), "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a"); BOOST_CHECK_EQUAL(result[2].get_int(), 9); - BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("1")("mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU")("9"))); + BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"1", "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU", "9"})); BOOST_CHECK_EQUAL(result[0].get_int(), 1); BOOST_CHECK_EQUAL(result[1].get_str(), "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU"); BOOST_CHECK_EQUAL(result[2].get_int(), 9); diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp index e4ddf9d618..1de865776e 100644 --- a/src/test/scheduler_tests.cpp +++ b/src/test/scheduler_tests.cpp @@ -8,8 +8,6 @@ #include "test/test_bitcoin.h" #include <boost/bind.hpp> -#include <boost/random/mersenne_twister.hpp> -#include <boost/random/uniform_int_distribution.hpp> #include <boost/thread.hpp> #include <boost/test/unit_test.hpp> @@ -56,10 +54,10 @@ BOOST_AUTO_TEST_CASE(manythreads) boost::mutex counterMutex[10]; int counter[10] = { 0 }; - boost::random::mt19937 rng(42); - boost::random::uniform_int_distribution<> zeroToNine(0, 9); - boost::random::uniform_int_distribution<> randomMsec(-11, 1000); - boost::random::uniform_int_distribution<> randomDelta(-1000, 1000); + FastRandomContext rng(42); + auto zeroToNine = [](FastRandomContext& rc) -> int { return rc.randrange(10); }; // [0, 9] + auto randomMsec = [](FastRandomContext& rc) -> int { return -11 + rc.randrange(1012); }; // [-11, 1000] + auto randomDelta = [](FastRandomContext& rc) -> int { return -1000 + rc.randrange(2001); }; // [-1000, 1000] boost::chrono::system_clock::time_point start = boost::chrono::system_clock::now(); boost::chrono::system_clock::time_point now = start; diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 343c645cb1..a18471588a 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -24,7 +24,6 @@ #include <string> #include <vector> -#include <boost/foreach.hpp> #include <boost/test/unit_test.hpp> #include <univalue.h> @@ -468,7 +467,7 @@ std::string JSONPrettyPrint(const UniValue& univalue) } return ret; } -} +} // namespace BOOST_AUTO_TEST_CASE(script_build) { @@ -927,7 +926,7 @@ BOOST_AUTO_TEST_CASE(script_build) std::string strGen; - BOOST_FOREACH(TestBuilder& test, tests) { + for (TestBuilder& test : tests) { test.Test(); std::string str = JSONPrettyPrint(test.GetJSON()); #ifndef UPDATE_JSON_TESTS @@ -1033,7 +1032,7 @@ sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transac // and vice-versa) // result << OP_0; - BOOST_FOREACH(const CKey &key, keys) + for (const CKey &key : keys) { std::vector<unsigned char> vchSig; BOOST_CHECK(key.Sign(hash, vchSig)); @@ -1438,4 +1437,18 @@ BOOST_AUTO_TEST_CASE(script_FindAndDelete) BOOST_CHECK(s == expect); } +BOOST_AUTO_TEST_CASE(script_HasValidOps) +{ + // Exercise the HasValidOps functionality + CScript script; + script = ScriptFromHex("76a9141234567890abcdefa1a2a3a4a5a6a7a8a9a0aaab88ac"); // Normal script + BOOST_CHECK(script.HasValidOps()); + script = ScriptFromHex("76a914ff34567890abcdefa1a2a3a4a5a6a7a8a9a0aaab88ac"); + BOOST_CHECK(script.HasValidOps()); + script = ScriptFromHex("ff88ac"); // Script with OP_INVALIDOPCODE explicit + BOOST_CHECK(!script.HasValidOps()); + script = ScriptFromHex("88acc0"); // Script with undefined opcode + BOOST_CHECK(!script.HasValidOps()); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 2f7c22084e..1ca83a7cf8 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -11,7 +11,6 @@ #include "serialize.h" #include "streams.h" #include "test/test_bitcoin.h" -#include "test/test_random.h" #include "util.h" #include "utilstrencodings.h" #include "version.h" @@ -30,7 +29,6 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); if (nIn >= txTo.vin.size()) { - printf("ERROR: SignatureHash(): nIn=%d out of range\n", nIn); return one; } CMutableTransaction txTmp(txTo); @@ -61,7 +59,6 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un unsigned int nOut = nIn; if (nOut >= txTmp.vout.size()) { - printf("ERROR: SignatureHash(): nOut=%d out of range\n", nOut); return one; } txTmp.vout.resize(nOut+1); @@ -90,30 +87,30 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un void static RandomScript(CScript &script) { static const opcodetype oplist[] = {OP_FALSE, OP_1, OP_2, OP_3, OP_CHECKSIG, OP_IF, OP_VERIF, OP_RETURN, OP_CODESEPARATOR}; script = CScript(); - int ops = (insecure_rand() % 10); + int ops = (InsecureRandRange(10)); for (int i=0; i<ops; i++) - script << oplist[insecure_rand() % (sizeof(oplist)/sizeof(oplist[0]))]; + script << oplist[InsecureRandRange(sizeof(oplist)/sizeof(oplist[0]))]; } void static RandomTransaction(CMutableTransaction &tx, bool fSingle) { - tx.nVersion = insecure_rand(); + tx.nVersion = InsecureRand32(); tx.vin.clear(); tx.vout.clear(); - tx.nLockTime = (insecure_rand() % 2) ? insecure_rand() : 0; - int ins = (insecure_rand() % 4) + 1; - int outs = fSingle ? ins : (insecure_rand() % 4) + 1; + tx.nLockTime = (InsecureRandBool()) ? InsecureRand32() : 0; + int ins = (InsecureRandBits(2)) + 1; + int outs = fSingle ? ins : (InsecureRandBits(2)) + 1; for (int in = 0; in < ins; in++) { tx.vin.push_back(CTxIn()); CTxIn &txin = tx.vin.back(); - txin.prevout.hash = GetRandHash(); - txin.prevout.n = insecure_rand() % 4; + txin.prevout.hash = InsecureRand256(); + txin.prevout.n = InsecureRandBits(2); RandomScript(txin.scriptSig); - txin.nSequence = (insecure_rand() % 2) ? insecure_rand() : (unsigned int)-1; + txin.nSequence = (InsecureRandBool()) ? InsecureRand32() : (unsigned int)-1; } for (int out = 0; out < outs; out++) { tx.vout.push_back(CTxOut()); CTxOut &txout = tx.vout.back(); - txout.nValue = insecure_rand() % 100000000; + txout.nValue = InsecureRandRange(100000000); RandomScript(txout.scriptPubKey); } } @@ -122,7 +119,7 @@ BOOST_FIXTURE_TEST_SUITE(sighash_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(sighash_test) { - seed_insecure_rand(false); + SeedInsecureRand(false); #if defined(PRINT_SIGHASH_JSON) std::cout << "[\n"; @@ -134,12 +131,12 @@ BOOST_AUTO_TEST_CASE(sighash_test) nRandomTests = 500; #endif for (int i=0; i<nRandomTests; i++) { - int nHashType = insecure_rand(); + int nHashType = InsecureRand32(); CMutableTransaction txTo; RandomTransaction(txTo, (nHashType & 0x1f) == SIGHASH_SINGLE); CScript scriptCode; RandomScript(scriptCode); - int nIn = insecure_rand() % txTo.vin.size(); + int nIn = InsecureRandRange(txTo.vin.size()); uint256 sh, sho; sho = SignatureHashOld(scriptCode, txTo, nIn, nHashType); diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp index 4e117448fe..d3b8b07228 100644 --- a/src/test/sigopcount_tests.cpp +++ b/src/test/sigopcount_tests.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "consensus/tx_verify.h" +#include "consensus/validation.h" #include "pubkey.h" #include "key.h" #include "script/script.h" @@ -12,7 +13,6 @@ #include <vector> -#include <boost/foreach.hpp> #include <boost/test/unit_test.hpp> // Helpers: diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp index 0b2fe0ef9d..77c321cdf6 100644 --- a/src/test/skiplist_tests.cpp +++ b/src/test/skiplist_tests.cpp @@ -5,7 +5,6 @@ #include "chain.h" #include "util.h" #include "test/test_bitcoin.h" -#include "test/test_random.h" #include <vector> @@ -35,8 +34,8 @@ BOOST_AUTO_TEST_CASE(skiplist_test) } for (int i=0; i < 1000; i++) { - int from = insecure_rand() % (SKIPLIST_LENGTH - 1); - int to = insecure_rand() % (from + 1); + int from = InsecureRandRange(SKIPLIST_LENGTH - 1); + int to = InsecureRandRange(from + 1); BOOST_CHECK(vIndex[SKIPLIST_LENGTH - 1].GetAncestor(from) == &vIndex[from]); BOOST_CHECK(vIndex[from].GetAncestor(to) == &vIndex[to]); @@ -78,7 +77,7 @@ BOOST_AUTO_TEST_CASE(getlocator_test) // Test 100 random starting points for locators. for (int n=0; n<100; n++) { - int r = insecure_rand() % 150000; + int r = InsecureRandRange(150000); CBlockIndex* tip = (r < 100000) ? &vBlocksMain[r] : &vBlocksSide[r - 100000]; CBlockLocator locator = chain.GetLocator(tip); @@ -116,7 +115,7 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_test) } else { // randomly choose something in the range [MTP, MTP*2] int64_t medianTimePast = vBlocksMain[i].GetMedianTimePast(); - int r = insecure_rand() % medianTimePast; + int r = InsecureRandRange(medianTimePast); vBlocksMain[i].nTime = r + medianTimePast; vBlocksMain[i].nTimeMax = std::max(vBlocksMain[i].nTime, vBlocksMain[i-1].nTimeMax); } @@ -135,7 +134,7 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_test) // Verify that FindEarliestAtLeast is correct. for (unsigned int i=0; i<10000; ++i) { // Pick a random element in vBlocksMain. - int r = insecure_rand() % vBlocksMain.size(); + int r = InsecureRandRange(vBlocksMain.size()); int64_t test_time = vBlocksMain[r].nTime; CBlockIndex *ret = chain.FindEarliestAtLeast(test_time); BOOST_CHECK(ret->nTimeMax >= test_time); @@ -143,4 +142,39 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_test) BOOST_CHECK(vBlocksMain[r].GetAncestor(ret->nHeight) == ret); } } + +BOOST_AUTO_TEST_CASE(findearliestatleast_edge_test) +{ + std::list<CBlockIndex> blocks; + for (unsigned int timeMax : {100, 100, 100, 200, 200, 200, 300, 300, 300}) { + CBlockIndex* prev = blocks.empty() ? nullptr : &blocks.back(); + blocks.emplace_back(); + blocks.back().nHeight = prev ? prev->nHeight + 1 : 0; + blocks.back().pprev = prev; + blocks.back().BuildSkip(); + blocks.back().nTimeMax = timeMax; + } + + CChain chain; + chain.SetTip(&blocks.back()); + + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(50)->nHeight, 0); + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(100)->nHeight, 0); + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(150)->nHeight, 3); + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(200)->nHeight, 3); + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(250)->nHeight, 6); + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(300)->nHeight, 6); + BOOST_CHECK(!chain.FindEarliestAtLeast(350)); + + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0)->nHeight, 0); + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-1)->nHeight, 0); + + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::min())->nHeight, 0); + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(std::numeric_limits<unsigned int>::min())->nHeight, 0); + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-int64_t(std::numeric_limits<unsigned int>::max()) - 1)->nHeight, 0); + BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::max())); + BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<unsigned int>::max())); + BOOST_CHECK(!chain.FindEarliestAtLeast(int64_t(std::numeric_limits<unsigned int>::max()) + 1)); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp index 94b5cc119b..af2a152aa5 100644 --- a/src/test/streams_tests.cpp +++ b/src/test/streams_tests.cpp @@ -7,7 +7,6 @@ #include "test/test_bitcoin.h" #include <boost/assign/std/vector.hpp> // for 'operator+=()' -#include <boost/assert.hpp> #include <boost/test/unit_test.hpp> using namespace boost::assign; // bring 'operator+=()' into scope diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index cb625bda11..0dd51a4908 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -7,6 +7,7 @@ #include "chainparams.h" #include "consensus/consensus.h" #include "consensus/validation.h" +#include "crypto/sha256.h" #include "fs.h" #include "key.h" #include "validation.h" @@ -25,8 +26,6 @@ #include <memory> -#include <boost/thread.hpp> - uint256 insecure_rand_seed = GetRandHash(); FastRandomContext insecure_rand_ctx(insecure_rand_seed); @@ -35,10 +34,13 @@ extern void noui_connect(); BasicTestingSetup::BasicTestingSetup(const std::string& chainName) { + SHA256AutoDetect(); + RandomInit(); ECC_Start(); SetupEnvironment(); SetupNetworking(); InitSignatureCache(); + InitScriptExecutionCache(); fPrintToDebugLog = false; // don't want to write to debug.log file fCheckBlockIndex = true; SelectParams(chainName); @@ -59,9 +61,15 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha RegisterAllCoreRPCCommands(tableRPC); ClearDatadirCache(); - pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); + pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(100000))); fs::create_directories(pathTemp); ForceSetArg("-datadir", pathTemp.string()); + + // Note that because we don't bother running a scheduler thread here, + // callbacks via CValidationInterface are unreliable, but that's OK, + // our unit tests aren't testing multiple parts of the code at once. + GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); + mempool.setSanityCheck(1.0); pblocktree = new CBlockTreeDB(1 << 20, true); pcoinsdbview = new CCoinsViewDB(1 << 23, true); @@ -88,6 +96,8 @@ TestingSetup::~TestingSetup() UnregisterNodeSignals(GetNodeSignals()); threadGroup.interrupt_all(); threadGroup.join_all(); + GetMainSignals().FlushBackgroundCallbacks(); + GetMainSignals().UnregisterBackgroundSignalScheduler(); UnloadBlockIndex(); delete pcoinsTip; delete pcoinsdbview; @@ -121,7 +131,7 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>& // Replace mempool-selected txns with just coinbase plus passed-in txns: block.vtx.resize(1); - BOOST_FOREACH(const CMutableTransaction& tx, txns) + for (const CMutableTransaction& tx : txns) block.vtx.push_back(MakeTransactionRef(tx)); // IncrementExtraNonce creates a valid coinbase and merkleRoot unsigned int extraNonce = 0; diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h index 60a86d8c48..dd3b13c8c8 100644 --- a/src/test/test_bitcoin.h +++ b/src/test/test_bitcoin.h @@ -9,11 +9,32 @@ #include "fs.h" #include "key.h" #include "pubkey.h" +#include "random.h" +#include "scheduler.h" #include "txdb.h" #include "txmempool.h" #include <boost/thread.hpp> +extern uint256 insecure_rand_seed; +extern FastRandomContext insecure_rand_ctx; + +static inline void SeedInsecureRand(bool fDeterministic = false) +{ + if (fDeterministic) { + insecure_rand_seed = uint256(); + } else { + insecure_rand_seed = GetRandHash(); + } + insecure_rand_ctx = FastRandomContext(insecure_rand_seed); +} + +static inline uint32_t InsecureRand32() { return insecure_rand_ctx.rand32(); } +static inline uint256 InsecureRand256() { return insecure_rand_ctx.rand256(); } +static inline uint64_t InsecureRandBits(int bits) { return insecure_rand_ctx.randbits(bits); } +static inline uint64_t InsecureRandRange(uint64_t range) { return insecure_rand_ctx.randrange(range); } +static inline bool InsecureRandBool() { return insecure_rand_ctx.randbool(); } + /** Basic testing setup. * This just configures logging and chain parameters. */ @@ -33,6 +54,7 @@ struct TestingSetup: public BasicTestingSetup { fs::path pathTemp; boost::thread_group threadGroup; CConnman* connman; + CScheduler scheduler; TestingSetup(const std::string& chainName = CBaseChainParams::MAIN); ~TestingSetup(); diff --git a/src/test/test_random.h b/src/test/test_random.h deleted file mode 100644 index 318c44df4d..0000000000 --- a/src/test/test_random.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-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. - -#ifndef BITCOIN_TEST_RANDOM_H -#define BITCOIN_TEST_RANDOM_H - -#include "random.h" - -extern uint256 insecure_rand_seed; -extern FastRandomContext insecure_rand_ctx; - -static inline void seed_insecure_rand(bool fDeterministic = false) -{ - if (fDeterministic) { - insecure_rand_seed = uint256(); - } else { - insecure_rand_seed = GetRandHash(); - } - insecure_rand_ctx = FastRandomContext(insecure_rand_seed); -} - -static inline uint32_t insecure_rand(void) -{ - return insecure_rand_ctx.rand32(); -} - -#endif diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 5c7516fbf1..6654634bf1 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -26,10 +26,7 @@ #include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/split.hpp> -#include <boost/assign/list_of.hpp> #include <boost/test/unit_test.hpp> -#include <boost/assign/list_of.hpp> -#include <boost/foreach.hpp> #include <univalue.h> @@ -38,24 +35,25 @@ typedef std::vector<unsigned char> valtype; // In script_tests.cpp extern UniValue read_json(const std::string& jsondata); -static std::map<std::string, unsigned int> mapFlagNames = boost::assign::map_list_of - (std::string("NONE"), (unsigned int)SCRIPT_VERIFY_NONE) - (std::string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH) - (std::string("STRICTENC"), (unsigned int)SCRIPT_VERIFY_STRICTENC) - (std::string("DERSIG"), (unsigned int)SCRIPT_VERIFY_DERSIG) - (std::string("LOW_S"), (unsigned int)SCRIPT_VERIFY_LOW_S) - (std::string("SIGPUSHONLY"), (unsigned int)SCRIPT_VERIFY_SIGPUSHONLY) - (std::string("MINIMALDATA"), (unsigned int)SCRIPT_VERIFY_MINIMALDATA) - (std::string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY) - (std::string("DISCOURAGE_UPGRADABLE_NOPS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) - (std::string("CLEANSTACK"), (unsigned int)SCRIPT_VERIFY_CLEANSTACK) - (std::string("MINIMALIF"), (unsigned int)SCRIPT_VERIFY_MINIMALIF) - (std::string("NULLFAIL"), (unsigned int)SCRIPT_VERIFY_NULLFAIL) - (std::string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) - (std::string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY) - (std::string("WITNESS"), (unsigned int)SCRIPT_VERIFY_WITNESS) - (std::string("DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) - (std::string("WITNESS_PUBKEYTYPE"), (unsigned int)SCRIPT_VERIFY_WITNESS_PUBKEYTYPE); +static std::map<std::string, unsigned int> mapFlagNames = { + {std::string("NONE"), (unsigned int)SCRIPT_VERIFY_NONE}, + {std::string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH}, + {std::string("STRICTENC"), (unsigned int)SCRIPT_VERIFY_STRICTENC}, + {std::string("DERSIG"), (unsigned int)SCRIPT_VERIFY_DERSIG}, + {std::string("LOW_S"), (unsigned int)SCRIPT_VERIFY_LOW_S}, + {std::string("SIGPUSHONLY"), (unsigned int)SCRIPT_VERIFY_SIGPUSHONLY}, + {std::string("MINIMALDATA"), (unsigned int)SCRIPT_VERIFY_MINIMALDATA}, + {std::string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY}, + {std::string("DISCOURAGE_UPGRADABLE_NOPS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS}, + {std::string("CLEANSTACK"), (unsigned int)SCRIPT_VERIFY_CLEANSTACK}, + {std::string("MINIMALIF"), (unsigned int)SCRIPT_VERIFY_MINIMALIF}, + {std::string("NULLFAIL"), (unsigned int)SCRIPT_VERIFY_NULLFAIL}, + {std::string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY}, + {std::string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY}, + {std::string("WITNESS"), (unsigned int)SCRIPT_VERIFY_WITNESS}, + {std::string("DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM}, + {std::string("WITNESS_PUBKEYTYPE"), (unsigned int)SCRIPT_VERIFY_WITNESS_PUBKEYTYPE}, +}; unsigned int ParseScriptFlags(std::string strFlags) { @@ -66,7 +64,7 @@ unsigned int ParseScriptFlags(std::string strFlags) std::vector<std::string> words; boost::algorithm::split(words, strFlags, boost::algorithm::is_any_of(",")); - BOOST_FOREACH(std::string word, words) + for (std::string word : words) { if (!mapFlagNames.count(word)) BOOST_ERROR("Bad test: unknown verification flag '" << word << "'"); @@ -394,7 +392,7 @@ void CheckWithFlag(const CTransactionRef& output, const CMutableTransaction& inp static CScript PushAll(const std::vector<valtype>& values) { CScript result; - BOOST_FOREACH(const valtype& v, values) { + for (const valtype& v : values) { if (v.size() == 0) { result << OP_0; } else if (v.size() == 1 && v[0] >= 1 && v[0] <= 16) { @@ -694,7 +692,7 @@ BOOST_AUTO_TEST_CASE(test_IsStandard) BOOST_CHECK(IsStandardTx(t, reason)); // Check dust with default relay fee: - CAmount nDustThreshold = 182 * dustRelayFee.GetFeePerK()/1000 * 3; + CAmount nDustThreshold = 182 * dustRelayFee.GetFeePerK()/1000; BOOST_CHECK_EQUAL(nDustThreshold, 546); // dust: t.vout[0].nValue = nDustThreshold - 1; @@ -704,13 +702,13 @@ BOOST_AUTO_TEST_CASE(test_IsStandard) BOOST_CHECK(IsStandardTx(t, reason)); // Check dust with odd relay fee to verify rounding: - // nDustThreshold = 182 * 1234 / 1000 * 3 - dustRelayFee = CFeeRate(1234); + // nDustThreshold = 182 * 3702 / 1000 + dustRelayFee = CFeeRate(3702); // dust: - t.vout[0].nValue = 672 - 1; + t.vout[0].nValue = 673 - 1; BOOST_CHECK(!IsStandardTx(t, reason)); // not dust: - t.vout[0].nValue = 672; + t.vout[0].nValue = 673; BOOST_CHECK(IsStandardTx(t, reason)); dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE); diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp index c5367208ba..f609cb1af4 100644 --- a/src/test/txvalidationcache_tests.cpp +++ b/src/test/txvalidationcache_tests.cpp @@ -10,11 +10,17 @@ #include "txmempool.h" #include "random.h" #include "script/standard.h" +#include "script/sign.h" #include "test/test_bitcoin.h" #include "utiltime.h" +#include "core_io.h" +#include "keystore.h" +#include "policy/policy.h" #include <boost/test/unit_test.hpp> +bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks); + BOOST_AUTO_TEST_SUITE(tx_validationcache_tests) static bool @@ -84,4 +90,282 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) BOOST_CHECK_EQUAL(mempool.size(), 0); } +// Run CheckInputs (using pcoinsTip) on the given transaction, for all script +// flags. Test that CheckInputs passes for all flags that don't overlap with +// the failing_flags argument, but otherwise fails. +// CHECKLOCKTIMEVERIFY and CHECKSEQUENCEVERIFY (and future NOP codes that may +// get reassigned) have an interaction with DISCOURAGE_UPGRADABLE_NOPS: if +// the script flags used contain DISCOURAGE_UPGRADABLE_NOPS but don't contain +// CHECKLOCKTIMEVERIFY (or CHECKSEQUENCEVERIFY), but the script does contain +// OP_CHECKLOCKTIMEVERIFY (or OP_CHECKSEQUENCEVERIFY), then script execution +// should fail. +// Capture this interaction with the upgraded_nop argument: set it when evaluating +// any script flag that is implemented as an upgraded NOP code. +void ValidateCheckInputsForAllFlags(CMutableTransaction &tx, uint32_t failing_flags, bool add_to_cache, bool upgraded_nop) +{ + PrecomputedTransactionData txdata(tx); + // If we add many more flags, this loop can get too expensive, but we can + // rewrite in the future to randomly pick a set of flags to evaluate. + for (uint32_t test_flags=0; test_flags < (1U << 16); test_flags += 1) { + CValidationState state; + // Filter out incompatible flag choices + if ((test_flags & SCRIPT_VERIFY_CLEANSTACK)) { + // CLEANSTACK requires P2SH and WITNESS, see VerifyScript() in + // script/interpreter.cpp + test_flags |= SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS; + } + if ((test_flags & SCRIPT_VERIFY_WITNESS)) { + // WITNESS requires P2SH + test_flags |= SCRIPT_VERIFY_P2SH; + } + bool ret = CheckInputs(tx, state, pcoinsTip, true, test_flags, true, add_to_cache, txdata, nullptr); + // CheckInputs should succeed iff test_flags doesn't intersect with + // failing_flags + bool expected_return_value = !(test_flags & failing_flags); + if (expected_return_value && upgraded_nop) { + // If the script flag being tested corresponds to an upgraded NOP, + // then script execution should fail if DISCOURAGE_UPGRADABLE_NOPS + // is set. + expected_return_value = !(test_flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS); + } + BOOST_CHECK_EQUAL(ret, expected_return_value); + + // Test the caching + if (ret && add_to_cache) { + // Check that we get a cache hit if the tx was valid + std::vector<CScriptCheck> scriptchecks; + BOOST_CHECK(CheckInputs(tx, state, pcoinsTip, true, test_flags, true, add_to_cache, txdata, &scriptchecks)); + BOOST_CHECK(scriptchecks.empty()); + } else { + // Check that we get script executions to check, if the transaction + // was invalid, or we didn't add to cache. + std::vector<CScriptCheck> scriptchecks; + BOOST_CHECK(CheckInputs(tx, state, pcoinsTip, true, test_flags, true, add_to_cache, txdata, &scriptchecks)); + BOOST_CHECK_EQUAL(scriptchecks.size(), tx.vin.size()); + } + } +} + +BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) +{ + // Test that passing CheckInputs with one set of script flags doesn't imply + // that we would pass again with a different set of flags. + InitScriptExecutionCache(); + + CScript p2pk_scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG; + CScript p2sh_scriptPubKey = GetScriptForDestination(CScriptID(p2pk_scriptPubKey)); + CScript p2pkh_scriptPubKey = GetScriptForDestination(coinbaseKey.GetPubKey().GetID()); + CScript p2wpkh_scriptPubKey = GetScriptForWitness(p2pkh_scriptPubKey); + + CBasicKeyStore keystore; + keystore.AddKey(coinbaseKey); + keystore.AddCScript(p2pk_scriptPubKey); + + // flags to test: SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, SCRIPT_VERIFY_CHECKSEQUENCE_VERIFY, SCRIPT_VERIFY_NULLDUMMY, uncompressed pubkey thing + + // Create 2 outputs that match the three scripts above, spending the first + // coinbase tx. + CMutableTransaction spend_tx; + + spend_tx.nVersion = 1; + spend_tx.vin.resize(1); + spend_tx.vin[0].prevout.hash = coinbaseTxns[0].GetHash(); + spend_tx.vin[0].prevout.n = 0; + spend_tx.vout.resize(4); + spend_tx.vout[0].nValue = 11*CENT; + spend_tx.vout[0].scriptPubKey = p2sh_scriptPubKey; + spend_tx.vout[1].nValue = 11*CENT; + spend_tx.vout[1].scriptPubKey = p2wpkh_scriptPubKey; + spend_tx.vout[2].nValue = 11*CENT; + spend_tx.vout[2].scriptPubKey = CScript() << OP_CHECKLOCKTIMEVERIFY << OP_DROP << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG; + spend_tx.vout[3].nValue = 11*CENT; + spend_tx.vout[3].scriptPubKey = CScript() << OP_CHECKSEQUENCEVERIFY << OP_DROP << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG; + + // Sign, with a non-DER signature + { + std::vector<unsigned char> vchSig; + uint256 hash = SignatureHash(p2pk_scriptPubKey, spend_tx, 0, SIGHASH_ALL, 0, SIGVERSION_BASE); + BOOST_CHECK(coinbaseKey.Sign(hash, vchSig)); + vchSig.push_back((unsigned char) 0); // padding byte makes this non-DER + vchSig.push_back((unsigned char)SIGHASH_ALL); + spend_tx.vin[0].scriptSig << vchSig; + } + + LOCK(cs_main); + + // Test that invalidity under a set of flags doesn't preclude validity + // under other (eg consensus) flags. + // spend_tx is invalid according to DERSIG + { + CValidationState state; + PrecomputedTransactionData ptd_spend_tx(spend_tx); + + BOOST_CHECK(!CheckInputs(spend_tx, state, pcoinsTip, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, nullptr)); + + // If we call again asking for scriptchecks (as happens in + // ConnectBlock), we should add a script check object for this -- we're + // not caching invalidity (if that changes, delete this test case). + std::vector<CScriptCheck> scriptchecks; + BOOST_CHECK(CheckInputs(spend_tx, state, pcoinsTip, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, &scriptchecks)); + BOOST_CHECK_EQUAL(scriptchecks.size(), 1); + + // Test that CheckInputs returns true iff DERSIG-enforcing flags are + // not present. Don't add these checks to the cache, so that we can + // test later that block validation works fine in the absence of cached + // successes. + ValidateCheckInputsForAllFlags(spend_tx, SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC, false, false); + + // And if we produce a block with this tx, it should be valid (DERSIG not + // enabled yet), even though there's no cache entry. + CBlock block; + + block = CreateAndProcessBlock({spend_tx}, p2pk_scriptPubKey); + BOOST_CHECK(chainActive.Tip()->GetBlockHash() == block.GetHash()); + BOOST_CHECK(pcoinsTip->GetBestBlock() == block.GetHash()); + } + + // Test P2SH: construct a transaction that is valid without P2SH, and + // then test validity with P2SH. + { + CMutableTransaction invalid_under_p2sh_tx; + invalid_under_p2sh_tx.nVersion = 1; + invalid_under_p2sh_tx.vin.resize(1); + invalid_under_p2sh_tx.vin[0].prevout.hash = spend_tx.GetHash(); + invalid_under_p2sh_tx.vin[0].prevout.n = 0; + invalid_under_p2sh_tx.vout.resize(1); + invalid_under_p2sh_tx.vout[0].nValue = 11*CENT; + invalid_under_p2sh_tx.vout[0].scriptPubKey = p2pk_scriptPubKey; + std::vector<unsigned char> vchSig2(p2pk_scriptPubKey.begin(), p2pk_scriptPubKey.end()); + invalid_under_p2sh_tx.vin[0].scriptSig << vchSig2; + + ValidateCheckInputsForAllFlags(invalid_under_p2sh_tx, SCRIPT_VERIFY_P2SH, true, false); + } + + // Test CHECKLOCKTIMEVERIFY + { + CMutableTransaction invalid_with_cltv_tx; + invalid_with_cltv_tx.nVersion = 1; + invalid_with_cltv_tx.nLockTime = 100; + invalid_with_cltv_tx.vin.resize(1); + invalid_with_cltv_tx.vin[0].prevout.hash = spend_tx.GetHash(); + invalid_with_cltv_tx.vin[0].prevout.n = 2; + invalid_with_cltv_tx.vin[0].nSequence = 0; + invalid_with_cltv_tx.vout.resize(1); + invalid_with_cltv_tx.vout[0].nValue = 11*CENT; + invalid_with_cltv_tx.vout[0].scriptPubKey = p2pk_scriptPubKey; + + // Sign + std::vector<unsigned char> vchSig; + uint256 hash = SignatureHash(spend_tx.vout[2].scriptPubKey, invalid_with_cltv_tx, 0, SIGHASH_ALL, 0, SIGVERSION_BASE); + BOOST_CHECK(coinbaseKey.Sign(hash, vchSig)); + vchSig.push_back((unsigned char)SIGHASH_ALL); + invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 101; + + ValidateCheckInputsForAllFlags(invalid_with_cltv_tx, SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true); + + // Make it valid, and check again + invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 100; + CValidationState state; + PrecomputedTransactionData txdata(invalid_with_cltv_tx); + BOOST_CHECK(CheckInputs(invalid_with_cltv_tx, state, pcoinsTip, true, SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true, txdata, nullptr)); + } + + // TEST CHECKSEQUENCEVERIFY + { + CMutableTransaction invalid_with_csv_tx; + invalid_with_csv_tx.nVersion = 2; + invalid_with_csv_tx.vin.resize(1); + invalid_with_csv_tx.vin[0].prevout.hash = spend_tx.GetHash(); + invalid_with_csv_tx.vin[0].prevout.n = 3; + invalid_with_csv_tx.vin[0].nSequence = 100; + invalid_with_csv_tx.vout.resize(1); + invalid_with_csv_tx.vout[0].nValue = 11*CENT; + invalid_with_csv_tx.vout[0].scriptPubKey = p2pk_scriptPubKey; + + // Sign + std::vector<unsigned char> vchSig; + uint256 hash = SignatureHash(spend_tx.vout[3].scriptPubKey, invalid_with_csv_tx, 0, SIGHASH_ALL, 0, SIGVERSION_BASE); + BOOST_CHECK(coinbaseKey.Sign(hash, vchSig)); + vchSig.push_back((unsigned char)SIGHASH_ALL); + invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 101; + + ValidateCheckInputsForAllFlags(invalid_with_csv_tx, SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true); + + // Make it valid, and check again + invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 100; + CValidationState state; + PrecomputedTransactionData txdata(invalid_with_csv_tx); + BOOST_CHECK(CheckInputs(invalid_with_csv_tx, state, pcoinsTip, true, SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true, txdata, nullptr)); + } + + // TODO: add tests for remaining script flags + + // Test that passing CheckInputs with a valid witness doesn't imply success + // for the same tx with a different witness. + { + CMutableTransaction valid_with_witness_tx; + valid_with_witness_tx.nVersion = 1; + valid_with_witness_tx.vin.resize(1); + valid_with_witness_tx.vin[0].prevout.hash = spend_tx.GetHash(); + valid_with_witness_tx.vin[0].prevout.n = 1; + valid_with_witness_tx.vout.resize(1); + valid_with_witness_tx.vout[0].nValue = 11*CENT; + valid_with_witness_tx.vout[0].scriptPubKey = p2pk_scriptPubKey; + + // Sign + SignatureData sigdata; + ProduceSignature(MutableTransactionSignatureCreator(&keystore, &valid_with_witness_tx, 0, 11*CENT, SIGHASH_ALL), spend_tx.vout[1].scriptPubKey, sigdata); + UpdateTransaction(valid_with_witness_tx, 0, sigdata); + + // This should be valid under all script flags. + ValidateCheckInputsForAllFlags(valid_with_witness_tx, 0, true, false); + + // Remove the witness, and check that it is now invalid. + valid_with_witness_tx.vin[0].scriptWitness.SetNull(); + ValidateCheckInputsForAllFlags(valid_with_witness_tx, SCRIPT_VERIFY_WITNESS, true, false); + } + + { + // Test a transaction with multiple inputs. + CMutableTransaction tx; + + tx.nVersion = 1; + tx.vin.resize(2); + tx.vin[0].prevout.hash = spend_tx.GetHash(); + tx.vin[0].prevout.n = 0; + tx.vin[1].prevout.hash = spend_tx.GetHash(); + tx.vin[1].prevout.n = 1; + tx.vout.resize(1); + tx.vout[0].nValue = 22*CENT; + tx.vout[0].scriptPubKey = p2pk_scriptPubKey; + + // Sign + for (int i=0; i<2; ++i) { + SignatureData sigdata; + ProduceSignature(MutableTransactionSignatureCreator(&keystore, &tx, i, 11*CENT, SIGHASH_ALL), spend_tx.vout[i].scriptPubKey, sigdata); + UpdateTransaction(tx, i, sigdata); + } + + // This should be valid under all script flags + ValidateCheckInputsForAllFlags(tx, 0, true, false); + + // Check that if the second input is invalid, but the first input is + // valid, the transaction is not cached. + // Invalidate vin[1] + tx.vin[1].scriptWitness.SetNull(); + + CValidationState state; + PrecomputedTransactionData txdata(tx); + // This transaction is now invalid under segwit, because of the second input. + BOOST_CHECK(!CheckInputs(tx, state, pcoinsTip, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, nullptr)); + + std::vector<CScriptCheck> scriptchecks; + // Make sure this transaction was not cached (ie because the first + // input was valid) + BOOST_CHECK(CheckInputs(tx, state, pcoinsTip, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, &scriptchecks)); + // Should get 2 script checks back -- caching is on a whole-transaction basis. + BOOST_CHECK_EQUAL(scriptchecks.size(), 2); + } +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 10330c0c23..5e9dfb730b 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -10,7 +10,6 @@ #include "utilstrencodings.h" #include "utilmoneystr.h" #include "test/test_bitcoin.h" -#include "test/test_random.h" #include <stdint.h> #include <vector> @@ -256,7 +255,7 @@ BOOST_AUTO_TEST_CASE(util_IsHex) BOOST_AUTO_TEST_CASE(util_seed_insecure_rand) { - seed_insecure_rand(true); + SeedInsecureRand(true); for (int mod=2;mod<11;mod++) { int mask = 1; @@ -270,7 +269,7 @@ BOOST_AUTO_TEST_CASE(util_seed_insecure_rand) for (int i = 0; i < 10000; i++) { uint32_t rval; do{ - rval=insecure_rand()&mask; + rval=InsecureRand32()&mask; }while(rval>=(uint32_t)mod); count += rval==0; } diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp index 79405ec4d1..722f6ae059 100644 --- a/src/test/versionbits_tests.cpp +++ b/src/test/versionbits_tests.cpp @@ -5,7 +5,6 @@ #include "chain.h" #include "versionbits.h" #include "test/test_bitcoin.h" -#include "test/test_random.h" #include "chainparams.h" #include "validation.h" #include "consensus/params.h" @@ -23,11 +22,11 @@ private: mutable ThresholdConditionCache cache; public: - int64_t BeginTime(const Consensus::Params& params) const { return TestTime(10000); } - int64_t EndTime(const Consensus::Params& params) const { return TestTime(20000); } - int Period(const Consensus::Params& params) const { return 1000; } - int Threshold(const Consensus::Params& params) const { return 900; } - bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const { return (pindex->nVersion & 0x100); } + int64_t BeginTime(const Consensus::Params& params) const override { return TestTime(10000); } + int64_t EndTime(const Consensus::Params& params) const override { return TestTime(20000); } + int Period(const Consensus::Params& params) const override { return 1000; } + int Threshold(const Consensus::Params& params) const override { return 900; } + bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override { return (pindex->nVersion & 0x100); } ThresholdState GetStateFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateFor(pindexPrev, paramsDummy, cache); } int GetStateSinceHeightFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev, paramsDummy, cache); } @@ -81,7 +80,7 @@ public: VersionBitsTester& TestStateSinceHeight(int height) { for (int i = 0; i < CHECKERS; i++) { - if ((insecure_rand() & ((1 << i) - 1)) == 0) { + if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateSinceHeightFor(vpblock.empty() ? NULL : vpblock.back()) == height, strprintf("Test %i for StateSinceHeight", num)); } } @@ -91,7 +90,7 @@ public: VersionBitsTester& TestDefined() { for (int i = 0; i < CHECKERS; i++) { - if ((insecure_rand() & ((1 << i) - 1)) == 0) { + if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_DEFINED, strprintf("Test %i for DEFINED", num)); } } @@ -101,7 +100,7 @@ public: VersionBitsTester& TestStarted() { for (int i = 0; i < CHECKERS; i++) { - if ((insecure_rand() & ((1 << i) - 1)) == 0) { + if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_STARTED, strprintf("Test %i for STARTED", num)); } } @@ -111,7 +110,7 @@ public: VersionBitsTester& TestLockedIn() { for (int i = 0; i < CHECKERS; i++) { - if ((insecure_rand() & ((1 << i) - 1)) == 0) { + if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_LOCKED_IN, strprintf("Test %i for LOCKED_IN", num)); } } @@ -121,7 +120,7 @@ public: VersionBitsTester& TestActive() { for (int i = 0; i < CHECKERS; i++) { - if ((insecure_rand() & ((1 << i) - 1)) == 0) { + if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_ACTIVE, strprintf("Test %i for ACTIVE", num)); } } @@ -131,7 +130,7 @@ public: VersionBitsTester& TestFailed() { for (int i = 0; i < CHECKERS; i++) { - if ((insecure_rand() & ((1 << i) - 1)) == 0) { + if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_FAILED, strprintf("Test %i for FAILED", num)); } } |