diff options
Diffstat (limited to 'src/test')
89 files changed, 4266 insertions, 1823 deletions
diff --git a/src/test/README.md b/src/test/README.md index 01da32109b..0017e3de26 100644 --- a/src/test/README.md +++ b/src/test/README.md @@ -42,12 +42,12 @@ unit tests as possible). The build system is setup to compile an executable called `test_bitcoin` that runs all of the unit tests. The main source file is called -test_bitcoin.cpp. To add a new unit test file to our test suite you need -to add the file to `src/Makefile.test.include`. The pattern is to create -one test file for each class or source file for which you want to create -unit tests. The file naming convention is `<source_filename>_tests.cpp` -and such files should wrap their tests in a test suite -called `<source_filename>_tests`. For an example of this pattern, +setup_common.cpp. To add a new unit test file to our test suite you need +to add the file to `src/Makefile.test.include`. The pattern is to create +one test file for each class or source file for which you want to create +unit tests. The file naming convention is `<source_filename>_tests.cpp` +and such files should wrap their tests in a test suite +called `<source_filename>_tests`. For an example of this pattern, examine `uint256_tests.cpp`. For further reading, I found the following website to be helpful in diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index ee3650d148..eeb54b4cf0 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -1,8 +1,8 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <addrman.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <string> #include <boost/test/unit_test.hpp> @@ -12,13 +12,9 @@ class CAddrManTest : public CAddrMan { - uint64_t state; - public: explicit CAddrManTest(bool makeDeterministic = true) { - state = 1; - if (makeDeterministic) { // Set addrman addr placement to be deterministic. MakeDeterministic(); @@ -32,30 +28,28 @@ public: insecure_rand = FastRandomContext(true); } - int RandomInt(int nMax) override - { - state = (CHashWriter(SER_GETHASH, 0) << state).GetHash().GetCheapHash(); - return (unsigned int)(state % nMax); - } - CAddrInfo* Find(const CNetAddr& addr, int* pnId = nullptr) { + LOCK(cs); return CAddrMan::Find(addr, pnId); } CAddrInfo* Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId = nullptr) { + LOCK(cs); return CAddrMan::Create(addr, addrSource, pnId); } void Delete(int nId) { + LOCK(cs); CAddrMan::Delete(nId); } // Simulates connection failure so that we can test eviction of offline nodes void SimConnFail(CService& addr) { + LOCK(cs); int64_t nLastSuccess = 1; Good_(addr, true, nLastSuccess); // Set last good connection in the deep past. @@ -150,11 +144,11 @@ BOOST_AUTO_TEST_CASE(addrman_ports) // Test 7; Addr with same IP but diff port does not replace existing addr. CService addr1 = ResolveService("250.1.1.1", 8333); - addrman.Add(CAddress(addr1, NODE_NONE), source); + BOOST_CHECK(addrman.Add(CAddress(addr1, NODE_NONE), source)); BOOST_CHECK_EQUAL(addrman.size(), 1U); CService addr1_port = ResolveService("250.1.1.1", 8334); - addrman.Add(CAddress(addr1_port, NODE_NONE), source); + BOOST_CHECK(!addrman.Add(CAddress(addr1_port, NODE_NONE), source)); BOOST_CHECK_EQUAL(addrman.size(), 1U); CAddrInfo addr_ret2 = addrman.Select(); BOOST_CHECK_EQUAL(addr_ret2.ToString(), "250.1.1.1:8333"); @@ -177,7 +171,7 @@ BOOST_AUTO_TEST_CASE(addrman_select) // Test: Select from new with 1 addr in new. CService addr1 = ResolveService("250.1.1.1", 8333); - addrman.Add(CAddress(addr1, NODE_NONE), source); + BOOST_CHECK(addrman.Add(CAddress(addr1, NODE_NONE), source)); BOOST_CHECK_EQUAL(addrman.size(), 1U); bool newOnly = true; @@ -201,20 +195,20 @@ BOOST_AUTO_TEST_CASE(addrman_select) CService addr3 = ResolveService("250.3.2.2", 9999); CService addr4 = ResolveService("250.3.3.3", 9999); - addrman.Add(CAddress(addr2, NODE_NONE), ResolveService("250.3.1.1", 8333)); - addrman.Add(CAddress(addr3, NODE_NONE), ResolveService("250.3.1.1", 8333)); - addrman.Add(CAddress(addr4, NODE_NONE), ResolveService("250.4.1.1", 8333)); + BOOST_CHECK(addrman.Add(CAddress(addr2, NODE_NONE), ResolveService("250.3.1.1", 8333))); + BOOST_CHECK(addrman.Add(CAddress(addr3, NODE_NONE), ResolveService("250.3.1.1", 8333))); + BOOST_CHECK(addrman.Add(CAddress(addr4, NODE_NONE), ResolveService("250.4.1.1", 8333))); // Add three addresses to tried table. CService addr5 = ResolveService("250.4.4.4", 8333); CService addr6 = ResolveService("250.4.5.5", 7777); CService addr7 = ResolveService("250.4.6.6", 8333); - addrman.Add(CAddress(addr5, NODE_NONE), ResolveService("250.3.1.1", 8333)); + BOOST_CHECK(addrman.Add(CAddress(addr5, NODE_NONE), ResolveService("250.3.1.1", 8333))); addrman.Good(CAddress(addr5, NODE_NONE)); - addrman.Add(CAddress(addr6, NODE_NONE), ResolveService("250.3.1.1", 8333)); + BOOST_CHECK(addrman.Add(CAddress(addr6, NODE_NONE), ResolveService("250.3.1.1", 8333))); addrman.Good(CAddress(addr6, NODE_NONE)); - addrman.Add(CAddress(addr7, NODE_NONE), ResolveService("250.1.1.3", 8333)); + BOOST_CHECK(addrman.Add(CAddress(addr7, NODE_NONE), ResolveService("250.1.1.3", 8333))); addrman.Good(CAddress(addr7, NODE_NONE)); // Test: 6 addrs + 1 addr from last test = 7. @@ -238,7 +232,7 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions) for (unsigned int i = 1; i < 18; i++) { CService addr = ResolveService("250.1.1." + std::to_string(i)); - addrman.Add(CAddress(addr, NODE_NONE), source); + BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source)); //Test: No collision in new table yet. BOOST_CHECK_EQUAL(addrman.size(), i); @@ -246,11 +240,11 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions) //Test: new table collision! CService addr1 = ResolveService("250.1.1.18"); - addrman.Add(CAddress(addr1, NODE_NONE), source); + BOOST_CHECK(addrman.Add(CAddress(addr1, NODE_NONE), source)); BOOST_CHECK_EQUAL(addrman.size(), 17U); CService addr2 = ResolveService("250.1.1.19"); - addrman.Add(CAddress(addr2, NODE_NONE), source); + BOOST_CHECK(addrman.Add(CAddress(addr2, NODE_NONE), source)); BOOST_CHECK_EQUAL(addrman.size(), 18U); } @@ -264,7 +258,7 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions) for (unsigned int i = 1; i < 80; i++) { CService addr = ResolveService("250.1.1." + std::to_string(i)); - addrman.Add(CAddress(addr, NODE_NONE), source); + BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source)); addrman.Good(CAddress(addr, NODE_NONE)); //Test: No collision in tried table yet. @@ -273,11 +267,11 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions) //Test: tried table collision! CService addr1 = ResolveService("250.1.1.80"); - addrman.Add(CAddress(addr1, NODE_NONE), source); + BOOST_CHECK(addrman.Add(CAddress(addr1, NODE_NONE), source)); BOOST_CHECK_EQUAL(addrman.size(), 79U); CService addr2 = ResolveService("250.1.1.81"); - addrman.Add(CAddress(addr2, NODE_NONE), source); + BOOST_CHECK(addrman.Add(CAddress(addr2, NODE_NONE), source)); BOOST_CHECK_EQUAL(addrman.size(), 80U); } @@ -294,9 +288,9 @@ BOOST_AUTO_TEST_CASE(addrman_find) CNetAddr source1 = ResolveIP("250.1.2.1"); CNetAddr source2 = ResolveIP("250.1.2.2"); - addrman.Add(addr1, source1); - addrman.Add(addr2, source2); - addrman.Add(addr3, source1); + BOOST_CHECK(addrman.Add(addr1, source1)); + BOOST_CHECK(!addrman.Add(addr2, source2)); + BOOST_CHECK(addrman.Add(addr3, source1)); // Test: ensure Find returns an IP matching what we searched on. CAddrInfo* info1 = addrman.Find(addr1); @@ -378,11 +372,11 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr) CNetAddr source2 = ResolveIP("250.2.3.3"); // Test: Ensure GetAddr works with new addresses. - addrman.Add(addr1, source1); - addrman.Add(addr2, source2); - addrman.Add(addr3, source1); - addrman.Add(addr4, source2); - addrman.Add(addr5, source1); + BOOST_CHECK(addrman.Add(addr1, source1)); + BOOST_CHECK(addrman.Add(addr2, source2)); + BOOST_CHECK(addrman.Add(addr3, source1)); + BOOST_CHECK(addrman.Add(addr4, source2)); + BOOST_CHECK(addrman.Add(addr5, source1)); // GetAddr returns 23% of addresses, 23% of 5 is 1 rounded down. BOOST_CHECK_EQUAL(addrman.GetAddr().size(), 1U); @@ -551,7 +545,7 @@ BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision) CNetAddr source = ResolveIP("252.2.2.2"); for (unsigned int i = 1; i < 23; i++) { CService addr = ResolveService("250.1.1."+std::to_string(i)); - addrman.Add(CAddress(addr, NODE_NONE), source); + BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source)); addrman.Good(addr); // No collisions yet. @@ -581,7 +575,7 @@ BOOST_AUTO_TEST_CASE(addrman_noevict) CNetAddr source = ResolveIP("252.2.2.2"); for (unsigned int i = 1; i < 23; i++) { CService addr = ResolveService("250.1.1."+std::to_string(i)); - addrman.Add(CAddress(addr, NODE_NONE), source); + BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source)); addrman.Good(addr); // No collision yet. @@ -591,7 +585,7 @@ BOOST_AUTO_TEST_CASE(addrman_noevict) // Collision between 23 and 19. CService addr23 = ResolveService("250.1.1.23"); - addrman.Add(CAddress(addr23, NODE_NONE), source); + BOOST_CHECK(addrman.Add(CAddress(addr23, NODE_NONE), source)); addrman.Good(addr23); BOOST_CHECK(addrman.size() == 23); @@ -604,7 +598,7 @@ BOOST_AUTO_TEST_CASE(addrman_noevict) // Lets create two collisions. for (unsigned int i = 24; i < 33; i++) { CService addr = ResolveService("250.1.1."+std::to_string(i)); - addrman.Add(CAddress(addr, NODE_NONE), source); + BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source)); addrman.Good(addr); BOOST_CHECK(addrman.size() == i); @@ -613,14 +607,14 @@ BOOST_AUTO_TEST_CASE(addrman_noevict) // Cause a collision. CService addr33 = ResolveService("250.1.1.33"); - addrman.Add(CAddress(addr33, NODE_NONE), source); + BOOST_CHECK(addrman.Add(CAddress(addr33, NODE_NONE), source)); addrman.Good(addr33); BOOST_CHECK(addrman.size() == 33); BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "250.1.1.27:0"); // Cause a second collision. - addrman.Add(CAddress(addr23, NODE_NONE), source); + BOOST_CHECK(!addrman.Add(CAddress(addr23, NODE_NONE), source)); addrman.Good(addr23); BOOST_CHECK(addrman.size() == 33); @@ -645,7 +639,7 @@ BOOST_AUTO_TEST_CASE(addrman_evictionworks) CNetAddr source = ResolveIP("252.2.2.2"); for (unsigned int i = 1; i < 23; i++) { CService addr = ResolveService("250.1.1."+std::to_string(i)); - addrman.Add(CAddress(addr, NODE_NONE), source); + BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source)); addrman.Good(addr); // No collision yet. @@ -655,7 +649,7 @@ BOOST_AUTO_TEST_CASE(addrman_evictionworks) // Collision between 23 and 19. CService addr = ResolveService("250.1.1.23"); - addrman.Add(CAddress(addr, NODE_NONE), source); + BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source)); addrman.Good(addr); BOOST_CHECK(addrman.size() == 23); @@ -670,14 +664,14 @@ BOOST_AUTO_TEST_CASE(addrman_evictionworks) BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0"); // If 23 was swapped for 19, then this should cause no collisions. - addrman.Add(CAddress(addr, NODE_NONE), source); + BOOST_CHECK(!addrman.Add(CAddress(addr, NODE_NONE), source)); addrman.Good(addr); BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0"); // If we insert 19 is should collide with 23. CService addr19 = ResolveService("250.1.1.19"); - addrman.Add(CAddress(addr19, NODE_NONE), source); + BOOST_CHECK(!addrman.Add(CAddress(addr19, NODE_NONE), source)); addrman.Good(addr19); BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "250.1.1.23:0"); diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp index 67d1229c70..f255691704 100644 --- a/src/test/allocator_tests.cpp +++ b/src/test/allocator_tests.cpp @@ -1,11 +1,11 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <util.h> +#include <util/system.h> #include <support/allocators/secure.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <memory> @@ -105,13 +105,13 @@ BOOST_AUTO_TEST_CASE(arena_tests) // Go entirely wild: free and alloc interleaved, // generate targets and sizes using pseudo-randomness. for (int x=0; x<2048; ++x) - addr.push_back(0); + addr.push_back(nullptr); uint32_t s = 0x12345678; for (int x=0; x<5000; ++x) { int idx = s & (addr.size()-1); if (s & 0x80000000) { b.free(addr[idx]); - addr[idx] = 0; + addr[idx] = nullptr; } else if(!addr[idx]) { addr[idx] = b.alloc((s >> 16) & 2047); } @@ -144,9 +144,9 @@ public: *lockingSuccess = true; } - return reinterpret_cast<void*>(0x08000000 + (count<<24)); // Fake address, do not actually use this memory + return reinterpret_cast<void*>(uint64_t{static_cast<uint64_t>(0x08000000) + (count << 24)}); // Fake address, do not actually use this memory } - return 0; + return nullptr; } void FreeLocked(void* addr, size_t len) override { @@ -163,7 +163,7 @@ private: BOOST_AUTO_TEST_CASE(lockedpool_tests_mock) { // Test over three virtual arenas, of which one will succeed being locked - std::unique_ptr<LockedPageAllocator> x(new TestLockedPageAllocator(3, 1)); + std::unique_ptr<LockedPageAllocator> x = MakeUnique<TestLockedPageAllocator>(3, 1); LockedPool pool(std::move(x)); BOOST_CHECK(pool.stats().total == 0); BOOST_CHECK(pool.stats().locked == 0); diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp index 854146102e..378fe285d5 100644 --- a/src/test/amount_tests.cpp +++ b/src/test/amount_tests.cpp @@ -1,10 +1,10 @@ -// Copyright (c) 2016-2017 The Bitcoin Core developers +// Copyright (c) 2016-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <amount.h> #include <policy/feerate.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> @@ -13,8 +13,10 @@ BOOST_FIXTURE_TEST_SUITE(amount_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(MoneyRangeTest) { BOOST_CHECK_EQUAL(MoneyRange(CAmount(-1)), false); - BOOST_CHECK_EQUAL(MoneyRange(MAX_MONEY + CAmount(1)), false); + BOOST_CHECK_EQUAL(MoneyRange(CAmount(0)), true); BOOST_CHECK_EQUAL(MoneyRange(CAmount(1)), true); + BOOST_CHECK_EQUAL(MoneyRange(MAX_MONEY), true); + BOOST_CHECK_EQUAL(MoneyRange(MAX_MONEY + CAmount(1)), false); } BOOST_AUTO_TEST_CASE(GetFeeTest) @@ -23,43 +25,43 @@ BOOST_AUTO_TEST_CASE(GetFeeTest) feeRate = CFeeRate(0); // Must always return 0 - BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0); - BOOST_CHECK_EQUAL(feeRate.GetFee(1e5), 0); + BOOST_CHECK_EQUAL(feeRate.GetFee(0), CAmount(0)); + BOOST_CHECK_EQUAL(feeRate.GetFee(1e5), CAmount(0)); feeRate = CFeeRate(1000); // Must always just return the arg - BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0); - BOOST_CHECK_EQUAL(feeRate.GetFee(1), 1); - BOOST_CHECK_EQUAL(feeRate.GetFee(121), 121); - BOOST_CHECK_EQUAL(feeRate.GetFee(999), 999); - BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), 1e3); - BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), 9e3); + BOOST_CHECK_EQUAL(feeRate.GetFee(0), CAmount(0)); + BOOST_CHECK_EQUAL(feeRate.GetFee(1), CAmount(1)); + BOOST_CHECK_EQUAL(feeRate.GetFee(121), CAmount(121)); + BOOST_CHECK_EQUAL(feeRate.GetFee(999), CAmount(999)); + BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), CAmount(1e3)); + BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), CAmount(9e3)); feeRate = CFeeRate(-1000); // Must always just return -1 * arg - BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0); - BOOST_CHECK_EQUAL(feeRate.GetFee(1), -1); - BOOST_CHECK_EQUAL(feeRate.GetFee(121), -121); - BOOST_CHECK_EQUAL(feeRate.GetFee(999), -999); - BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), -1e3); - BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), -9e3); + BOOST_CHECK_EQUAL(feeRate.GetFee(0), CAmount(0)); + BOOST_CHECK_EQUAL(feeRate.GetFee(1), CAmount(-1)); + BOOST_CHECK_EQUAL(feeRate.GetFee(121), CAmount(-121)); + BOOST_CHECK_EQUAL(feeRate.GetFee(999), CAmount(-999)); + BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), CAmount(-1e3)); + BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), CAmount(-9e3)); feeRate = CFeeRate(123); // Truncates the result, if not integer - BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0); - BOOST_CHECK_EQUAL(feeRate.GetFee(8), 1); // Special case: returns 1 instead of 0 - BOOST_CHECK_EQUAL(feeRate.GetFee(9), 1); - BOOST_CHECK_EQUAL(feeRate.GetFee(121), 14); - BOOST_CHECK_EQUAL(feeRate.GetFee(122), 15); - BOOST_CHECK_EQUAL(feeRate.GetFee(999), 122); - BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), 123); - BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), 1107); + BOOST_CHECK_EQUAL(feeRate.GetFee(0), CAmount(0)); + BOOST_CHECK_EQUAL(feeRate.GetFee(8), CAmount(1)); // Special case: returns 1 instead of 0 + BOOST_CHECK_EQUAL(feeRate.GetFee(9), CAmount(1)); + BOOST_CHECK_EQUAL(feeRate.GetFee(121), CAmount(14)); + BOOST_CHECK_EQUAL(feeRate.GetFee(122), CAmount(15)); + BOOST_CHECK_EQUAL(feeRate.GetFee(999), CAmount(122)); + BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), CAmount(123)); + BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), CAmount(1107)); feeRate = CFeeRate(-123); // Truncates the result, if not integer - BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0); - BOOST_CHECK_EQUAL(feeRate.GetFee(8), -1); // Special case: returns -1 instead of 0 - BOOST_CHECK_EQUAL(feeRate.GetFee(9), -1); + BOOST_CHECK_EQUAL(feeRate.GetFee(0), CAmount(0)); + BOOST_CHECK_EQUAL(feeRate.GetFee(8), CAmount(-1)); // Special case: returns -1 instead of 0 + BOOST_CHECK_EQUAL(feeRate.GetFee(9), CAmount(-1)); // check alternate constructor feeRate = CFeeRate(1000); @@ -67,6 +69,9 @@ BOOST_AUTO_TEST_CASE(GetFeeTest) BOOST_CHECK_EQUAL(feeRate.GetFee(100), altFeeRate.GetFee(100)); // Check full constructor + BOOST_CHECK(CFeeRate(CAmount(-1), 0) == CFeeRate(0)); + BOOST_CHECK(CFeeRate(CAmount(0), 0) == CFeeRate(0)); + BOOST_CHECK(CFeeRate(CAmount(1), 0) == CFeeRate(0)); // default value BOOST_CHECK(CFeeRate(CAmount(-1), 1000) == CFeeRate(-1)); BOOST_CHECK(CFeeRate(CAmount(0), 1000) == CFeeRate(0)); diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp index 8644aea371..809c627d27 100644 --- a/src/test/arith_uint256_tests.cpp +++ b/src/test/arith_uint256_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2017 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -12,7 +12,7 @@ #include <arith_uint256.h> #include <string> #include <version.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> BOOST_FIXTURE_TEST_SUITE(arith_uint256_tests, BasicTestingSetup) diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp index 1210c7a7ee..b3bed2434c 100644 --- a/src/test/base32_tests.cpp +++ b/src/test/base32_tests.cpp @@ -1,9 +1,9 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <utilstrencodings.h> -#include <test/test_bitcoin.h> +#include <util/strencodings.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index f90d4f90cb..cb376cddb6 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -1,12 +1,12 @@ -// Copyright (c) 2011-2017 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <test/data/base58_encode_decode.json.h> #include <base58.h> -#include <test/test_bitcoin.h> -#include <utilstrencodings.h> +#include <test/setup_common.h> +#include <util/strencodings.h> #include <univalue.h> diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp index f785cede81..9ffffb0b7d 100644 --- a/src/test/base64_tests.cpp +++ b/src/test/base64_tests.cpp @@ -1,9 +1,9 @@ -// Copyright (c) 2011-2017 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <utilstrencodings.h> -#include <test/test_bitcoin.h> +#include <util/strencodings.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/bech32_tests.cpp b/src/test/bech32_tests.cpp index 6ecc9ac705..0ba492c24e 100644 --- a/src/test/bech32_tests.cpp +++ b/src/test/bech32_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <bech32.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp index 2c625c089c..0c0423c0db 100644 --- a/src/test/bip32_tests.cpp +++ b/src/test/bip32_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2013-2017 The Bitcoin Core developers +// Copyright (c) 2013-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -7,9 +7,9 @@ #include <key.h> #include <key_io.h> #include <uint256.h> -#include <util.h> -#include <utilstrencodings.h> -#include <test/test_bitcoin.h> +#include <util/system.h> +#include <util/strencodings.h> +#include <test/setup_common.h> #include <string> #include <vector> diff --git a/src/test/blockchain_tests.cpp b/src/test/blockchain_tests.cpp index 7d8ae46fb8..13afcca375 100644 --- a/src/test/blockchain_tests.cpp +++ b/src/test/blockchain_tests.cpp @@ -3,7 +3,7 @@ #include <stdlib.h> #include <rpc/blockchain.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> /* Equality between doubles is imprecise. Comparison should be done * with a small threshold of tolerance, rather than exact equality. @@ -68,11 +68,4 @@ BOOST_AUTO_TEST_CASE(get_difficulty_for_very_high_target) TestDifficulty(0x12345678, 5913134931067755359633408.0); } -// Verify that difficulty is 1.0 for an empty chain. -BOOST_AUTO_TEST_CASE(get_difficulty_for_null_tip) -{ - double difficulty = GetDifficulty(nullptr); - RejectDifficultyMismatch(difficulty, 1.0); -} - BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp index 3dd5356164..f57e1a0ebd 100644 --- a/src/test/blockencodings_tests.cpp +++ b/src/test/blockencodings_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2017 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -8,7 +8,7 @@ #include <pow.h> #include <random.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> @@ -62,8 +62,8 @@ BOOST_AUTO_TEST_CASE(SimpleRoundTripTest) TestMemPoolEntryHelper entry; CBlock block(BuildBlockTestCase()); - pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(block.vtx[2])); - LOCK(pool.cs); + LOCK2(cs_main, pool.cs); + pool.addUnchecked(entry.FromTx(block.vtx[2])); BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0); // Do a simple ShortTxIDs RT @@ -162,8 +162,8 @@ BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest) TestMemPoolEntryHelper entry; CBlock block(BuildBlockTestCase()); - pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(block.vtx[2])); - LOCK(pool.cs); + LOCK2(cs_main, pool.cs); + pool.addUnchecked(entry.FromTx(block.vtx[2])); BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0); uint256 txhash; @@ -232,8 +232,8 @@ BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest) TestMemPoolEntryHelper entry; CBlock block(BuildBlockTestCase()); - pool.addUnchecked(block.vtx[1]->GetHash(), entry.FromTx(block.vtx[1])); - LOCK(pool.cs); + LOCK2(cs_main, pool.cs); + pool.addUnchecked(entry.FromTx(block.vtx[1])); BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0); uint256 txhash; @@ -344,4 +344,50 @@ BOOST_AUTO_TEST_CASE(TransactionsRequestSerializationTest) { BOOST_CHECK_EQUAL(req1.indexes[3], req2.indexes[3]); } +BOOST_AUTO_TEST_CASE(TransactionsRequestDeserializationMaxTest) { + // Check that the highest legal index is decoded correctly + BlockTransactionsRequest req0; + req0.blockhash = InsecureRand256(); + req0.indexes.resize(1); + req0.indexes[0] = 0xffff; + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << req0; + + BlockTransactionsRequest req1; + stream >> req1; + BOOST_CHECK_EQUAL(req0.indexes.size(), req1.indexes.size()); + BOOST_CHECK_EQUAL(req0.indexes[0], req1.indexes[0]); +} + +BOOST_AUTO_TEST_CASE(TransactionsRequestDeserializationOverflowTest) { + // Any set of index deltas that starts with N values that sum to (0x10000 - N) + // causes the edge-case overflow that was originally not checked for. Such + // a request cannot be created by serializing a real BlockTransactionsRequest + // due to the overflow, so here we'll serialize from raw deltas. + BlockTransactionsRequest req0; + req0.blockhash = InsecureRand256(); + req0.indexes.resize(3); + req0.indexes[0] = 0x7000; + req0.indexes[1] = 0x10000 - 0x7000 - 2; + req0.indexes[2] = 0; + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << req0.blockhash; + WriteCompactSize(stream, req0.indexes.size()); + WriteCompactSize(stream, req0.indexes[0]); + WriteCompactSize(stream, req0.indexes[1]); + WriteCompactSize(stream, req0.indexes[2]); + + BlockTransactionsRequest req1; + try { + stream >> req1; + // before patch: deserialize above succeeds and this check fails, demonstrating the overflow + BOOST_CHECK(req1.indexes[1] < req1.indexes[2]); + // this shouldn't be reachable before or after patch + BOOST_CHECK(0); + } catch(std::ios_base::failure &) { + // deserialize should fail + BOOST_CHECK(true); // Needed to suppress "Test case [...] did not check any assertions" + } +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp new file mode 100644 index 0000000000..7ba483173c --- /dev/null +++ b/src/test/blockfilter_index_tests.cpp @@ -0,0 +1,307 @@ +// Copyright (c) 2017-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <blockfilter.h> +#include <chainparams.h> +#include <consensus/validation.h> +#include <index/blockfilterindex.h> +#include <miner.h> +#include <pow.h> +#include <test/setup_common.h> +#include <script/standard.h> +#include <validation.h> + +#include <boost/test/unit_test.hpp> + +BOOST_AUTO_TEST_SUITE(blockfilter_index_tests) + +static bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex* block_index, + BlockFilter& filter) +{ + CBlock block; + if (!ReadBlockFromDisk(block, block_index->GetBlockPos(), Params().GetConsensus())) { + return false; + } + + CBlockUndo block_undo; + if (block_index->nHeight > 0 && !UndoReadFromDisk(block_undo, block_index)) { + return false; + } + + filter = BlockFilter(filter_type, block, block_undo); + return true; +} + +static bool CheckFilterLookups(BlockFilterIndex& filter_index, const CBlockIndex* block_index, + uint256& last_header) +{ + BlockFilter expected_filter; + if (!ComputeFilter(filter_index.GetFilterType(), block_index, expected_filter)) { + BOOST_ERROR("ComputeFilter failed on block " << block_index->nHeight); + return false; + } + + BlockFilter filter; + uint256 filter_header; + std::vector<BlockFilter> filters; + std::vector<uint256> filter_hashes; + + BOOST_CHECK(filter_index.LookupFilter(block_index, filter)); + BOOST_CHECK(filter_index.LookupFilterHeader(block_index, filter_header)); + BOOST_CHECK(filter_index.LookupFilterRange(block_index->nHeight, block_index, filters)); + BOOST_CHECK(filter_index.LookupFilterHashRange(block_index->nHeight, block_index, + filter_hashes)); + + BOOST_CHECK_EQUAL(filters.size(), 1); + BOOST_CHECK_EQUAL(filter_hashes.size(), 1); + + BOOST_CHECK_EQUAL(filter.GetHash(), expected_filter.GetHash()); + BOOST_CHECK_EQUAL(filter_header, expected_filter.ComputeHeader(last_header)); + BOOST_CHECK_EQUAL(filters[0].GetHash(), expected_filter.GetHash()); + BOOST_CHECK_EQUAL(filter_hashes[0], expected_filter.GetHash()); + + filters.clear(); + filter_hashes.clear(); + last_header = filter_header; + return true; +} + +static CBlock CreateBlock(const CBlockIndex* prev, + const std::vector<CMutableTransaction>& txns, + const CScript& scriptPubKey) +{ + const CChainParams& chainparams = Params(); + std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey); + CBlock& block = pblocktemplate->block; + block.hashPrevBlock = prev->GetBlockHash(); + block.nTime = prev->nTime + 1; + + // Replace mempool-selected txns with just coinbase plus passed-in txns: + block.vtx.resize(1); + for (const CMutableTransaction& tx : txns) { + block.vtx.push_back(MakeTransactionRef(tx)); + } + // IncrementExtraNonce creates a valid coinbase and merkleRoot + unsigned int extraNonce = 0; + IncrementExtraNonce(&block, prev, extraNonce); + + while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce; + + return block; +} + +static bool BuildChain(const CBlockIndex* pindex, const CScript& coinbase_script_pub_key, + size_t length, std::vector<std::shared_ptr<CBlock>>& chain) +{ + std::vector<CMutableTransaction> no_txns; + + chain.resize(length); + for (auto& block : chain) { + block = std::make_shared<CBlock>(CreateBlock(pindex, no_txns, coinbase_script_pub_key)); + CBlockHeader header = block->GetBlockHeader(); + + CValidationState state; + if (!ProcessNewBlockHeaders({header}, state, Params(), &pindex, nullptr)) { + return false; + } + } + + return true; +} + +BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, TestChain100Setup) +{ + BlockFilterIndex filter_index(BlockFilterType::BASIC, 1 << 20, true); + + uint256 last_header; + + // Filter should not be found in the index before it is started. + { + LOCK(cs_main); + + BlockFilter filter; + uint256 filter_header; + std::vector<BlockFilter> filters; + std::vector<uint256> filter_hashes; + + for (const CBlockIndex* block_index = ::ChainActive().Genesis(); + block_index != nullptr; + block_index = ::ChainActive().Next(block_index)) { + BOOST_CHECK(!filter_index.LookupFilter(block_index, filter)); + BOOST_CHECK(!filter_index.LookupFilterHeader(block_index, filter_header)); + BOOST_CHECK(!filter_index.LookupFilterRange(block_index->nHeight, block_index, filters)); + BOOST_CHECK(!filter_index.LookupFilterHashRange(block_index->nHeight, block_index, + filter_hashes)); + } + } + + // BlockUntilSyncedToCurrentChain should return false before index is started. + BOOST_CHECK(!filter_index.BlockUntilSyncedToCurrentChain()); + + filter_index.Start(); + + // Allow filter index to catch up with the block index. + constexpr int64_t timeout_ms = 10 * 1000; + int64_t time_start = GetTimeMillis(); + while (!filter_index.BlockUntilSyncedToCurrentChain()) { + BOOST_REQUIRE(time_start + timeout_ms > GetTimeMillis()); + MilliSleep(100); + } + + // Check that filter index has all blocks that were in the chain before it started. + { + LOCK(cs_main); + const CBlockIndex* block_index; + for (block_index = ::ChainActive().Genesis(); + block_index != nullptr; + block_index = ::ChainActive().Next(block_index)) { + CheckFilterLookups(filter_index, block_index, last_header); + } + } + + // Create two forks. + const CBlockIndex* tip; + { + LOCK(cs_main); + tip = ::ChainActive().Tip(); + } + CScript coinbase_script_pub_key = GetScriptForDestination(PKHash(coinbaseKey.GetPubKey())); + std::vector<std::shared_ptr<CBlock>> chainA, chainB; + BOOST_REQUIRE(BuildChain(tip, coinbase_script_pub_key, 10, chainA)); + BOOST_REQUIRE(BuildChain(tip, coinbase_script_pub_key, 10, chainB)); + + // Check that new blocks on chain A get indexed. + uint256 chainA_last_header = last_header; + for (size_t i = 0; i < 2; i++) { + const auto& block = chainA[i]; + BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr)); + + const CBlockIndex* block_index; + { + LOCK(cs_main); + block_index = LookupBlockIndex(block->GetHash()); + } + + BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain()); + CheckFilterLookups(filter_index, block_index, chainA_last_header); + } + + // Reorg to chain B. + uint256 chainB_last_header = last_header; + for (size_t i = 0; i < 3; i++) { + const auto& block = chainB[i]; + BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr)); + + const CBlockIndex* block_index; + { + LOCK(cs_main); + block_index = LookupBlockIndex(block->GetHash()); + } + + BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain()); + CheckFilterLookups(filter_index, block_index, chainB_last_header); + } + + // Check that filters for stale blocks on A can be retrieved. + chainA_last_header = last_header; + for (size_t i = 0; i < 2; i++) { + const auto& block = chainA[i]; + const CBlockIndex* block_index; + { + LOCK(cs_main); + block_index = LookupBlockIndex(block->GetHash()); + } + + BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain()); + CheckFilterLookups(filter_index, block_index, chainA_last_header); + } + + // Reorg back to chain A. + for (size_t i = 2; i < 4; i++) { + const auto& block = chainA[i]; + BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr)); + } + + // Check that chain A and B blocks can be retrieved. + chainA_last_header = last_header; + chainB_last_header = last_header; + for (size_t i = 0; i < 3; i++) { + const CBlockIndex* block_index; + + { + LOCK(cs_main); + block_index = LookupBlockIndex(chainA[i]->GetHash()); + } + BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain()); + CheckFilterLookups(filter_index, block_index, chainA_last_header); + + { + LOCK(cs_main); + block_index = LookupBlockIndex(chainB[i]->GetHash()); + } + BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain()); + CheckFilterLookups(filter_index, block_index, chainB_last_header); + } + + // Test lookups for a range of filters/hashes. + std::vector<BlockFilter> filters; + std::vector<uint256> filter_hashes; + + { + LOCK(cs_main); + tip = ::ChainActive().Tip(); + } + BOOST_CHECK(filter_index.LookupFilterRange(0, tip, filters)); + BOOST_CHECK(filter_index.LookupFilterHashRange(0, tip, filter_hashes)); + + BOOST_CHECK_EQUAL(filters.size(), tip->nHeight + 1); + BOOST_CHECK_EQUAL(filter_hashes.size(), tip->nHeight + 1); + + filters.clear(); + filter_hashes.clear(); + + filter_index.Interrupt(); + filter_index.Stop(); +} + +BOOST_FIXTURE_TEST_CASE(blockfilter_index_init_destroy, BasicTestingSetup) +{ + SetDataDir("tempdir"); + + BlockFilterIndex* filter_index; + + filter_index = GetBlockFilterIndex(BlockFilterType::BASIC); + BOOST_CHECK(filter_index == nullptr); + + BOOST_CHECK(InitBlockFilterIndex(BlockFilterType::BASIC, 1 << 20, true, false)); + + filter_index = GetBlockFilterIndex(BlockFilterType::BASIC); + BOOST_CHECK(filter_index != nullptr); + BOOST_CHECK(filter_index->GetFilterType() == BlockFilterType::BASIC); + + // Initialize returns false if index already exists. + BOOST_CHECK(!InitBlockFilterIndex(BlockFilterType::BASIC, 1 << 20, true, false)); + + int iter_count = 0; + ForEachBlockFilterIndex([&iter_count](BlockFilterIndex& _index) { iter_count++; }); + BOOST_CHECK_EQUAL(iter_count, 1); + + BOOST_CHECK(DestroyBlockFilterIndex(BlockFilterType::BASIC)); + + // Destroy returns false because index was already destroyed. + BOOST_CHECK(!DestroyBlockFilterIndex(BlockFilterType::BASIC)); + + filter_index = GetBlockFilterIndex(BlockFilterType::BASIC); + BOOST_CHECK(filter_index == nullptr); + + // Reinitialize index. + BOOST_CHECK(InitBlockFilterIndex(BlockFilterType::BASIC, 1 << 20, true, false)); + + DestroyAllBlockFilterIndexes(); + + filter_index = GetBlockFilterIndex(BlockFilterType::BASIC); + BOOST_CHECK(filter_index == nullptr); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/blockfilter_tests.cpp b/src/test/blockfilter_tests.cpp new file mode 100644 index 0000000000..df0a041e0e --- /dev/null +++ b/src/test/blockfilter_tests.cpp @@ -0,0 +1,194 @@ +// Copyright (c) 2018-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <test/data/blockfilters.json.h> +#include <test/setup_common.h> + +#include <blockfilter.h> +#include <core_io.h> +#include <serialize.h> +#include <streams.h> +#include <univalue.h> +#include <util/strencodings.h> + +#include <boost/test/unit_test.hpp> + +BOOST_AUTO_TEST_SUITE(blockfilter_tests) + +BOOST_AUTO_TEST_CASE(gcsfilter_test) +{ + GCSFilter::ElementSet included_elements, excluded_elements; + for (int i = 0; i < 100; ++i) { + GCSFilter::Element element1(32); + element1[0] = i; + included_elements.insert(std::move(element1)); + + GCSFilter::Element element2(32); + element2[1] = i; + excluded_elements.insert(std::move(element2)); + } + + GCSFilter filter({0, 0, 10, 1 << 10}, included_elements); + for (const auto& element : included_elements) { + BOOST_CHECK(filter.Match(element)); + + auto insertion = excluded_elements.insert(element); + BOOST_CHECK(filter.MatchAny(excluded_elements)); + excluded_elements.erase(insertion.first); + } +} + +BOOST_AUTO_TEST_CASE(gcsfilter_default_constructor) +{ + GCSFilter filter; + BOOST_CHECK_EQUAL(filter.GetN(), 0); + BOOST_CHECK_EQUAL(filter.GetEncoded().size(), 1); + + const GCSFilter::Params& params = filter.GetParams(); + BOOST_CHECK_EQUAL(params.m_siphash_k0, 0); + BOOST_CHECK_EQUAL(params.m_siphash_k1, 0); + BOOST_CHECK_EQUAL(params.m_P, 0); + BOOST_CHECK_EQUAL(params.m_M, 1); +} + +BOOST_AUTO_TEST_CASE(blockfilter_basic_test) +{ + CScript included_scripts[5], excluded_scripts[4]; + + // First two are outputs on a single transaction. + included_scripts[0] << std::vector<unsigned char>(0, 65) << OP_CHECKSIG; + included_scripts[1] << OP_DUP << OP_HASH160 << std::vector<unsigned char>(1, 20) << OP_EQUALVERIFY << OP_CHECKSIG; + + // Third is an output on in a second transaction. + included_scripts[2] << OP_1 << std::vector<unsigned char>(2, 33) << OP_1 << OP_CHECKMULTISIG; + + // Last two are spent by a single transaction. + included_scripts[3] << OP_0 << std::vector<unsigned char>(3, 32); + included_scripts[4] << OP_4 << OP_ADD << OP_8 << OP_EQUAL; + + // OP_RETURN output is an output on the second transaction. + excluded_scripts[0] << OP_RETURN << std::vector<unsigned char>(4, 40); + + // This script is not related to the block at all. + excluded_scripts[1] << std::vector<unsigned char>(5, 33) << OP_CHECKSIG; + + // OP_RETURN is non-standard since it's not followed by a data push, but is still excluded from + // filter. + excluded_scripts[2] << OP_RETURN << OP_4 << OP_ADD << OP_8 << OP_EQUAL; + + CMutableTransaction tx_1; + tx_1.vout.emplace_back(100, included_scripts[0]); + tx_1.vout.emplace_back(200, included_scripts[1]); + tx_1.vout.emplace_back(0, excluded_scripts[0]); + + CMutableTransaction tx_2; + tx_2.vout.emplace_back(300, included_scripts[2]); + tx_2.vout.emplace_back(0, excluded_scripts[2]); + tx_2.vout.emplace_back(400, excluded_scripts[3]); // Script is empty + + CBlock block; + block.vtx.push_back(MakeTransactionRef(tx_1)); + block.vtx.push_back(MakeTransactionRef(tx_2)); + + CBlockUndo block_undo; + block_undo.vtxundo.emplace_back(); + block_undo.vtxundo.back().vprevout.emplace_back(CTxOut(500, included_scripts[3]), 1000, true); + block_undo.vtxundo.back().vprevout.emplace_back(CTxOut(600, included_scripts[4]), 10000, false); + block_undo.vtxundo.back().vprevout.emplace_back(CTxOut(700, excluded_scripts[3]), 100000, false); + + BlockFilter block_filter(BlockFilterType::BASIC, block, block_undo); + const GCSFilter& filter = block_filter.GetFilter(); + + for (const CScript& script : included_scripts) { + BOOST_CHECK(filter.Match(GCSFilter::Element(script.begin(), script.end()))); + } + for (const CScript& script : excluded_scripts) { + BOOST_CHECK(!filter.Match(GCSFilter::Element(script.begin(), script.end()))); + } + + // Test serialization/unserialization. + BlockFilter block_filter2; + + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << block_filter; + stream >> block_filter2; + + BOOST_CHECK_EQUAL(block_filter.GetFilterType(), block_filter2.GetFilterType()); + BOOST_CHECK_EQUAL(block_filter.GetBlockHash(), block_filter2.GetBlockHash()); + BOOST_CHECK(block_filter.GetEncodedFilter() == block_filter2.GetEncodedFilter()); + + BlockFilter default_ctor_block_filter_1; + BlockFilter default_ctor_block_filter_2; + BOOST_CHECK_EQUAL(default_ctor_block_filter_1.GetFilterType(), default_ctor_block_filter_2.GetFilterType()); + BOOST_CHECK_EQUAL(default_ctor_block_filter_1.GetBlockHash(), default_ctor_block_filter_2.GetBlockHash()); + BOOST_CHECK(default_ctor_block_filter_1.GetEncodedFilter() == default_ctor_block_filter_2.GetEncodedFilter()); +} + +BOOST_AUTO_TEST_CASE(blockfilters_json_test) +{ + UniValue json; + std::string json_data(json_tests::blockfilters, + json_tests::blockfilters + sizeof(json_tests::blockfilters)); + if (!json.read(json_data) || !json.isArray()) { + BOOST_ERROR("Parse error."); + return; + } + + const UniValue& tests = json.get_array(); + for (unsigned int i = 0; i < tests.size(); i++) { + UniValue test = tests[i]; + std::string strTest = test.write(); + + if (test.size() == 1) { + continue; + } else if (test.size() < 7) { + BOOST_ERROR("Bad test: " << strTest); + continue; + } + + unsigned int pos = 0; + /*int block_height =*/ test[pos++].get_int(); + uint256 block_hash; + BOOST_CHECK(ParseHashStr(test[pos++].get_str(), block_hash)); + + CBlock block; + BOOST_REQUIRE(DecodeHexBlk(block, test[pos++].get_str())); + + CBlockUndo block_undo; + block_undo.vtxundo.emplace_back(); + CTxUndo& tx_undo = block_undo.vtxundo.back(); + const UniValue& prev_scripts = test[pos++].get_array(); + for (unsigned int ii = 0; ii < prev_scripts.size(); ii++) { + std::vector<unsigned char> raw_script = ParseHex(prev_scripts[ii].get_str()); + CTxOut txout(0, CScript(raw_script.begin(), raw_script.end())); + tx_undo.vprevout.emplace_back(txout, 0, false); + } + + uint256 prev_filter_header_basic; + BOOST_CHECK(ParseHashStr(test[pos++].get_str(), prev_filter_header_basic)); + std::vector<unsigned char> filter_basic = ParseHex(test[pos++].get_str()); + uint256 filter_header_basic; + BOOST_CHECK(ParseHashStr(test[pos++].get_str(), filter_header_basic)); + + BlockFilter computed_filter_basic(BlockFilterType::BASIC, block, block_undo); + BOOST_CHECK(computed_filter_basic.GetFilter().GetEncoded() == filter_basic); + + uint256 computed_header_basic = computed_filter_basic.ComputeHeader(prev_filter_header_basic); + BOOST_CHECK(computed_header_basic == filter_header_basic); + } +} + +BOOST_AUTO_TEST_CASE(blockfilter_type_names) +{ + BOOST_CHECK_EQUAL(BlockFilterTypeName(BlockFilterType::BASIC), "basic"); + BOOST_CHECK_EQUAL(BlockFilterTypeName(static_cast<BlockFilterType>(255)), ""); + + BlockFilterType filter_type; + BOOST_CHECK(BlockFilterTypeByName("basic", filter_type)); + BOOST_CHECK_EQUAL(filter_type, BlockFilterType::BASIC); + + BOOST_CHECK(!BlockFilterTypeByName("unknown", filter_type)); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index 17f3004ef3..4421494007 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -13,9 +13,9 @@ #include <serialize.h> #include <streams.h> #include <uint256.h> -#include <util.h> -#include <utilstrencodings.h> -#include <test/test_bitcoin.h> +#include <util/system.h> +#include <util/strencodings.h> +#include <test/setup_common.h> #include <vector> @@ -461,6 +461,9 @@ static std::vector<unsigned char> RandomData() BOOST_AUTO_TEST_CASE(rolling_bloom) { + SeedInsecureRand(/* deterministic */ true); + g_mock_deterministic_tests = true; + // last-100-entry, 1% false positive: CRollingBloomFilter rb1(100, 0.01); @@ -485,12 +488,8 @@ BOOST_AUTO_TEST_CASE(rolling_bloom) if (rb1.contains(RandomData())) ++nHits; } - // Run test_bitcoin with --log_level=message to see BOOST_TEST_MESSAGEs: - BOOST_TEST_MESSAGE("RollingBloomFilter got " << nHits << " false positives (~100 expected)"); - - // Insanely unlikely to get a fp count outside this range: - BOOST_CHECK(nHits > 25); - BOOST_CHECK(nHits < 175); + // Expect about 100 hits + BOOST_CHECK_EQUAL(nHits, 75); BOOST_CHECK(rb1.contains(data[DATASIZE-1])); rb1.reset(); @@ -517,10 +516,8 @@ BOOST_AUTO_TEST_CASE(rolling_bloom) if (rb1.contains(data[i])) ++nHits; } - // Expect about 5 false positives, more than 100 means - // something is definitely broken. - BOOST_TEST_MESSAGE("RollingBloomFilter got " << nHits << " false positives (~5 expected)"); - BOOST_CHECK(nHits < 100); + // Expect about 5 false positives + BOOST_CHECK_EQUAL(nHits, 6); // last-1000-entry, 0.01% false positive: CRollingBloomFilter rb2(1000, 0.001); @@ -531,6 +528,7 @@ BOOST_AUTO_TEST_CASE(rolling_bloom) for (int i = 0; i < DATASIZE; i++) { BOOST_CHECK(rb2.contains(data[i])); } + g_mock_deterministic_tests = false; } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/bswap_tests.cpp b/src/test/bswap_tests.cpp index f22f513e87..8fd4e5d5d6 100644 --- a/src/test/bswap_tests.cpp +++ b/src/test/bswap_tests.cpp @@ -1,9 +1,9 @@ -// Copyright (c) 2016-2017 The Bitcoin Core developers +// Copyright (c) 2016-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <compat/byteswap.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp index c8de7f4a7c..408a7fbda4 100644 --- a/src/test/checkqueue_tests.cpp +++ b/src/test/checkqueue_tests.cpp @@ -1,12 +1,12 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <util.h> -#include <utiltime.h> +#include <util/system.h> +#include <util/time.h> #include <validation.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <checkqueue.h> #include <boost/test/unit_test.hpp> #include <boost/thread.hpp> @@ -148,14 +148,14 @@ typedef CCheckQueue<FrozenCleanupCheck> FrozenCleanup_Queue; */ static void Correct_Queue_range(std::vector<size_t> range) { - auto small_queue = std::unique_ptr<Correct_Queue>(new Correct_Queue {QUEUE_BATCH_SIZE}); + auto small_queue = MakeUnique<Correct_Queue>(QUEUE_BATCH_SIZE); boost::thread_group tg; for (auto x = 0; x < nScriptCheckThreads; ++x) { tg.create_thread([&]{small_queue->Thread();}); } // Make vChecks here to save on malloc (this test can be slow...) std::vector<FakeCheckCheckCompletion> vChecks; - for (auto i : range) { + for (const size_t i : range) { size_t total = i; FakeCheckCheckCompletion::n_calls = 0; CCheckQueueControl<FakeCheckCheckCompletion> control(small_queue.get()); @@ -167,7 +167,6 @@ static void Correct_Queue_range(std::vector<size_t> range) BOOST_REQUIRE(control.Wait()); if (FakeCheckCheckCompletion::n_calls != i) { BOOST_REQUIRE_EQUAL(FakeCheckCheckCompletion::n_calls, i); - BOOST_TEST_MESSAGE("Failure on trial " << i << " expected, got " << FakeCheckCheckCompletion::n_calls); } } tg.interrupt_all(); @@ -213,7 +212,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Random) /** Test that failing checks are caught */ BOOST_AUTO_TEST_CASE(test_CheckQueue_Catches_Failure) { - auto fail_queue = std::unique_ptr<Failing_Queue>(new Failing_Queue {QUEUE_BATCH_SIZE}); + auto fail_queue = MakeUnique<Failing_Queue>(QUEUE_BATCH_SIZE); boost::thread_group tg; for (auto x = 0; x < nScriptCheckThreads; ++x) { @@ -246,14 +245,14 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Catches_Failure) // future blocks, ie, the bad state is cleared. BOOST_AUTO_TEST_CASE(test_CheckQueue_Recovers_From_Failure) { - auto fail_queue = std::unique_ptr<Failing_Queue>(new Failing_Queue {QUEUE_BATCH_SIZE}); + auto fail_queue = MakeUnique<Failing_Queue>(QUEUE_BATCH_SIZE); boost::thread_group tg; for (auto x = 0; x < nScriptCheckThreads; ++x) { tg.create_thread([&]{fail_queue->Thread();}); } for (auto times = 0; times < 10; ++times) { - for (bool end_fails : {true, false}) { + for (const bool end_fails : {true, false}) { CCheckQueueControl<FailingCheck> control(fail_queue.get()); { std::vector<FailingCheck> vChecks; @@ -274,7 +273,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Recovers_From_Failure) // more than once as well BOOST_AUTO_TEST_CASE(test_CheckQueue_UniqueCheck) { - auto queue = std::unique_ptr<Unique_Queue>(new Unique_Queue {QUEUE_BATCH_SIZE}); + auto queue = MakeUnique<Unique_Queue>(QUEUE_BATCH_SIZE); boost::thread_group tg; for (auto x = 0; x < nScriptCheckThreads; ++x) { tg.create_thread([&]{queue->Thread();}); @@ -310,7 +309,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_UniqueCheck) // time could leave the data hanging across a sequence of blocks. BOOST_AUTO_TEST_CASE(test_CheckQueue_Memory) { - auto queue = std::unique_ptr<Memory_Queue>(new Memory_Queue {QUEUE_BATCH_SIZE}); + auto queue = MakeUnique<Memory_Queue>(QUEUE_BATCH_SIZE); boost::thread_group tg; for (auto x = 0; x < nScriptCheckThreads; ++x) { tg.create_thread([&]{queue->Thread();}); @@ -341,7 +340,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Memory) // have been destructed BOOST_AUTO_TEST_CASE(test_CheckQueue_FrozenCleanup) { - auto queue = std::unique_ptr<FrozenCleanup_Queue>(new FrozenCleanup_Queue {QUEUE_BATCH_SIZE}); + auto queue = MakeUnique<FrozenCleanup_Queue>(QUEUE_BATCH_SIZE); boost::thread_group tg; bool fails = false; for (auto x = 0; x < nScriptCheckThreads; ++x) { @@ -355,7 +354,8 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_FrozenCleanup) // would get called twice). vChecks[0].should_freeze = true; control.Add(vChecks); - control.Wait(); // Hangs here + bool waitResult = control.Wait(); // Hangs here + assert(waitResult); }); { std::unique_lock<std::mutex> l(FrozenCleanupCheck::m); @@ -384,7 +384,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_FrozenCleanup) /** Test that CCheckQueueControl is threadsafe */ BOOST_AUTO_TEST_CASE(test_CheckQueueControl_Locks) { - auto queue = std::unique_ptr<Standard_Queue>(new Standard_Queue{QUEUE_BATCH_SIZE}); + auto queue = MakeUnique<Standard_Queue>(QUEUE_BATCH_SIZE); { boost::thread_group tg; std::atomic<int> nThreads {0}; diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index b792ff8b45..665975ca67 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -1,18 +1,19 @@ -// Copyright (c) 2014-2017 The Bitcoin Core developers +// Copyright (c) 2014-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include <attributes.h> #include <coins.h> +#include <consensus/validation.h> #include <script/standard.h> +#include <test/setup_common.h> #include <uint256.h> #include <undo.h> -#include <utilstrencodings.h> -#include <test/test_bitcoin.h> +#include <util/strencodings.h> #include <validation.h> -#include <consensus/validation.h> -#include <vector> #include <map> +#include <vector> #include <boost/test/unit_test.hpp> @@ -36,7 +37,7 @@ class CCoinsViewTest : public CCoinsView std::map<COutPoint, Coin> map_; public: - bool GetCoin(const COutPoint& outpoint, Coin& coin) const override + NODISCARD bool GetCoin(const COutPoint& outpoint, Coin& coin) const override { std::map<COutPoint, Coin>::const_iterator it = map_.find(outpoint); if (it == map_.end()) { @@ -175,7 +176,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) } else { removed_an_entry = true; coin.Clear(); - stack.back()->SpendCoin(COutPoint(txid, 0)); + BOOST_CHECK(stack.back()->SpendCoin(COutPoint(txid, 0))); } } @@ -210,14 +211,14 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) // Every 100 iterations, flush an intermediate cache if (stack.size() > 1 && InsecureRandBool() == 0) { unsigned int flushIndex = InsecureRandRange(stack.size() - 1); - stack[flushIndex]->Flush(); + BOOST_CHECK(stack[flushIndex]->Flush()); } } if (InsecureRandRange(100) == 0) { // Every 100 iterations, change the cache stack. if (stack.size() > 0 && InsecureRandBool() == 0) { //Remove the top cache - stack.back()->Flush(); + BOOST_CHECK(stack.back()->Flush()); delete stack.back(); stack.pop_back(); } @@ -278,6 +279,8 @@ UtxoData::iterator FindRandomFrom(const std::set<COutPoint> &utxoSet) { // has the expected effect (the other duplicate is overwritten at all cache levels) BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) { + SeedInsecureRand(/* deterministic */ true); + bool spent_a_duplicate_coinbase = false; // A simple map to track what we expect the cache stack to represent. std::map<COutPoint, Coin> result; @@ -376,7 +379,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) // Call UpdateCoins on the top cache CTxUndo undo; - UpdateCoins(tx, *(stack.back()), undo, height); + UpdateCoins(CTransaction(tx), *(stack.back()), undo, height); // Update the utxo set for future spends utxoset.insert(outpoint); @@ -402,7 +405,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) // Disconnect the tx from the current UTXO // See code in DisconnectBlock // remove outputs - stack.back()->SpendCoin(utxod->first); + BOOST_CHECK(stack.back()->SpendCoin(utxod->first)); // restore inputs if (!tx.IsCoinBase()) { const COutPoint &out = tx.vin[0].prevout; @@ -443,13 +446,13 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) // Every 100 iterations, flush an intermediate cache if (stack.size() > 1 && InsecureRandBool() == 0) { unsigned int flushIndex = InsecureRandRange(stack.size() - 1); - stack[flushIndex]->Flush(); + BOOST_CHECK(stack[flushIndex]->Flush()); } } if (InsecureRandRange(100) == 0) { // Every 100 iterations, change the cache stack. if (stack.size() > 0 && InsecureRandBool() == 0) { - stack.back()->Flush(); + BOOST_CHECK(stack.back()->Flush()); delete stack.back(); stack.pop_back(); } @@ -482,7 +485,7 @@ BOOST_AUTO_TEST_CASE(ccoins_serialization) BOOST_CHECK_EQUAL(cc1.fCoinBase, false); BOOST_CHECK_EQUAL(cc1.nHeight, 203998U); BOOST_CHECK_EQUAL(cc1.out.nValue, CAmount{60000000000}); - BOOST_CHECK_EQUAL(HexStr(cc1.out.scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35")))))); + BOOST_CHECK_EQUAL(HexStr(cc1.out.scriptPubKey), HexStr(GetScriptForDestination(PKHash(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35")))))); // Good example CDataStream ss2(ParseHex("8ddf77bbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa4"), SER_DISK, CLIENT_VERSION); @@ -491,7 +494,7 @@ BOOST_AUTO_TEST_CASE(ccoins_serialization) BOOST_CHECK_EQUAL(cc2.fCoinBase, true); BOOST_CHECK_EQUAL(cc2.nHeight, 120891U); BOOST_CHECK_EQUAL(cc2.out.nValue, 110397); - BOOST_CHECK_EQUAL(HexStr(cc2.out.scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("8c988f1a4a4de2161e0f50aac7f17e7f9555caa4")))))); + BOOST_CHECK_EQUAL(HexStr(cc2.out.scriptPubKey), HexStr(GetScriptForDestination(PKHash(uint160(ParseHex("8c988f1a4a4de2161e0f50aac7f17e7f9555caa4")))))); // Smallest possible example CDataStream ss3(ParseHex("000006"), SER_DISK, CLIENT_VERSION); @@ -508,7 +511,7 @@ BOOST_AUTO_TEST_CASE(ccoins_serialization) Coin cc4; ss4 >> cc4; BOOST_CHECK_MESSAGE(false, "We should have thrown"); - } catch (const std::ios_base::failure& e) { + } catch (const std::ios_base::failure&) { } // Very large scriptPubKey (3*10^9 bytes) past the end of the stream @@ -521,7 +524,7 @@ BOOST_AUTO_TEST_CASE(ccoins_serialization) Coin cc5; ss5 >> cc5; BOOST_CHECK_MESSAGE(false, "We should have thrown"); - } catch (const std::ios_base::failure& e) { + } catch (const std::ios_base::failure&) { } } @@ -588,7 +591,7 @@ void WriteCoinsViewEntry(CCoinsView& view, CAmount value, char flags) { CCoinsMap map; InsertCoinsMapEntry(map, value, flags); - view.BatchWrite(map, {}); + BOOST_CHECK(view.BatchWrite(map, {})); } class SingleEntryCacheTest @@ -719,7 +722,7 @@ static void CheckAddCoinBase(CAmount base_value, CAmount cache_value, CAmount mo test.cache.AddCoin(OUTPOINT, Coin(std::move(output), 1, coinbase), coinbase); test.cache.SelfTest(); GetCoinsMapEntry(test.cache.map(), result_value, result_flags); - } catch (std::logic_error& e) { + } catch (std::logic_error&) { result_value = FAIL; result_flags = NO_ENTRY; } @@ -736,7 +739,7 @@ static void CheckAddCoinBase(CAmount base_value, CAmount cache_value, CAmount mo template <typename... Args> static void CheckAddCoin(Args&&... args) { - for (CAmount base_value : {ABSENT, PRUNED, VALUE1}) + for (const CAmount base_value : {ABSENT, PRUNED, VALUE1}) CheckAddCoinBase(base_value, std::forward<Args>(args)...); } @@ -780,7 +783,7 @@ void CheckWriteCoins(CAmount parent_value, CAmount child_value, CAmount expected WriteCoinsViewEntry(test.cache, child_value, child_flags); test.cache.SelfTest(); GetCoinsMapEntry(test.cache.map(), result_value, result_flags); - } catch (std::logic_error& e) { + } catch (std::logic_error&) { result_value = FAIL; result_flags = NO_ENTRY; } @@ -848,10 +851,10 @@ BOOST_AUTO_TEST_CASE(ccoins_write) // they would be too repetitive (the parent cache is never updated in these // cases). The loop below covers these cases and makes sure the parent cache // is always left unchanged. - for (CAmount parent_value : {ABSENT, PRUNED, VALUE1}) - for (CAmount child_value : {ABSENT, PRUNED, VALUE2}) - for (char parent_flags : parent_value == ABSENT ? ABSENT_FLAGS : FLAGS) - for (char child_flags : child_value == ABSENT ? ABSENT_FLAGS : CLEAN_FLAGS) + for (const CAmount parent_value : {ABSENT, PRUNED, VALUE1}) + for (const CAmount child_value : {ABSENT, PRUNED, VALUE2}) + for (const char parent_flags : parent_value == ABSENT ? ABSENT_FLAGS : FLAGS) + for (const char child_flags : child_value == ABSENT ? ABSENT_FLAGS : CLEAN_FLAGS) CheckWriteCoins(parent_value, child_value, parent_value, parent_flags, child_flags, parent_flags); } diff --git a/src/test/compress_tests.cpp b/src/test/compress_tests.cpp index 127cc154df..6cef8cd8a8 100644 --- a/src/test/compress_tests.cpp +++ b/src/test/compress_tests.cpp @@ -1,10 +1,10 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <compressor.h> -#include <util.h> -#include <test/test_bitcoin.h> +#include <util/system.h> +#include <test/setup_common.h> #include <stdint.h> diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index d701f3bc4e..35911e507f 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -1,24 +1,24 @@ -// Copyright (c) 2014-2017 The Bitcoin Core developers +// Copyright (c) 2014-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <crypto/aes.h> #include <crypto/chacha20.h> +#include <crypto/poly1305.h> +#include <crypto/hkdf_sha256_32.h> +#include <crypto/hmac_sha256.h> +#include <crypto/hmac_sha512.h> #include <crypto/ripemd160.h> #include <crypto/sha1.h> #include <crypto/sha256.h> #include <crypto/sha512.h> -#include <crypto/hmac_sha256.h> -#include <crypto/hmac_sha512.h> #include <random.h> -#include <utilstrencodings.h> -#include <test/test_bitcoin.h> +#include <util/strencodings.h> +#include <test/setup_common.h> #include <vector> #include <boost/test/unit_test.hpp> -#include <openssl/aes.h> -#include <openssl/evp.h> BOOST_FIXTURE_TEST_SUITE(crypto_tests, BasicTestingSetup) @@ -66,26 +66,6 @@ static void TestHMACSHA512(const std::string &hexkey, const std::string &hexin, TestVector(CHMAC_SHA512(key.data(), key.size()), ParseHex(hexin), ParseHex(hexout)); } -static void TestAES128(const std::string &hexkey, const std::string &hexin, const std::string &hexout) -{ - std::vector<unsigned char> key = ParseHex(hexkey); - std::vector<unsigned char> in = ParseHex(hexin); - std::vector<unsigned char> correctout = ParseHex(hexout); - std::vector<unsigned char> buf, buf2; - - assert(key.size() == 16); - assert(in.size() == 16); - assert(correctout.size() == 16); - AES128Encrypt enc(key.data()); - buf.resize(correctout.size()); - buf2.resize(correctout.size()); - enc.Encrypt(buf.data(), in.data()); - BOOST_CHECK_EQUAL(HexStr(buf), HexStr(correctout)); - AES128Decrypt dec(key.data()); - dec.Decrypt(buf2.data(), buf.data()); - BOOST_CHECK_EQUAL(HexStr(buf2), HexStr(in)); -} - static void TestAES256(const std::string &hexkey, const std::string &hexin, const std::string &hexout) { std::vector<unsigned char> key = ParseHex(hexkey); @@ -105,47 +85,6 @@ static void TestAES256(const std::string &hexkey, const std::string &hexin, cons BOOST_CHECK(buf == in); } -static void TestAES128CBC(const std::string &hexkey, const std::string &hexiv, bool pad, const std::string &hexin, const std::string &hexout) -{ - std::vector<unsigned char> key = ParseHex(hexkey); - std::vector<unsigned char> iv = ParseHex(hexiv); - std::vector<unsigned char> in = ParseHex(hexin); - std::vector<unsigned char> correctout = ParseHex(hexout); - std::vector<unsigned char> realout(in.size() + AES_BLOCKSIZE); - - // Encrypt the plaintext and verify that it equals the cipher - AES128CBCEncrypt enc(key.data(), iv.data(), pad); - int size = enc.Encrypt(in.data(), in.size(), realout.data()); - realout.resize(size); - BOOST_CHECK(realout.size() == correctout.size()); - BOOST_CHECK_MESSAGE(realout == correctout, HexStr(realout) + std::string(" != ") + hexout); - - // Decrypt the cipher and verify that it equals the plaintext - std::vector<unsigned char> decrypted(correctout.size()); - AES128CBCDecrypt dec(key.data(), iv.data(), pad); - size = dec.Decrypt(correctout.data(), correctout.size(), decrypted.data()); - decrypted.resize(size); - BOOST_CHECK(decrypted.size() == in.size()); - BOOST_CHECK_MESSAGE(decrypted == in, HexStr(decrypted) + std::string(" != ") + hexin); - - // Encrypt and re-decrypt substrings of the plaintext and verify that they equal each-other - for(std::vector<unsigned char>::iterator i(in.begin()); i != in.end(); ++i) - { - std::vector<unsigned char> sub(i, in.end()); - std::vector<unsigned char> subout(sub.size() + AES_BLOCKSIZE); - int _size = enc.Encrypt(sub.data(), sub.size(), subout.data()); - if (_size != 0) - { - subout.resize(_size); - std::vector<unsigned char> subdecrypted(subout.size()); - _size = dec.Decrypt(subout.data(), subout.size(), subdecrypted.data()); - subdecrypted.resize(_size); - BOOST_CHECK(decrypted.size() == in.size()); - BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub)); - } - } -} - static void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, bool pad, const std::string &hexin, const std::string &hexout) { std::vector<unsigned char> key = ParseHex(hexkey); @@ -187,20 +126,66 @@ static void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, b } } -static void TestChaCha20(const std::string &hexkey, uint64_t nonce, uint64_t seek, const std::string& hexout) +static void TestChaCha20(const std::string &hex_message, const std::string &hexkey, uint64_t nonce, uint64_t seek, const std::string& hexout) { std::vector<unsigned char> key = ParseHex(hexkey); + std::vector<unsigned char> m = ParseHex(hex_message); ChaCha20 rng(key.data(), key.size()); rng.SetIV(nonce); rng.Seek(seek); std::vector<unsigned char> out = ParseHex(hexout); std::vector<unsigned char> outres; outres.resize(out.size()); - rng.Output(outres.data(), outres.size()); + assert(hex_message.empty() || m.size() == out.size()); + + // perform the ChaCha20 round(s), if message is provided it will output the encrypted ciphertext otherwise the keystream + if (!hex_message.empty()) { + rng.Crypt(m.data(), outres.data(), outres.size()); + } else { + rng.Keystream(outres.data(), outres.size()); + } BOOST_CHECK(out == outres); + if (!hex_message.empty()) { + // Manually XOR with the keystream and compare the output + rng.SetIV(nonce); + rng.Seek(seek); + std::vector<unsigned char> only_keystream(outres.size()); + rng.Keystream(only_keystream.data(), only_keystream.size()); + for (size_t i = 0; i != m.size(); i++) { + outres[i] = m[i] ^ only_keystream[i]; + } + BOOST_CHECK(out == outres); + } +} + +static void TestPoly1305(const std::string &hexmessage, const std::string &hexkey, const std::string& hextag) +{ + std::vector<unsigned char> key = ParseHex(hexkey); + std::vector<unsigned char> m = ParseHex(hexmessage); + std::vector<unsigned char> tag = ParseHex(hextag); + std::vector<unsigned char> tagres; + tagres.resize(POLY1305_TAGLEN); + poly1305_auth(tagres.data(), m.data(), m.size(), key.data()); + BOOST_CHECK(tag == tagres); +} + +static void TestHKDF_SHA256_32(const std::string &ikm_hex, const std::string &salt_hex, const std::string &info_hex, const std::string &okm_check_hex) { + std::vector<unsigned char> initial_key_material = ParseHex(ikm_hex); + std::vector<unsigned char> salt = ParseHex(salt_hex); + std::vector<unsigned char> info = ParseHex(info_hex); + + + // our implementation only supports strings for the "info" and "salt", stringify them + std::string salt_stringified(reinterpret_cast<char*>(salt.data()), salt.size()); + std::string info_stringified(reinterpret_cast<char*>(info.data()), info.size()); + + CHKDF_HMAC_SHA256_L32 hkdf32(initial_key_material.data(), initial_key_material.size(), salt_stringified); + unsigned char out[32]; + hkdf32.Expand32(info_stringified, out); + BOOST_CHECK(HexStr(out, out + 32) == okm_check_hex); } -static std::string LongTestString(void) { +static std::string LongTestString() { std::string ret; for (int i=0; i<200000; i++) { ret += (unsigned char)(i); @@ -428,14 +413,9 @@ BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) { BOOST_AUTO_TEST_CASE(aes_testvectors) { // AES test vectors from FIPS 197. - TestAES128("000102030405060708090a0b0c0d0e0f", "00112233445566778899aabbccddeeff", "69c4e0d86a7b0430d8cdb78070b4c55a"); TestAES256("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "00112233445566778899aabbccddeeff", "8ea2b7ca516745bfeafc49904b496089"); // AES-ECB test vectors from NIST sp800-38a. - TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "6bc1bee22e409f96e93d7e117393172a", "3ad77bb40d7a3660a89ecaf32466ef97"); - TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "ae2d8a571e03ac9c9eb76fac45af8e51", "f5d3d58503b9699de785895a96fdbaaf"); - TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "30c81c46a35ce411e5fbc1191a0a52ef", "43b1cd7f598ece23881b00e3ed030688"); - TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "f69f2445df4f9b17ad2b417be66c3710", "7b0c785e27e8ad3f8223207104725dd4"); TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "6bc1bee22e409f96e93d7e117393172a", "f3eed1bdb5d2a03c064b5a7e3db181f8"); TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "ae2d8a571e03ac9c9eb76fac45af8e51", "591ccb10d410ed26dc5ba74a31362870"); TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "30c81c46a35ce411e5fbc1191a0a52ef", "b6ed21b99ca6f4f9f153e7b1beafed1d"); @@ -443,27 +423,6 @@ BOOST_AUTO_TEST_CASE(aes_testvectors) { } BOOST_AUTO_TEST_CASE(aes_cbc_testvectors) { - - // NIST AES CBC 128-bit encryption test-vectors - TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", false, \ - "6bc1bee22e409f96e93d7e117393172a", "7649abac8119b246cee98e9b12e9197d"); - TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "7649ABAC8119B246CEE98E9B12E9197D", false, \ - "ae2d8a571e03ac9c9eb76fac45af8e51", "5086cb9b507219ee95db113a917678b2"); - TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "5086cb9b507219ee95db113a917678b2", false, \ - "30c81c46a35ce411e5fbc1191a0a52ef", "73bed6b8e3c1743b7116e69e22229516"); - TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "73bed6b8e3c1743b7116e69e22229516", false, \ - "f69f2445df4f9b17ad2b417be66c3710", "3ff1caa1681fac09120eca307586e1a7"); - - // The same vectors with padding enabled - TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", true, \ - "6bc1bee22e409f96e93d7e117393172a", "7649abac8119b246cee98e9b12e9197d8964e0b149c10b7b682e6e39aaeb731c"); - TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "7649ABAC8119B246CEE98E9B12E9197D", true, \ - "ae2d8a571e03ac9c9eb76fac45af8e51", "5086cb9b507219ee95db113a917678b255e21d7100b988ffec32feeafaf23538"); - TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "5086cb9b507219ee95db113a917678b2", true, \ - "30c81c46a35ce411e5fbc1191a0a52ef", "73bed6b8e3c1743b7116e69e22229516f6eccda327bf8e5ec43718b0039adceb"); - TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "73bed6b8e3c1743b7116e69e22229516", true, \ - "f69f2445df4f9b17ad2b417be66c3710", "3ff1caa1681fac09120eca307586e1a78cb82807230e1321d3fae00d18cc2012"); - // NIST AES CBC 256-bit encryption test-vectors TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \ "000102030405060708090A0B0C0D0E0F", false, "6bc1bee22e409f96e93d7e117393172a", \ @@ -497,25 +456,37 @@ BOOST_AUTO_TEST_CASE(aes_cbc_testvectors) { BOOST_AUTO_TEST_CASE(chacha20_testvector) { // Test vector from RFC 7539 - TestChaCha20("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x4a000000UL, 1, + + // test encryption + TestChaCha20("4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756" + "c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e" + "20776f756c642062652069742e", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x4a000000UL, 1, + "6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0bf91b65c5524733ab8f593dabcd62b3571639d" + "624e65152ab8f530c359f0861d807ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab77937365af90bbf74" + "a35be6b40b8eedf2785e42874d" + ); + + // test keystream output + TestChaCha20("", "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x4a000000UL, 1, "224f51f3401bd9e12fde276fb8631ded8c131f823d2c06e27e4fcaec9ef3cf788a3b0aa372600a92b57974cded2b9334794cb" "a40c63e34cdea212c4cf07d41b769a6749f3f630f4122cafe28ec4dc47e26d4346d70b98c73f3e9c53ac40c5945398b6eda1a" "832c89c167eacd901d7e2bf363"); // Test vectors from https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7 - TestChaCha20("0000000000000000000000000000000000000000000000000000000000000000", 0, 0, + TestChaCha20("", "0000000000000000000000000000000000000000000000000000000000000000", 0, 0, "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b" "8f41518a11cc387b669b2ee6586"); - TestChaCha20("0000000000000000000000000000000000000000000000000000000000000001", 0, 0, + TestChaCha20("", "0000000000000000000000000000000000000000000000000000000000000001", 0, 0, "4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d79" "2b1c43fea817e9ad275ae546963"); - TestChaCha20("0000000000000000000000000000000000000000000000000000000000000000", 0x0100000000000000ULL, 0, + TestChaCha20("", "0000000000000000000000000000000000000000000000000000000000000000", 0x0100000000000000ULL, 0, "de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a7084527214f73efc7fa5b52770" "62eb7a0433e445f41e3"); - TestChaCha20("0000000000000000000000000000000000000000000000000000000000000000", 1, 0, + TestChaCha20("", "0000000000000000000000000000000000000000000000000000000000000000", 1, 0, "ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc4" "97a0b466e7d6bbdb0041b2f586b"); - TestChaCha20("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x0706050403020100ULL, 0, + TestChaCha20("", "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x0706050403020100ULL, 0, "f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3b" "e59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc1" "18be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5" @@ -524,6 +495,96 @@ BOOST_AUTO_TEST_CASE(chacha20_testvector) "fab78c9"); } +BOOST_AUTO_TEST_CASE(poly1305_testvector) +{ + // RFC 7539, section 2.5.2. + TestPoly1305("43727970746f6772617068696320466f72756d2052657365617263682047726f7570", + "85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b", + "a8061dc1305136c6c22b8baf0c0127a9"); + + // RFC 7539, section A.3. + TestPoly1305("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000"); + + TestPoly1305("416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e747269627" + "5746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465" + "726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686" + "520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e2022494554" + "4620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c20737461746" + "56d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c65" + "6374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207" + "768696368206172652061646472657373656420746f", + "0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e", + "36e5f6b5c5e06070f0efca96227a863e"); + + TestPoly1305("416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e747269627" + "5746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465" + "726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686" + "520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e2022494554" + "4620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c20737461746" + "56d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c65" + "6374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207" + "768696368206172652061646472657373656420746f", + "36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000", + "f3477e7cd95417af89a6b8794c310cf0"); + + TestPoly1305("2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e6420676" + "96d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e" + "6420746865206d6f6d65207261746873206f757467726162652e", + "1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0", + "4541669a7eaaee61e708dc7cbcc5eb62"); + + TestPoly1305("ffffffffffffffffffffffffffffffff", + "0200000000000000000000000000000000000000000000000000000000000000", + "03000000000000000000000000000000"); + + TestPoly1305("02000000000000000000000000000000", + "02000000000000000000000000000000ffffffffffffffffffffffffffffffff", + "03000000000000000000000000000000"); + + TestPoly1305("fffffffffffffffffffffffffffffffff0ffffffffffffffffffffffffffffff11000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000", + "05000000000000000000000000000000"); + + TestPoly1305("fffffffffffffffffffffffffffffffffbfefefefefefefefefefefefefefefe01010101010101010101010101010101", + "0100000000000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000"); + + TestPoly1305("fdffffffffffffffffffffffffffffff", + "0200000000000000000000000000000000000000000000000000000000000000", + "faffffffffffffffffffffffffffffff"); + + TestPoly1305("e33594d7505e43b900000000000000003394d7505e4379cd01000000000000000000000000000000000000000000000001000000000000000000000000000000", + "0100000000000000040000000000000000000000000000000000000000000000", + "14000000000000005500000000000000"); + + TestPoly1305("e33594d7505e43b900000000000000003394d7505e4379cd010000000000000000000000000000000000000000000000", + "0100000000000000040000000000000000000000000000000000000000000000", + "13000000000000000000000000000000"); +} + +BOOST_AUTO_TEST_CASE(hkdf_hmac_sha256_l32_tests) +{ + // Use rfc5869 test vectors but trucated to 32 bytes (our implementation only support length 32) + TestHKDF_SHA256_32( + /* IKM */ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + /* salt */ "000102030405060708090a0b0c", + /* info */ "f0f1f2f3f4f5f6f7f8f9", + /* expected OKM */ "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf"); + TestHKDF_SHA256_32( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f", + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf", + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", + "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c"); + TestHKDF_SHA256_32( + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "", + "", + "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d"); +} + BOOST_AUTO_TEST_CASE(countbits_tests) { FastRandomContext ctx; @@ -532,7 +593,7 @@ BOOST_AUTO_TEST_CASE(countbits_tests) // Check handling of zero. BOOST_CHECK_EQUAL(CountBits(0), 0U); } else if (i < 10) { - for (uint64_t j = 1 << (i - 1); (j >> i) == 0; ++j) { + for (uint64_t j = (uint64_t)1 << (i - 1); (j >> i) == 0; ++j) { // Exhaustively test up to 10 bits BOOST_CHECK_EQUAL(CountBits(j), i); } diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp index 2edc7c16d4..d38ede691a 100644 --- a/src/test/cuckoocache_tests.cpp +++ b/src/test/cuckoocache_tests.cpp @@ -1,10 +1,10 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <boost/test/unit_test.hpp> #include <cuckoocache.h> #include <script/sigcache.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <random.h> #include <thread> @@ -21,40 +21,23 @@ * using BOOST_CHECK_CLOSE to fail. * */ -FastRandomContext local_rand_ctx(true); - BOOST_AUTO_TEST_SUITE(cuckoocache_tests); - -/** insecure_GetRandHash fills in a uint256 from local_rand_ctx - */ -static void insecure_GetRandHash(uint256& t) -{ - uint32_t* ptr = (uint32_t*)t.begin(); - for (uint8_t j = 0; j < 8; ++j) - *(ptr++) = local_rand_ctx.rand32(); -} - - - /* Test that no values not inserted into the cache are read out of it. * * There are no repeats in the first 200000 insecure_GetRandHash calls */ BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes) { - local_rand_ctx = FastRandomContext(true); + SeedInsecureRand(true); CuckooCache::cache<uint256, SignatureCacheHasher> cc{}; size_t megabytes = 4; cc.setup_bytes(megabytes << 20); - uint256 v; for (int x = 0; x < 100000; ++x) { - insecure_GetRandHash(v); - cc.insert(v); + cc.insert(InsecureRand256()); } for (int x = 0; x < 100000; ++x) { - insecure_GetRandHash(v); - BOOST_CHECK(!cc.contains(v, false)); + BOOST_CHECK(!cc.contains(InsecureRand256(), false)); } }; @@ -64,7 +47,7 @@ BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes) template <typename Cache> static double test_cache(size_t megabytes, double load) { - local_rand_ctx = FastRandomContext(true); + SeedInsecureRand(true); std::vector<uint256> hashes; Cache set{}; size_t bytes = megabytes * (1 << 20); @@ -74,7 +57,7 @@ static 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++) = local_rand_ctx.rand32(); + *(ptr++) = InsecureRand32(); } /** We make a copy of the hashes because future optimizations of the * cuckoocache may overwrite the inserted element, so the test is @@ -82,11 +65,11 @@ static double test_cache(size_t megabytes, double load) */ std::vector<uint256> hashes_insert_copy = hashes; /** Do the insert */ - for (uint256& h : hashes_insert_copy) + for (const uint256& h : hashes_insert_copy) set.insert(h); /** Count the hits */ uint32_t count = 0; - for (uint256& h : hashes) + for (const uint256& h : hashes) count += set.contains(h, false); double hit_rate = ((double)count) / ((double)n_insert); return hit_rate; @@ -135,7 +118,7 @@ template <typename Cache> static void test_cache_erase(size_t megabytes) { double load = 1; - local_rand_ctx = FastRandomContext(true); + SeedInsecureRand(true); std::vector<uint256> hashes; Cache set{}; size_t bytes = megabytes * (1 << 20); @@ -145,7 +128,7 @@ static 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++) = local_rand_ctx.rand32(); + *(ptr++) = InsecureRand32(); } /** We make a copy of the hashes because future optimizations of the * cuckoocache may overwrite the inserted element, so the test is @@ -158,7 +141,7 @@ static void test_cache_erase(size_t megabytes) set.insert(hashes_insert_copy[i]); /** Erase the first quarter */ for (uint32_t i = 0; i < (n_insert / 4); ++i) - set.contains(hashes[i], true); + BOOST_CHECK(set.contains(hashes[i], true)); /** Insert the second half */ for (uint32_t i = (n_insert / 2); i < n_insert; ++i) set.insert(hashes_insert_copy[i]); @@ -198,7 +181,7 @@ template <typename Cache> static void test_cache_erase_parallel(size_t megabytes) { double load = 1; - local_rand_ctx = FastRandomContext(true); + SeedInsecureRand(true); std::vector<uint256> hashes; Cache set{}; size_t bytes = megabytes * (1 << 20); @@ -208,7 +191,7 @@ static 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++) = local_rand_ctx.rand32(); + *(ptr++) = InsecureRand32(); } /** We make a copy of the hashes because future optimizations of the * cuckoocache may overwrite the inserted element, so the test is @@ -237,8 +220,10 @@ static void test_cache_erase_parallel(size_t megabytes) size_t ntodo = (n_insert/4)/3; size_t start = ntodo*x; size_t end = ntodo*(x+1); - for (uint32_t i = start; i < end; ++i) - set.contains(hashes[i], true); + for (uint32_t i = start; i < end; ++i) { + bool contains = set.contains(hashes[i], true); + assert(contains); + } }); /** Wait for all threads to finish @@ -300,7 +285,7 @@ static 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. - local_rand_ctx = FastRandomContext(true); + SeedInsecureRand(true); // block_activity models a chunk of network activity. n_insert elements are // added to the cache. The first and last n/4 are stored for removal later @@ -317,13 +302,13 @@ static 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++) = local_rand_ctx.rand32(); + *(ptr++) = InsecureRand32(); } for (uint32_t i = 0; i < n_insert / 4; ++i) reads.push_back(inserts[i]); for (uint32_t i = n_insert - (n_insert / 4); i < n_insert; ++i) reads.push_back(inserts[i]); - for (auto h : inserts) + for (const auto& h : inserts) c.insert(h); } }; diff --git a/src/test/data/blockfilters.json b/src/test/data/blockfilters.json new file mode 100644 index 0000000000..8945296a07 --- /dev/null +++ b/src/test/data/blockfilters.json @@ -0,0 +1,13 @@ +[ +["Block Height,Block Hash,Block,[Prev Output Scripts for Block],Previous Basic Header,Basic Filter,Basic Header,Notes"], +[0,"000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943","0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff001d1aa4ae180101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000",[],"0000000000000000000000000000000000000000000000000000000000000000","019dfca8","21584579b7eb08997773e5aeff3a7f932700042d0ed2a6129012b7d7ae81b750","Genesis block"], +[2,"000000006c02c8ea6e4ff69651f7fcde348fb9d557a06e6957b65552002a7820","0100000006128e87be8b1b4dea47a7247d5528d2702c96826c7a648497e773b800000000e241352e3bec0a95a6217e10c3abb54adfa05abb12c126695595580fb92e222032e7494dffff001d00d235340101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0432e7494d010e062f503253482fffffffff0100f2052a010000002321038a7f6ef1c8ca0c588aa53fa860128077c9e6c11e6830f4d7ee4e763a56b7718fac00000000",[],"d7bdac13a59d745b1add0d2ce852f1a0442e8945fc1bf3848d3cbffd88c24fe1","0174a170","186afd11ef2b5e7e3504f2e8cbf8df28a1fd251fe53d60dff8b1467d1b386cf0",""], +[3,"000000008b896e272758da5297bcd98fdc6d97c9b765ecec401e286dc1fdbe10","0100000020782a005255b657696ea057d5b98f34defcf75196f64f6eeac8026c0000000041ba5afc532aae03151b8aa87b65e1594f97504a768e010c98c0add79216247186e7494dffff001d058dc2b60101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0486e7494d0151062f503253482fffffffff0100f2052a01000000232103f6d9ff4c12959445ca5549c811683bf9c88e637b222dd2e0311154c4c85cf423ac00000000",[],"186afd11ef2b5e7e3504f2e8cbf8df28a1fd251fe53d60dff8b1467d1b386cf0","016cf7a0","8d63aadf5ab7257cb6d2316a57b16f517bff1c6388f124ec4c04af1212729d2a",""], +[15007,"0000000038c44c703bae0f98cdd6bf30922326340a5996cc692aaae8bacf47ad","0100000002394092aa378fe35d7e9ac79c869b975c4de4374cd75eb5484b0e1e00000000eb9b8670abd44ad6c55cee18e3020fb0c6519e7004b01a16e9164867531b67afc33bc94fffff001d123f10050101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e04c33bc94f0115062f503253482fffffffff0100f2052a01000000232103f268e9ae07e0f8cb2f6e901d87c510d650b97230c0365b021df8f467363cafb1ac00000000",[],"18b5c2b0146d2d09d24fb00ff5b52bd0742f36c9e65527abdb9de30c027a4748","013c3710","07384b01311867949e0c046607c66b7a766d338474bb67f66c8ae9dbd454b20e","Tx has non-standard OP_RETURN output followed by opcodes"], +[49291,"0000000018b07dca1b28b4b5a119f6d6e71698ce1ed96f143f54179ce177a19c","02000000abfaf47274223ca2fea22797e44498240e482cb4c2f2baea088962f800000000604b5b52c32305b15d7542071d8b04e750a547500005d4010727694b6e72a776e55d0d51ffff001d211806480201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0d038bc0000102062f503253482fffffffff01a078072a01000000232102971dd6034ed0cf52450b608d196c07d6345184fcb14deb277a6b82d526a6163dac0000000001000000081cefd96060ecb1c4fbe675ad8a4f8bdc61d634c52b3a1c4116dee23749fe80ff000000009300493046022100866859c21f306538152e83f115bcfbf59ab4bb34887a88c03483a5dff9895f96022100a6dfd83caa609bf0516debc2bf65c3df91813a4842650a1858b3f61cfa8af249014730440220296d4b818bb037d0f83f9f7111665f49532dfdcbec1e6b784526e9ac4046eaa602204acf3a5cb2695e8404d80bf49ab04828bcbe6fc31d25a2844ced7a8d24afbdff01ffffffff1cefd96060ecb1c4fbe675ad8a4f8bdc61d634c52b3a1c4116dee23749fe80ff020000009400483045022100e87899175991aa008176cb553c6f2badbb5b741f328c9845fcab89f8b18cae2302200acce689896dc82933015e7230e5230d5cff8a1ffe82d334d60162ac2c5b0c9601493046022100994ad29d1e7b03e41731a4316e5f4992f0d9b6e2efc40a1ccd2c949b461175c502210099b69fdc2db00fbba214f16e286f6a49e2d8a0d5ffc6409d87796add475478d601ffffffff1e4a6d2d280ea06680d6cf8788ac90344a9c67cca9b06005bbd6d3f6945c8272010000009500493046022100a27400ba52fd842ce07398a1de102f710a10c5599545e6c95798934352c2e4df022100f6383b0b14c9f64b6718139f55b6b9494374755b86bae7d63f5d3e583b57255a01493046022100fdf543292f34e1eeb1703b264965339ec4a450ec47585009c606b3edbc5b617b022100a5fbb1c8de8aaaa582988cdb23622838e38de90bebcaab3928d949aa502a65d401ffffffff1e4a6d2d280ea06680d6cf8788ac90344a9c67cca9b06005bbd6d3f6945c8272020000009400493046022100ac626ac3051f875145b4fe4cfe089ea895aac73f65ab837b1ac30f5d875874fa022100bc03e79fa4b7eb707fb735b95ff6613ca33adeaf3a0607cdcead4cfd3b51729801483045022100b720b04a5c5e2f61b7df0fcf334ab6fea167b7aaede5695d3f7c6973496adbf1022043328c4cc1cdc3e5db7bb895ccc37133e960b2fd3ece98350f774596badb387201ffffffff23a8733e349c97d6cd90f520fdd084ba15ce0a395aad03cd51370602bb9e5db3010000004a00483045022100e8556b72c5e9c0da7371913a45861a61c5df434dfd962de7b23848e1a28c86ca02205d41ceda00136267281be0974be132ac4cda1459fe2090ce455619d8b91045e901ffffffff6856d609b881e875a5ee141c235e2a82f6b039f2b9babe82333677a5570285a6000000006a473044022040a1c631554b8b210fbdf2a73f191b2851afb51d5171fb53502a3a040a38d2c0022040d11cf6e7b41fe1b66c3d08f6ada1aee07a047cb77f242b8ecc63812c832c9a012102bcfad931b502761e452962a5976c79158a0f6d307ad31b739611dac6a297c256ffffffff6856d609b881e875a5ee141c235e2a82f6b039f2b9babe82333677a5570285a601000000930048304502205b109df098f7e932fbf71a45869c3f80323974a826ee2770789eae178a21bfc8022100c0e75615e53ee4b6e32b9bb5faa36ac539e9c05fa2ae6b6de5d09c08455c8b9601483045022009fb7d27375c47bea23b24818634df6a54ecf72d52e0c1268fb2a2c84f1885de022100e0ed4f15d62e7f537da0d0f1863498f9c7c0c0a4e00e4679588c8d1a9eb20bb801ffffffffa563c3722b7b39481836d5edfc1461f97335d5d1e9a23ade13680d0e2c1c371f030000006c493046022100ecc38ae2b1565643dc3c0dad5e961a5f0ea09cab28d024f92fa05c922924157e022100ebc166edf6fbe4004c72bfe8cf40130263f98ddff728c8e67b113dbd621906a601210211a4ed241174708c07206601b44a4c1c29e5ad8b1f731c50ca7e1d4b2a06dc1fffffffff02d0223a00000000001976a91445db0b779c0b9fa207f12a8218c94fc77aff504588ac80f0fa02000000000000000000",["5221033423007d8f263819a2e42becaaf5b06f34cb09919e06304349d950668209eaed21021d69e2b68c3960903b702af7829fadcd80bd89b158150c85c4a75b2c8cb9c39452ae","52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821021d69e2b68c3960903b702af7829fadcd80bd89b158150c85c4a75b2c8cb9c39452ae","522102a7ae1e0971fc1689bd66d2a7296da3a1662fd21a53c9e38979e0f090a375c12d21022adb62335f41eb4e27056ac37d462cda5ad783fa8e0e526ed79c752475db285d52ae","52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821022adb62335f41eb4e27056ac37d462cda5ad783fa8e0e526ed79c752475db285d52ae","512103b9d1d0e2b4355ec3cdef7c11a5c0beff9e8b8d8372ab4b4e0aaf30e80173001951ae","76a9149144761ebaccd5b4bbdc2a35453585b5637b2f8588ac","522103f1848b40621c5d48471d9784c8174ca060555891ace6d2b03c58eece946b1a9121020ee5d32b54d429c152fdc7b1db84f2074b0564d35400d89d11870f9273ec140c52ae","76a914f4fa1cc7de742d135ea82c17adf0bb9cf5f4fb8388ac"],"ed47705334f4643892ca46396eb3f4196a5e30880589e4009ef38eae895d4a13","0afbc2920af1b027f31f87b592276eb4c32094bb4d3697021b4c6380","b6d98692cec5145f67585f3434ec3c2b3030182e1cb3ec58b855c5c164dfaaa3","Tx pays to empty output script"], +[180480,"00000000fd3ceb2404ff07a785c7fdcc76619edc8ed61bd25134eaa22084366a","020000006058aa080a655aa991a444bd7d1f2defd9a3bbe68aabb69030cf3b4e00000000d2e826bfd7ef0beaa891a7eedbc92cd6a544a6cb61c7bdaa436762eb2123ef9790f5f552ffff001d0002c90f0501000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0300c102024608062f503253482fffffffff01c0c6072a01000000232102e769e60137a4df6b0df8ebd387cca44c4c57ae74cc0114a8e8317c8f3bfd85e9ac00000000010000000381a0802911a01ffb025c4dea0bc77963e8c1bb46313b71164c53f72f37fe5248010000000151ffffffffc904b267833d215e2128bd9575242232ac2bc311550c7fc1f0ef6f264b40d14c010000000151ffffffffdf0915666649dba81886519c531649b7b02180b4af67d6885e871299e9d5f775000000000151ffffffff0180817dcb00000000232103bb52138972c48a132fc1f637858c5189607dd0f7fe40c4f20f6ad65f2d389ba4ac0000000001000000018da38b434fba82d66052af74fc5e4e94301b114d9bc03f819dc876398404c8b4010000006c493046022100fe738b7580dc5fb5168e51fc61b5aed211125eb71068031009a22d9bbad752c5022100be5086baa384d40bcab0fa586e4f728397388d86e18b66cc417dc4f7fa4f9878012103f233299455134caa2687bdf15cb0becdfb03bd0ff2ff38e65ec6b7834295c34fffffffff022ebc1400000000001976a9147779b7fba1c1e06b717069b80ca170e8b04458a488ac9879c40f000000001976a9142a0307cd925dbb66b534c4db33003dd18c57015788ac0000000001000000026139a62e3422a602de36c873a225c1d3ca5aeee598539ceecb9f0dc8d1ad0f83010000006b483045022100ad9f32b4a0a2ddc19b5a74eba78123e57616f1b3cfd72ce68c03ea35a3dda1f002200dbd22aa6da17213df5e70dfc3b2611d40f70c98ed9626aa5e2cde9d97461f0a012103ddb295d2f1e8319187738fb4b230fdd9aa29d0e01647f69f6d770b9ab24eea90ffffffff983c82c87cf020040d671956525014d5c2b28c6d948c85e1a522362c0059eeae010000006b4830450221009ca544274c786d30a5d5d25e17759201ea16d3aedddf0b9e9721246f7ef6b32e02202cfa5564b6e87dfd9fd98957820e4d4e6238baeb0f65fe305d91506bb13f5f4f012103c99113deac0d5d044e3ac0346abc02501542af8c8d3759f1382c72ff84e704f7ffffffff02c0c62d00000000001976a914ae19d27efe12f5a886dc79af37ad6805db6f922d88ac70ce2000000000001976a9143b8d051d37a07ea1042067e93efe63dbf73920b988ac000000000100000002be566e8cd9933f0c75c4a82c027f7d0c544d5c101d0607ef6ae5d07b98e7f1dc000000006b483045022036a8cdfd5ea7ebc06c2bfb6e4f942bbf9a1caeded41680d11a3a9f5d8284abad022100cacb92a5be3f39e8bc14db1710910ef7b395fa1e18f45d41c28d914fcdde33be012102bf59abf110b5131fae0a3ce1ec379329b4c896a6ae5d443edb68529cc2bc7816ffffffff96cf67645b76ceb23fe922874847456a15feee1655082ff32d25a6bf2c0dfc90000000006a47304402203471ca2001784a5ac0abab583581f2613523da47ec5f53df833c117b5abd81500220618a2847723d57324f2984678db556dbca1a72230fc7e39df04c2239942ba942012102925c9794fd7bb9f8b29e207d5fc491b1150135a21f505041858889fa4edf436fffffffff026c840f00000000001976a914797fb8777d7991d8284d88bfd421ce520f0f843188ac00ca9a3b000000001976a9146d10f3f592699265d10b106eda37c3ce793f7a8588ac00000000",["","","","76a9142903b138c24be9e070b3e73ec495d77a204615e788ac","76a91433a1941fd9a37b9821d376f5a51bd4b52fa50e2888ac","76a914e4374e8155d0865742ca12b8d4d14d41b57d682f88ac","76a914001fa7459a6cfc64bdc178ba7e7a21603bb2568f88ac","76a914f6039952bc2b307aeec5371bfb96b66078ec17f688ac"],"d34ef98386f413769502808d4bac5f20f8dfd5bffc9eedafaa71de0eb1f01489","0db414c859a07e8205876354a210a75042d0463404913d61a8e068e58a3ae2aa080026","c582d51c0ca365e3fcf36c51cb646d7f83a67e867cb4743fd2128e3e022b700c","Tx spends from empty output script"], +[926485,"000000000000015d6077a411a8f5cc95caf775ccf11c54e27df75ce58d187313","0000002060bbab0edbf3ef8a49608ee326f8fd75c473b7e3982095e2d100000000000000c30134f8c9b6d2470488d7a67a888f6fa12f8692e0c3411fbfb92f0f68f67eedae03ca57ef13021acc22dc4105010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff2f0315230e0004ae03ca57043e3d1e1d0c8796bf579aef0c0000000000122f4e696e6a61506f6f6c2f5345475749542fffffffff038427a112000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9ed5c748e121c0fe146d973a4ac26fa4a68b0549d46ee22d25f50a5e46fe1b377ee00000000000000002952534b424c4f434b3acd16772ad61a3c5f00287480b720f6035d5e54c9efc71be94bb5e3727f10909001200000000000000000000000000000000000000000000000000000000000000000000000000100000000010145310e878941a1b2bc2d33797ee4d89d95eaaf2e13488063a2aa9a74490f510a0100000023220020b6744de4f6ec63cc92f7c220cdefeeb1b1bed2b66c8e5706d80ec247d37e65a1ffffffff01002d3101000000001976a9143ebc40e411ed3c76f86711507ab952300890397288ac0400473044022001dd489a5d4e2fbd8a3ade27177f6b49296ba7695c40dbbe650ea83f106415fd02200b23a0602d8ff1bdf79dee118205fc7e9b40672bf31563e5741feb53fb86388501483045022100f88f040e90cc5dc6c6189d04718376ac19ed996bf9e4a3c29c3718d90ffd27180220761711f16c9e3a44f71aab55cbc0634907a1fa8bb635d971a9a01d368727bea10169522103b3623117e988b76aaabe3d63f56a4fc88b228a71e64c4cc551d1204822fe85cb2103dd823066e096f72ed617a41d3ca56717db335b1ea47a1b4c5c9dbdd0963acba621033d7c89bd9da29fa8d44db7906a9778b53121f72191184a9fee785c39180e4be153ae00000000010000000120925534261de4dcebb1ed5ab1b62bfe7a3ef968fb111dc2c910adfebc6e3bdf010000006b483045022100f50198f5ae66211a4f485190abe4dc7accdabe3bc214ebc9ea7069b97097d46e0220316a70a03014887086e335fc1b48358d46cd6bdc9af3b57c109c94af76fc915101210316cff587a01a2736d5e12e53551b18d73780b83c3bfb4fcf209c869b11b6415effffffff0220a10700000000001976a91450333046115eaa0ac9e0216565f945070e44573988ac2e7cd01a000000001976a914c01a7ca16b47be50cbdbc60724f701d52d75156688ac00000000010000000203a25f58630d7a1ea52550365fd2156683f56daf6ca73a4b4bbd097e66516322010000006a47304402204efc3d70e4ca3049c2a425025edf22d5ca355f9ec899dbfbbeeb2268533a0f2b02204780d3739653035af4814ea52e1396d021953f948c29754edd0ee537364603dc012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff03a25f58630d7a1ea52550365fd2156683f56daf6ca73a4b4bbd097e66516322000000006a47304402202d96defdc5b4af71d6ba28c9a6042c2d5ee7bc6de565d4db84ef517445626e03022022da80320e9e489c8f41b74833dfb6a54a4eb5087cdb46eb663eef0b25caa526012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff0200e1f5050000000017a914b7e6f7ff8658b2d1fb107e3d7be7af4742e6b1b3876f88fc00000000001976a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac0000000001000000043ffd60d3818431c495b89be84afac205d5d1ed663009291c560758bbd0a66df5010000006b483045022100f344607de9df42049688dcae8ff1db34c0c7cd25ec05516e30d2bc8f12ac9b2f022060b648f6a21745ea6d9782e17bcc4277b5808326488a1f40d41e125879723d3a012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffffa5379401cce30f84731ef1ba65ce27edf2cc7ce57704507ebe8714aa16a96b92010000006a473044022020c37a63bf4d7f564c2192528709b6a38ab8271bd96898c6c2e335e5208661580220435c6f1ad4d9305d2c0a818b2feb5e45d443f2f162c0f61953a14d097fd07064012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff70e731e193235ff12c3184510895731a099112ffca4b00246c60003c40f843ce000000006a473044022053760f74c29a879e30a17b5f03a5bb057a5751a39f86fa6ecdedc36a1b7db04c022041d41c9b95f00d2d10a0373322a9025dba66c942196bc9d8adeb0e12d3024728012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff66b7a71b3e50379c8e85fc18fe3f1a408fc985f257036c34702ba205cef09f6f000000006a4730440220499bf9e2db3db6e930228d0661395f65431acae466634d098612fd80b08459ee022040e069fc9e3c60009f521cef54c38aadbd1251aee37940e6018aadb10f194d6a012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff0200e1f5050000000017a9148fc37ad460fdfbd2b44fe446f6e3071a4f64faa6878f447f0b000000001976a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac00000000",["a914feb8a29635c56d9cd913122f90678756bf23887687","76a914c01a7ca16b47be50cbdbc60724f701d52d75156688ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac"],"8f13b9a9c85611635b47906c3053ac53cfcec7211455d4cb0d63dc9acc13d472","09027acea61b6cc3fb33f5d52f7d088a6b2f75d234e89ca800","546c574a0472144bcaf9b6aeabf26372ad87c7af7d1ee0dbfae5e099abeae49c","Duplicate pushdata 913bcc2be49cb534c20474c4dee1e9c4c317e7eb"], +[987876,"0000000000000c00901f2049055e2a437c819d79a3d54fd63e6af796cd7b8a79","000000202694f74969fdb542090e95a56bc8aa2d646e27033850e32f1c5f000000000000f7e53676b3f12d5beb524ed617f2d25f5a93b5f4f52c1ba2678260d72712f8dd0a6dfe5740257e1a4b1768960101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff1603e4120ff9c30a1c216900002f424d4920546573742fffffff0001205fa012000000001e76a914c486de584a735ec2f22da7cd9681614681f92173d83d0aa68688ac00000000",[],"fe4d230dbb0f4fec9bed23a5283e08baf996e3f32b93f52c7de1f641ddfd04ad","010c0b40","0965a544743bbfa36f254446e75630c09404b3d164a261892372977538928ed5","Coinbase tx has unparseable output script"], +[1263442,"000000006f27ddfe1dd680044a34548f41bed47eba9e6f0b310da21423bc5f33","000000201c8d1a529c39a396db2db234d5ec152fa651a2872966daccbde028b400000000083f14492679151dbfaa1a825ef4c18518e780c1f91044180280a7d33f4a98ff5f45765aaddc001d38333b9a02010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff230352471300fe5f45765afe94690a000963676d696e6572343208000000000000000000ffffffff024423a804000000001976a914f2c25ac3d59f3d674b1d1d0a25c27339aaac0ba688ac0000000000000000266a24aa21a9edcb26cb3052426b9ebb4d19c819ef87c19677bbf3a7c46ef0855bd1b2abe83491012000000000000000000000000000000000000000000000000000000000000000000000000002000000000101d20978463906ba4ff5e7192494b88dd5eb0de85d900ab253af909106faa22cc5010000000004000000014777ff000000000016001446c29eabe8208a33aa1023c741fa79aa92e881ff0347304402207d7ca96134f2bcfdd6b536536fdd39ad17793632016936f777ebb32c22943fda02206014d2fb8a6aa58279797f861042ba604ebd2f8f61e5bddbd9d3be5a245047b201004b632103eeaeba7ce5dc2470221e9517fb498e8d6bd4e73b85b8be655196972eb9ccd5566754b2752103a40b74d43df244799d041f32ce1ad515a6cd99501701540e38750d883ae21d3a68ac00000000",["002027a5000c7917f785d8fc6e5a55adfca8717ecb973ebb7743849ff956d896a7ed"],"31d66d516a9eda7de865df29f6ef6cb8e4bf9309e5dac899968a9a62a5df61e3","0385acb4f0fe889ef0","4e6d564c2a2452065c205dd7eb2791124e0c4e0dbb064c410c24968572589dec","Includes witness data"], +[1414221,"0000000000000027b2b3b3381f114f674f481544ff2be37ae3788d7e078383b1","000000204ea88307a7959d8207968f152bedca5a93aefab253f1fb2cfb032a400000000070cebb14ec6dbc27a9dfd066d9849a4d3bac5f674665f73a5fe1de01a022a0c851fda85bf05f4c19a779d1450102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff18034d94154d696e6572476174653030310d000000f238f401ffffffff01c817a804000000000000000000",[],"5e5e12d90693c8e936f01847859404c67482439681928353ca1296982042864e","00","021e8882ef5a0ed932edeebbecfeda1d7ce528ec7b3daa27641acf1189d7b5dc","Empty data"] +] diff --git a/src/test/data/key_io_invalid.json b/src/test/data/key_io_invalid.json index 2056c7491c..9b52943ac6 100644 --- a/src/test/data/key_io_invalid.json +++ b/src/test/data/key_io_invalid.json @@ -1,151 +1,151 @@ [ [ "" - ], + ], [ "x" - ], + ], [ "37qgekLpCCHrQuSjvX3fs496FWTGsHFHizjJAs6NPcR47aefnnCWECAhHV6E3g4YN7u7Yuwod5Y" - ], + ], [ "dzb7VV1Ui55BARxv7ATxAtCUeJsANKovDGWFVgpTbhq9gvPqP3yv" - ], + ], [ "MuNu7ZAEDFiHthiunm7dPjwKqrVNCM3mAz6rP9zFveQu14YA8CxExSJTHcVP9DErn6u84E6Ej7S" - ], + ], [ "rPpQpYknyNQ5AEHuY6H8ijJJrYc2nDKKk9jjmKEXsWzyAQcFGpDLU2Zvsmoi8JLR7hAwoy3RQWf" - ], + ], [ "4Uc3FmN6NQ6zLBK5QQBXRBUREaaHwCZYsGCueHauuDmJpZKn6jkEskMB2Zi2CNgtb5r6epWEFfUJq" - ], + ], [ "7aQgR5DFQ25vyXmqZAWmnVCjL3PkBcdVkBUpjrjMTcghHx3E8wb" - ], + ], [ "17QpPprjeg69fW1DV8DcYYCKvWjYhXvWkov6MJ1iTTvMFj6weAqW7wybZeH57WTNxXVCRH4veVs" - ], + ], [ "KxuACDviz8Xvpn1xAh9MfopySZNuyajYMZWz16Dv2mHHryznWUp3" - ], + ], [ "7nK3GSmqdXJQtdohvGfJ7KsSmn3TmGqExug49583bDAL91pVSGq5xS9SHoAYL3Wv3ijKTit65th" - ], + ], [ "cTivdBmq7bay3RFGEBBuNfMh2P1pDCgRYN2Wbxmgwr4ki3jNUL2va" - ], + ], [ "gjMV4vjNjyMrna4fsAr8bWxAbwtmMUBXJS3zL4NJt5qjozpbQLmAfK1uA3CquSqsZQMpoD1g2nk" - ], + ], [ "emXm1naBMoVzPjbk7xpeTVMFy4oDEe25UmoyGgKEB1gGWsK8kRGs" - ], + ], [ "7VThQnNRj1o3Zyvc7XHPRrjDf8j2oivPTeDXnRPYWeYGE4pXeRJDZgf28ppti5hsHWXS2GSobdqyo" - ], + ], [ "1G9u6oCVCPh2o8m3t55ACiYvG1y5BHewUkDSdiQarDcYXXhFHYdzMdYfUAhfxn5vNZBwpgUNpso" - ], + ], [ "31QQ7ZMLkScDiB4VyZjuptr7AEc9j1SjstF7pRoLhHTGkW4Q2y9XELobQmhhWxeRvqcukGd1XCq" - ], + ], [ "DHqKSnpxa8ZdQyH8keAhvLTrfkyBMQxqngcQA5N8LQ9KVt25kmGN" - ], + ], [ "2LUHcJPbwLCy9GLH1qXmfmAwvadWw4bp4PCpDfduLqV17s6iDcy1imUwhQJhAoNoN1XNmweiJP4i" - ], + ], [ "7USRzBXAnmck8fX9HmW7RAb4qt92VFX6soCnts9s74wxm4gguVhtG5of8fZGbNPJA83irHVY6bCos" - ], + ], [ "1DGezo7BfVebZxAbNT3XGujdeHyNNBF3vnficYoTSp4PfK2QaML9bHzAMxke3wdKdHYWmsMTJVu" - ], + ], [ "2D12DqDZKwCxxkzs1ZATJWvgJGhQ4cFi3WrizQ5zLAyhN5HxuAJ1yMYaJp8GuYsTLLxTAz6otCfb" - ], + ], [ "8AFJzuTujXjw1Z6M3fWhQ1ujDW7zsV4ePeVjVo7D1egERqSW9nZ" - ], + ], [ "163Q17qLbTCue8YY3AvjpUhotuaodLm2uqMhpYirsKjVqnxJRWTEoywMVY3NbBAHuhAJ2cF9GAZ" - ], + ], [ "2MnmgiRH4eGLyLc9eAqStzk7dFgBjFtUCtu" - ], + ], [ "461QQ2sYWxU7H2PV4oBwJGNch8XVTYYbZxU" - ], + ], [ "2UCtv53VttmQYkVU4VMtXB31REvQg4ABzs41AEKZ8UcB7DAfVzdkV9JDErwGwyj5AUHLkmgZeobs" - ], + ], [ "cSNjAsnhgtiFMi6MtfvgscMB2Cbhn2v1FUYfviJ1CdjfidvmeW6mn" - ], + ], [ "gmsow2Y6EWAFDFE1CE4Hd3Tpu2BvfmBfG1SXsuRARbnt1WjkZnFh1qGTiptWWbjsq2Q6qvpgJVj" - ], + ], [ "nksUKSkzS76v8EsSgozXGMoQFiCoCHzCVajFKAXqzK5on9ZJYVHMD5CKwgmX3S3c7M1U3xabUny" - ], + ], [ "L3favK1UzFGgdzYBF2oBT5tbayCo4vtVBLJhg2iYuMeePxWG8SQc" - ], + ], [ "7VxLxGGtYT6N99GdEfi6xz56xdQ8nP2dG1CavuXx7Rf2PrvNMTBNevjkfgs9JmkcGm6EXpj8ipyPZ" - ], + ], [ "2mbZwFXF6cxShaCo2czTRB62WTx9LxhTtpP" - ], + ], [ "dB7cwYdcPSgiyAwKWL3JwCVwSk6epU2txw" - ], + ], [ "HPhFUhUAh8ZQQisH8QQWafAxtQYju3SFTX" - ], + ], [ "4ctAH6AkHzq5ioiM1m9T3E2hiYEev5mTsB" - ], + ], [ "Hn1uFi4dNexWrqARpjMqgT6cX1UsNPuV3cHdGg9ExyXw8HTKadbktRDtdeVmY3M1BxJStiL4vjJ" - ], + ], [ "Sq3fDbvutABmnAHHExJDgPLQn44KnNC7UsXuT7KZecpaYDMU9Txs" - ], + ], [ "6TqWyrqdgUEYDQU1aChMuFMMEimHX44qHFzCUgGfqxGgZNMUVWJ" - ], + ], [ "giqJo7oWqFxNKWyrgcBxAVHXnjJ1t6cGoEffce5Y1y7u649Noj5wJ4mmiUAKEVVrYAGg2KPB3Y4" - ], + ], [ "cNzHY5e8vcmM3QVJUcjCyiKMYfeYvyueq5qCMV3kqcySoLyGLYUK" - ], + ], [ "37uTe568EYc9WLoHEd9jXEvUiWbq5LFLscNyqvAzLU5vBArUJA6eydkLmnMwJDjkL5kXc2VK7ig" - ], + ], [ "EsYbG4tWWWY45G31nox838qNdzksbPySWc" - ], + ], [ "nbuzhfwMoNzA3PaFnyLcRxE9bTJPDkjZ6Rf6Y6o2ckXZfzZzXBT" - ], + ], [ "cQN9PoxZeCWK1x56xnz6QYAsvR11XAce3Ehp3gMUdfSQ53Y2mPzx" - ], + ], [ "1Gm3N3rkef6iMbx4voBzaxtXcmmiMTqZPhcuAepRzYUJQW4qRpEnHvMojzof42hjFRf8PE2jPde" - ], + ], [ "2TAq2tuN6x6m233bpT7yqdYQPELdTDJn1eU" - ], + ], [ "ntEtnnGhqPii4joABvBtSEJG6BxjT2tUZqE8PcVYgk3RHpgxgHDCQxNbLJf7ardf1dDk2oCQ7Cf" - ], + ], [ "Ky1YjoZNgQ196HJV3HpdkecfhRBmRZdMJk89Hi5KGfpfPwS2bUbfd" - ], + ], [ "2A1q1YsMZowabbvta7kTy2Fd6qN4r5ZCeG3qLpvZBMzCixMUdkN2Y4dHB1wPsZAeVXUGD83MfRED" ], diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index 97edc98bf6..9b320b6943 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -712,7 +712,7 @@ ["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Zero-length R is correctly encoded"], ["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "", "OK", "Zero-length S is correctly encoded for DERSIG"], ["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Negative S is correctly encoded"], - + ["2147483648", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "OK", "CSV passes if stack top bit 1 << 31 is set"], ["", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "Test the test: we should have an empty stack after scriptSig evaluation"], diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json index 918df6d8d9..d22175d660 100644 --- a/src/test/data/tx_invalid.json +++ b/src/test/data/tx_invalid.json @@ -363,7 +363,7 @@ "010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a483045022100fa4a74ba9fd59c59f46c3960cf90cbe0d2b743c471d24a3d5d6db6002af5eebb02204d70ec490fd0f7055a7c45f86514336e3a7f03503dacecabb247fc23f15c83510151ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"], -["Using CHECKSIG with singatures in scriptSigs will trigger FindAndDelete, which is invalid"], +["Using CHECKSIG with signatures in scriptSigs will trigger FindAndDelete, which is invalid"], [[["ccf7f4053a02e653c36ac75c891b7496d0dc5ce5214f6c913d9cf8f1329ebee0", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], "0100000001e0be9e32f1f89c3d916c4f21e55cdcd096741b895cc76ac353e6023a05f4f7cc00000000d86149304602210086e5f736a2c3622ebb62bd9d93d8e5d76508b98be922b97160edc3dcca6d8c47022100b23c312ac232a4473f19d2aeb95ab7bdf2b65518911a0d72d50e38b5dd31dc820121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac4730440220508fa761865c8abd81244a168392876ee1d94e8ed83897066b5e2df2400dad24022043f5ee7538e87e9c6aef7ef55133d3e51da7cc522830a9c4d736977a76ef755c0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"], diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index 6df5aec9c9..0bde92c18d 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -1,11 +1,11 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <dbwrapper.h> #include <uint256.h> #include <random.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <memory> @@ -20,14 +20,14 @@ static bool is_null_key(const std::vector<unsigned char>& key) { return isnull; } - + BOOST_FIXTURE_TEST_SUITE(dbwrapper_tests, BasicTestingSetup) - + BOOST_AUTO_TEST_CASE(dbwrapper) { // Perform tests both obfuscated and non-obfuscated. - for (bool obfuscate : {false, true}) { - fs::path ph = fs::temp_directory_path() / fs::unique_path(); + for (const bool obfuscate : {false, true}) { + fs::path ph = SetDataDir(std::string("dbwrapper").append(obfuscate ? "_true" : "_false")); CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); char key = 'k'; uint256 in = InsecureRand256(); @@ -46,8 +46,8 @@ BOOST_AUTO_TEST_CASE(dbwrapper) BOOST_AUTO_TEST_CASE(dbwrapper_batch) { // Perform tests both obfuscated and non-obfuscated. - for (bool obfuscate : {false, true}) { - fs::path ph = fs::temp_directory_path() / fs::unique_path(); + for (const bool obfuscate : {false, true}) { + fs::path ph = SetDataDir(std::string("dbwrapper_batch").append(obfuscate ? "_true" : "_false")); CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); char key = 'i'; @@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_batch) // Remove key3 before it's even been written batch.Erase(key3); - dbw.WriteBatch(batch); + BOOST_CHECK(dbw.WriteBatch(batch)); BOOST_CHECK(dbw.Read(key, res)); BOOST_CHECK_EQUAL(res.ToString(), in.ToString()); @@ -82,8 +82,8 @@ BOOST_AUTO_TEST_CASE(dbwrapper_batch) BOOST_AUTO_TEST_CASE(dbwrapper_iterator) { // Perform tests both obfuscated and non-obfuscated. - for (bool obfuscate : {false, true}) { - fs::path ph = fs::temp_directory_path() / fs::unique_path(); + for (const bool obfuscate : {false, true}) { + fs::path ph = SetDataDir(std::string("dbwrapper_iterator").append(obfuscate ? "_true" : "_false")); CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); // The two keys are intentionally chosen for ordering @@ -102,15 +102,15 @@ BOOST_AUTO_TEST_CASE(dbwrapper_iterator) char key_res; uint256 val_res; - it->GetKey(key_res); - it->GetValue(val_res); + BOOST_REQUIRE(it->GetKey(key_res)); + BOOST_REQUIRE(it->GetValue(val_res)); BOOST_CHECK_EQUAL(key_res, key); BOOST_CHECK_EQUAL(val_res.ToString(), in.ToString()); it->Next(); - it->GetKey(key_res); - it->GetValue(val_res); + BOOST_REQUIRE(it->GetKey(key_res)); + BOOST_REQUIRE(it->GetValue(val_res)); BOOST_CHECK_EQUAL(key_res, key2); BOOST_CHECK_EQUAL(val_res.ToString(), in2.ToString()); @@ -123,7 +123,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_iterator) BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) { // We're going to share this fs::path between two wrappers - fs::path ph = fs::temp_directory_path() / fs::unique_path(); + fs::path ph = SetDataDir("existing_data_no_obfuscate"); create_directories(ph); // Set up a non-obfuscated wrapper to write some initial data. @@ -142,7 +142,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) // Now, set up another wrapper that wants to obfuscate the same directory CDBWrapper odbw(ph, (1 << 10), false, false, true); - // Check that the key/val we wrote with unobfuscated wrapper exists and + // Check that the key/val we wrote with unobfuscated wrapper exists and // is readable. uint256 res2; BOOST_CHECK(odbw.Read(key, res2)); @@ -153,18 +153,18 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) uint256 in2 = InsecureRand256(); uint256 res3; - + // Check that we can write successfully BOOST_CHECK(odbw.Write(key, in2)); BOOST_CHECK(odbw.Read(key, res3)); BOOST_CHECK_EQUAL(res3.ToString(), in2.ToString()); } - + // Ensure that we start obfuscating during a reindex. BOOST_AUTO_TEST_CASE(existing_data_reindex) { // We're going to share this fs::path between two wrappers - fs::path ph = fs::temp_directory_path() / fs::unique_path(); + fs::path ph = SetDataDir("existing_data_reindex"); create_directories(ph); // Set up a non-obfuscated wrapper to write some initial data. @@ -190,7 +190,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex) uint256 in2 = InsecureRand256(); uint256 res3; - + // Check that we can write successfully BOOST_CHECK(odbw.Write(key, in2)); BOOST_CHECK(odbw.Read(key, res3)); @@ -199,7 +199,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex) BOOST_AUTO_TEST_CASE(iterator_ordering) { - fs::path ph = fs::temp_directory_path() / fs::unique_path(); + fs::path ph = SetDataDir("iterator_ordering"); CDBWrapper dbw(ph, (1 << 20), true, false, false); for (int x=0x00; x<256; ++x) { uint8_t key = x; @@ -216,7 +216,7 @@ BOOST_AUTO_TEST_CASE(iterator_ordering) if (x & 1) BOOST_CHECK(dbw.Write(key, value)); } - for (int seek_start : {0x00, 0x80}) { + for (const int seek_start : {0x00, 0x80}) { it->Seek((uint8_t)seek_start); for (unsigned int x=seek_start; x<255; ++x) { uint8_t key; @@ -262,7 +262,7 @@ struct StringContentsSerializer { try { READWRITE(c); str.push_back(c); - } catch (const std::ios_base::failure& e) { + } catch (const std::ios_base::failure&) { break; } } @@ -277,7 +277,7 @@ BOOST_AUTO_TEST_CASE(iterator_string_ordering) { char buf[10]; - fs::path ph = fs::temp_directory_path() / fs::unique_path(); + fs::path ph = SetDataDir("iterator_string_ordering"); CDBWrapper dbw(ph, (1 << 20), true, false, false); for (int x=0x00; x<10; ++x) { for (int y = 0; y < 10; y++) { @@ -291,7 +291,7 @@ BOOST_AUTO_TEST_CASE(iterator_string_ordering) } std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper&>(dbw).NewIterator()); - for (int seek_start : {0, 5}) { + for (const 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/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index bebbd6c464..d47f395c15 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -1,9 +1,10 @@ -// Copyright (c) 2011-2017 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. // Unit tests for denial-of-service detection/prevention code +#include <banman.h> #include <chainparams.h> #include <keystore.h> #include <net.h> @@ -11,25 +12,45 @@ #include <pow.h> #include <script/sign.h> #include <serialize.h> -#include <util.h> +#include <util/system.h> #include <validation.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <stdint.h> #include <boost/test/unit_test.hpp> +struct CConnmanTest : public CConnman { + using CConnman::CConnman; + void AddNode(CNode& node) + { + LOCK(cs_vNodes); + vNodes.push_back(&node); + } + void ClearNodes() + { + LOCK(cs_vNodes); + for (CNode* node : vNodes) { + delete node; + } + vNodes.clear(); + } +}; + // Tests these internal-to-net_processing.cpp methods: extern bool AddOrphanTx(const CTransactionRef& tx, NodeId peer); extern void EraseOrphansFor(NodeId peer); extern unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans); +extern void Misbehaving(NodeId nodeid, int howmuch, const std::string& message=""); + struct COrphanTx { CTransactionRef tx; NodeId fromPeer; int64_t nTimeExpire; }; -extern std::map<uint256, COrphanTx> mapOrphanTransactions; +extern CCriticalSection g_cs_orphans; +extern std::map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(g_cs_orphans); static CService ip(uint32_t i) { @@ -54,7 +75,8 @@ BOOST_FIXTURE_TEST_SUITE(denialofservice_tests, TestingSetup) // work. BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) { - std::atomic<bool> interruptDummy(false); + auto connman = MakeUnique<CConnman>(0x1337, 0x1337); + auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, scheduler, false); // Mock an outbound peer CAddress addr1(ip(0xa0b0c001), NODE_NONE); @@ -68,14 +90,14 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) // This test requires that we have a chain with non-zero work. { LOCK(cs_main); - BOOST_CHECK(chainActive.Tip() != nullptr); - BOOST_CHECK(chainActive.Tip()->nChainWork > 0); + BOOST_CHECK(::ChainActive().Tip() != nullptr); + BOOST_CHECK(::ChainActive().Tip()->nChainWork > 0); } // Test starts here { LOCK2(cs_main, dummyNode1.cs_sendProcessing); - peerLogic->SendMessages(&dummyNode1, interruptDummy); // should result in getheaders + BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in getheaders } { LOCK2(cs_main, dummyNode1.cs_vSend); @@ -88,7 +110,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) SetMockTime(nStartTime+21*60); { LOCK2(cs_main, dummyNode1.cs_sendProcessing); - peerLogic->SendMessages(&dummyNode1, interruptDummy); // should result in getheaders + BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in getheaders } { LOCK2(cs_main, dummyNode1.cs_vSend); @@ -98,7 +120,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) SetMockTime(nStartTime+24*60); { LOCK2(cs_main, dummyNode1.cs_sendProcessing); - peerLogic->SendMessages(&dummyNode1, interruptDummy); // should result in disconnect + BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in disconnect } BOOST_CHECK(dummyNode1.fDisconnect == true); SetMockTime(0); @@ -107,9 +129,9 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) peerLogic->FinalizeNode(dummyNode1.GetId(), dummy); } -static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidation &peerLogic) +static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidation &peerLogic, CConnmanTest* connman) { - CAddress addr(ip(GetRandInt(0xffffffff)), NODE_NONE); + CAddress addr(ip(g_insecure_rand_ctx.randbits(32)), NODE_NONE); vNodes.emplace_back(new CNode(id++, ServiceFlags(NODE_NETWORK|NODE_WITNESS), 0, INVALID_SOCKET, addr, 0, 0, CAddress(), "", /*fInboundIn=*/ false)); CNode &node = *vNodes.back(); node.SetSendVersion(PROTOCOL_VERSION); @@ -118,11 +140,14 @@ static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidat node.nVersion = 1; node.fSuccessfullyConnected = true; - CConnmanTest::AddNode(node); + connman->AddNode(node); } BOOST_AUTO_TEST_CASE(stale_tip_peer_management) { + auto connman = MakeUnique<CConnmanTest>(0x1337, 0x1337); + auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, scheduler, false); + const Consensus::Params& consensusParams = Params().GetConsensus(); constexpr int nMaxOutbound = 8; CConnman::Options options; @@ -135,7 +160,7 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management) // Mock some outbound peers for (int i=0; i<nMaxOutbound; ++i) { - AddRandomOutboundPeer(vNodes, *peerLogic); + AddRandomOutboundPeer(vNodes, *peerLogic, connman.get()); } peerLogic->CheckForStaleTipAndEvictPeers(consensusParams); @@ -160,7 +185,7 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management) // If we add one more peer, something should get marked for eviction // on the next check (since we're mocking the time to be in the future, the // required time connected check should be satisfied). - AddRandomOutboundPeer(vNodes, *peerLogic); + AddRandomOutboundPeer(vNodes, *peerLogic, connman.get()); peerLogic->CheckForStaleTipAndEvictPeers(consensusParams); for (int i=0; i<nMaxOutbound; ++i) { @@ -187,14 +212,16 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management) peerLogic->FinalizeNode(node->GetId(), dummy); } - CConnmanTest::ClearNodes(); + connman->ClearNodes(); } BOOST_AUTO_TEST_CASE(DoS_banning) { - std::atomic<bool> interruptDummy(false); + auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); + auto connman = MakeUnique<CConnman>(0x1337, 0x1337); + auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler, false); - connman->ClearBanned(); + banman->ClearBanned(); CAddress addr1(ip(0xa0b0c001), NODE_NONE); CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", true); dummyNode1.SetSendVersion(PROTOCOL_VERSION); @@ -207,10 +234,10 @@ BOOST_AUTO_TEST_CASE(DoS_banning) } { LOCK2(cs_main, dummyNode1.cs_sendProcessing); - peerLogic->SendMessages(&dummyNode1, interruptDummy); + BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); } - BOOST_CHECK(connman->IsBanned(addr1)); - BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned + BOOST_CHECK(banman->IsBanned(addr1)); + BOOST_CHECK(!banman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned CAddress addr2(ip(0xa0b0c002), NODE_NONE); CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, 1, CAddress(), "", true); @@ -224,19 +251,19 @@ BOOST_AUTO_TEST_CASE(DoS_banning) } { LOCK2(cs_main, dummyNode2.cs_sendProcessing); - peerLogic->SendMessages(&dummyNode2, interruptDummy); + BOOST_CHECK(peerLogic->SendMessages(&dummyNode2)); } - BOOST_CHECK(!connman->IsBanned(addr2)); // 2 not banned yet... - BOOST_CHECK(connman->IsBanned(addr1)); // ... but 1 still should be + BOOST_CHECK(!banman->IsBanned(addr2)); // 2 not banned yet... + BOOST_CHECK(banman->IsBanned(addr1)); // ... but 1 still should be { LOCK(cs_main); Misbehaving(dummyNode2.GetId(), 50); } { LOCK2(cs_main, dummyNode2.cs_sendProcessing); - peerLogic->SendMessages(&dummyNode2, interruptDummy); + BOOST_CHECK(peerLogic->SendMessages(&dummyNode2)); } - BOOST_CHECK(connman->IsBanned(addr2)); + BOOST_CHECK(banman->IsBanned(addr2)); bool dummy; peerLogic->FinalizeNode(dummyNode1.GetId(), dummy); @@ -245,9 +272,11 @@ BOOST_AUTO_TEST_CASE(DoS_banning) BOOST_AUTO_TEST_CASE(DoS_banscore) { - std::atomic<bool> interruptDummy(false); + auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); + auto connman = MakeUnique<CConnman>(0x1337, 0x1337); + auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler, false); - connman->ClearBanned(); + banman->ClearBanned(); gArgs.ForceSetArg("-banscore", "111"); // because 11 is my favorite number CAddress addr1(ip(0xa0b0c001), NODE_NONE); CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 3, 1, CAddress(), "", true); @@ -261,27 +290,27 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) } { LOCK2(cs_main, dummyNode1.cs_sendProcessing); - peerLogic->SendMessages(&dummyNode1, interruptDummy); + BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); } - BOOST_CHECK(!connman->IsBanned(addr1)); + BOOST_CHECK(!banman->IsBanned(addr1)); { LOCK(cs_main); Misbehaving(dummyNode1.GetId(), 10); } { LOCK2(cs_main, dummyNode1.cs_sendProcessing); - peerLogic->SendMessages(&dummyNode1, interruptDummy); + BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); } - BOOST_CHECK(!connman->IsBanned(addr1)); + BOOST_CHECK(!banman->IsBanned(addr1)); { LOCK(cs_main); Misbehaving(dummyNode1.GetId(), 1); } { LOCK2(cs_main, dummyNode1.cs_sendProcessing); - peerLogic->SendMessages(&dummyNode1, interruptDummy); + BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); } - BOOST_CHECK(connman->IsBanned(addr1)); + BOOST_CHECK(banman->IsBanned(addr1)); gArgs.ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD)); bool dummy; @@ -290,9 +319,11 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) BOOST_AUTO_TEST_CASE(DoS_bantime) { - std::atomic<bool> interruptDummy(false); + auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); + auto connman = MakeUnique<CConnman>(0x1337, 0x1337); + auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler, false); - connman->ClearBanned(); + banman->ClearBanned(); int64_t nStartTime = GetTime(); SetMockTime(nStartTime); // Overrides future calls to GetTime() @@ -309,15 +340,15 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) } { LOCK2(cs_main, dummyNode.cs_sendProcessing); - peerLogic->SendMessages(&dummyNode, interruptDummy); + BOOST_CHECK(peerLogic->SendMessages(&dummyNode)); } - BOOST_CHECK(connman->IsBanned(addr)); + BOOST_CHECK(banman->IsBanned(addr)); SetMockTime(nStartTime+60*60); - BOOST_CHECK(connman->IsBanned(addr)); + BOOST_CHECK(banman->IsBanned(addr)); SetMockTime(nStartTime+60*60*24+1); - BOOST_CHECK(!connman->IsBanned(addr)); + BOOST_CHECK(!banman->IsBanned(addr)); bool dummy; peerLogic->FinalizeNode(dummyNode.GetId(), dummy); @@ -326,7 +357,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) static CTransactionRef RandomOrphan() { std::map<uint256, COrphanTx>::iterator it; - LOCK(cs_main); + LOCK2(cs_main, g_cs_orphans); it = mapOrphanTransactions.lower_bound(InsecureRand256()); if (it == mapOrphanTransactions.end()) it = mapOrphanTransactions.begin(); @@ -338,7 +369,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) CKey key; key.MakeNewKey(true); CBasicKeyStore keystore; - keystore.AddKey(key); + BOOST_CHECK(keystore.AddKey(key)); // 50 orphan transactions: for (int i = 0; i < 50; i++) @@ -350,7 +381,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) tx.vin[0].scriptSig << OP_1; tx.vout.resize(1); tx.vout[0].nValue = 1*CENT; - tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID()); + tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey())); AddOrphanTx(MakeTransactionRef(tx), i); } @@ -366,8 +397,8 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) tx.vin[0].prevout.hash = txPrev->GetHash(); tx.vout.resize(1); tx.vout[0].nValue = 1*CENT; - tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID()); - SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL); + tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey())); + BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL)); AddOrphanTx(MakeTransactionRef(tx), i); } @@ -380,14 +411,14 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) CMutableTransaction tx; tx.vout.resize(1); tx.vout[0].nValue = 1*CENT; - tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID()); + tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey())); tx.vin.resize(2777); for (unsigned int j = 0; j < tx.vin.size(); j++) { tx.vin[j].prevout.n = j; tx.vin[j].prevout.hash = txPrev->GetHash(); } - SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL); + BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL)); // Re-use same signature for other inputs // (they don't have to be valid for this test) for (unsigned int j = 1; j < tx.vin.size(); j++) @@ -396,7 +427,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) BOOST_CHECK(!AddOrphanTx(MakeTransactionRef(tx), i)); } - LOCK(cs_main); + LOCK2(cs_main, g_cs_orphans); // Test EraseOrphansFor: for (NodeId i = 0; i < 3; i++) { diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp new file mode 100644 index 0000000000..f5bda7d5e6 --- /dev/null +++ b/src/test/descriptor_tests.cpp @@ -0,0 +1,237 @@ +// Copyright (c) 2018-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <vector> +#include <string> +#include <script/sign.h> +#include <script/standard.h> +#include <test/setup_common.h> +#include <boost/test/unit_test.hpp> +#include <script/descriptor.h> +#include <util/strencodings.h> + +namespace { + +void CheckUnparsable(const std::string& prv, const std::string& pub) +{ + FlatSigningProvider keys_priv, keys_pub; + auto parse_priv = Parse(prv, keys_priv); + auto parse_pub = Parse(pub, keys_pub); + BOOST_CHECK_MESSAGE(!parse_priv, prv); + BOOST_CHECK_MESSAGE(!parse_pub, pub); +} + +constexpr int DEFAULT = 0; +constexpr int RANGE = 1; // Expected to be ranged descriptor +constexpr int HARDENED = 2; // Derivation needs access to private keys +constexpr int UNSOLVABLE = 4; // This descriptor is not expected to be solvable +constexpr int SIGNABLE = 8; // We can sign with this descriptor (this is not true when actual BIP32 derivation is used, as that's not integrated in our signing code) + +/** Compare two descriptors. If only one of them has a checksum, the checksum is ignored. */ +bool EqualDescriptor(std::string a, std::string b) +{ + bool a_check = (a.size() > 9 && a[a.size() - 9] == '#'); + bool b_check = (b.size() > 9 && b[b.size() - 9] == '#'); + if (a_check != b_check) { + if (a_check) a = a.substr(0, a.size() - 9); + if (b_check) b = b.substr(0, b.size() - 9); + } + return a == b; +} + +std::string MaybeUseHInsteadOfApostrophy(std::string ret) +{ + if (InsecureRandBool()) { + while (true) { + auto it = ret.find("'"); + if (it != std::string::npos) { + ret[it] = 'h'; + if (ret.size() > 9 && ret[ret.size() - 9] == '#') ret = ret.substr(0, ret.size() - 9); // Changing apostrophe to h breaks the checksum + } else { + break; + } + } + } + return ret; +} + +const std::set<std::vector<uint32_t>> ONLY_EMPTY{{}}; + +void Check(const std::string& prv, const std::string& pub, int flags, const std::vector<std::vector<std::string>>& scripts, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY) +{ + FlatSigningProvider keys_priv, keys_pub; + std::set<std::vector<uint32_t>> left_paths = paths; + + // Check that parsing succeeds. + auto parse_priv = Parse(MaybeUseHInsteadOfApostrophy(prv), keys_priv); + auto parse_pub = Parse(MaybeUseHInsteadOfApostrophy(pub), keys_pub); + BOOST_CHECK(parse_priv); + BOOST_CHECK(parse_pub); + + // Check private keys are extracted from the private version but not the public one. + BOOST_CHECK(keys_priv.keys.size()); + BOOST_CHECK(!keys_pub.keys.size()); + + // Check that both versions serialize back to the public version. + std::string pub1 = parse_priv->ToString(); + std::string pub2 = parse_pub->ToString(); + BOOST_CHECK(EqualDescriptor(pub, pub1)); + BOOST_CHECK(EqualDescriptor(pub, pub2)); + + // Check that both can be serialized with private key back to the private version, but not without private key. + std::string prv1; + BOOST_CHECK(parse_priv->ToPrivateString(keys_priv, prv1)); + BOOST_CHECK(EqualDescriptor(prv, prv1)); + BOOST_CHECK(!parse_priv->ToPrivateString(keys_pub, prv1)); + BOOST_CHECK(parse_pub->ToPrivateString(keys_priv, prv1)); + BOOST_CHECK(EqualDescriptor(prv, prv1)); + BOOST_CHECK(!parse_pub->ToPrivateString(keys_pub, prv1)); + + // Check whether IsRange on both returns the expected result + BOOST_CHECK_EQUAL(parse_pub->IsRange(), (flags & RANGE) != 0); + BOOST_CHECK_EQUAL(parse_priv->IsRange(), (flags & RANGE) != 0); + + // * For ranged descriptors, the `scripts` parameter is a list of expected result outputs, for subsequent + // positions to evaluate the descriptors on (so the first element of `scripts` is for evaluating the + // descriptor at 0; the second at 1; and so on). To verify this, we evaluate the descriptors once for + // each element in `scripts`. + // * For non-ranged descriptors, we evaluate the descriptors at positions 0, 1, and 2, but expect the + // same result in each case, namely the first element of `scripts`. Because of that, the size of + // `scripts` must be one in that case. + if (!(flags & RANGE)) assert(scripts.size() == 1); + size_t max = (flags & RANGE) ? scripts.size() : 3; + + // Iterate over the position we'll evaluate the descriptors in. + for (size_t i = 0; i < max; ++i) { + // Call the expected result scripts `ref`. + const auto& ref = scripts[(flags & RANGE) ? i : 0]; + // When t=0, evaluate the `prv` descriptor; when t=1, evaluate the `pub` descriptor. + for (int t = 0; t < 2; ++t) { + // When the descriptor is hardened, evaluate with access to the private keys inside. + const FlatSigningProvider& key_provider = (flags & HARDENED) ? keys_priv : keys_pub; + + // Evaluate the descriptor selected by `t` in poisition `i`. + FlatSigningProvider script_provider, script_provider_cached; + std::vector<CScript> spks, spks_cached; + std::vector<unsigned char> cache; + BOOST_CHECK((t ? parse_priv : parse_pub)->Expand(i, key_provider, spks, script_provider, &cache)); + + // Compare the output with the expected result. + BOOST_CHECK_EQUAL(spks.size(), ref.size()); + + // Try to expand again using cached data, and compare. + BOOST_CHECK(parse_pub->ExpandFromCache(i, cache, spks_cached, script_provider_cached)); + BOOST_CHECK(spks == spks_cached); + BOOST_CHECK(script_provider.pubkeys == script_provider_cached.pubkeys); + BOOST_CHECK(script_provider.scripts == script_provider_cached.scripts); + BOOST_CHECK(script_provider.origins == script_provider_cached.origins); + + // For each of the produced scripts, verify solvability, and when possible, try to sign a transaction spending it. + for (size_t n = 0; n < spks.size(); ++n) { + BOOST_CHECK_EQUAL(ref[n], HexStr(spks[n].begin(), spks[n].end())); + BOOST_CHECK_EQUAL(IsSolvable(Merge(key_provider, script_provider), spks[n]), (flags & UNSOLVABLE) == 0); + + if (flags & SIGNABLE) { + CMutableTransaction spend; + spend.vin.resize(1); + spend.vout.resize(1); + BOOST_CHECK_MESSAGE(SignSignature(Merge(keys_priv, script_provider), spks[n], spend, 0, 1, SIGHASH_ALL), prv); + } + + /* Infer a descriptor from the generated script, and verify its solvability and that it roundtrips. */ + auto inferred = InferDescriptor(spks[n], script_provider); + BOOST_CHECK_EQUAL(inferred->IsSolvable(), !(flags & UNSOLVABLE)); + std::vector<CScript> spks_inferred; + FlatSigningProvider provider_inferred; + BOOST_CHECK(inferred->Expand(0, provider_inferred, spks_inferred, provider_inferred)); + BOOST_CHECK_EQUAL(spks_inferred.size(), 1); + BOOST_CHECK(spks_inferred[0] == spks[n]); + BOOST_CHECK_EQUAL(IsSolvable(provider_inferred, spks_inferred[0]), !(flags & UNSOLVABLE)); + BOOST_CHECK(provider_inferred.origins == script_provider.origins); + } + + // Test whether the observed key path is present in the 'paths' variable (which contains expected, unobserved paths), + // and then remove it from that set. + for (const auto& origin : script_provider.origins) { + BOOST_CHECK_MESSAGE(paths.count(origin.second.second.path), "Unexpected key path: " + prv); + left_paths.erase(origin.second.second.path); + } + } + } + + // Verify no expected paths remain that were not observed. + BOOST_CHECK_MESSAGE(left_paths.empty(), "Not all expected key paths found: " + prv); +} + +} + +BOOST_FIXTURE_TEST_SUITE(descriptor_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(descriptor_test) +{ + // Basic single-key compressed + Check("combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac","76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac","00149a1c78a507689f6f54b847ad1cef1e614ee23f1e","a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}}); + Check("pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac"}}); + Check("pkh([deadbeef/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh([deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac"}}, {{1,0x80000002UL,3,0x80000004UL}}); + Check("wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"00149a1c78a507689f6f54b847ad1cef1e614ee23f1e"}}); + Check("sh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}}); + + // Basic single-key uncompressed + Check("combo(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac","76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}}); + Check("pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac"}}); + Check("pkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}}); + CheckUnparsable("wpkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "wpkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)"); // No uncompressed keys in witness + CheckUnparsable("wsh(pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss))", "wsh(pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235))"); // No uncompressed keys in witness + CheckUnparsable("sh(wpkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss))", "sh(wpkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235))"); // No uncompressed keys in witness + + // Some unconventional single-key constructions + Check("sh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a9141857af51a5e516552b3086430fd8ce55f7c1a52487"}}); + Check("sh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a9141a31ad23bf49c247dd531a623c2ef57da3c400c587"}}); + Check("wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"00202e271faa2325c199d25d22e1ead982e45b64eeb4f31e73dbdf41bd4b5fec23fa"}}); + Check("wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"0020338e023079b91c58571b20e602d7805fb808c22473cbc391a41b1bd3a192e75b"}}); + Check("sh(wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a91472d0c5a3bfad8c3e7bd5303a72b94240e80b6f1787"}}); + Check("sh(wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a914b61b92e2ca21bac1e72a3ab859a742982bea960a87"}}); + + // Versions with BIP32 derivations + Check("combo([01234567]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", SIGNABLE, {{"2102d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0ac","76a91431a507b815593dfc51ffc7245ae7e5aee304246e88ac","001431a507b815593dfc51ffc7245ae7e5aee304246e","a9142aafb926eb247cb18240a7f4c07983ad1f37922687"}}); + Check("pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", DEFAULT, {{"210379e45b3cf75f9c5f9befd8e9506fb962f6a9d185ac87001ec44a8d3df8d4a9e3ac"}}, {{0}}); + Check("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}}, {{0xFFFFFFFFUL,0}}); + Check("wpkh([ffffffff/13']xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*)", "wpkh([ffffffff/13']xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", RANGE, {{"0014326b2249e3a25d5dc60935f044ee835d090ba859"},{"0014af0bd98abc2f2cae66e36896a39ffe2d32984fb7"},{"00141fa798efd1cbf95cebf912c031b8a4a6e9fb9f27"}}, {{0x8000000DUL, 1, 2, 0}, {0x8000000DUL, 1, 2, 1}, {0x8000000DUL, 1, 2, 2}}); + Check("sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", RANGE | HARDENED, {{"a9149a4d9901d6af519b2a23d4a2f51650fcba87ce7b87"},{"a914bed59fc0024fae941d6e20a3b44a109ae740129287"},{"a9148483aa1116eb9c05c482a72bada4b1db24af654387"}}, {{10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}}); + Check("combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", RANGE, {{"2102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e076ac","76a914f90e3178ca25f2c808dc76624032d352fdbdfaf288ac","0014f90e3178ca25f2c808dc76624032d352fdbdfaf2","a91408f3ea8c68d4a7585bf9e8bda226723f70e445f087"},{"21032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ecac","76a914a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b788ac","0014a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b7","a91473e39884cb71ae4e5ac9739e9225026c99763e6687"}}, {{0}, {1}}); + CheckUnparsable("combo([012345678]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([012345678]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)"); // Too long key fingerprint + CheckUnparsable("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483648)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483648)"); // BIP 32 path element overflow + + // Multisig constructions + Check("multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}); + Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, {{0x8000006FUL,222},{0}}); + Check("wsh(multi(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", HARDENED | RANGE, {{"0020b92623201f3bb7c3771d45b2ad1d0351ea8fbf8cfe0a0e570264e1075fa1948f"},{"002036a08bbe4923af41cf4316817c93b8d37e2f635dd25cfff06bd50df6ae7ea203"},{"0020a96e7ab4607ca6b261bfe3245ffda9c746b28d3f59e83d34820ec0e2b36c139c"}}, {{0xFFFFFFFFUL,0}, {1,2,0}, {1,2,1}, {1,2,2}, {10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}}); + Check("sh(wsh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9)))","sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", SIGNABLE, {{"a9147fc63e13dc25e8a95a3cee3d9a714ac3afd96f1e87"}}); + CheckUnparsable("sh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9))","sh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232))"); // P2SH does not fit 16 compressed pubkeys in a redeemscript + CheckUnparsable("wsh(multi(2,[aaaaaaaa][aaaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaa][aaaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))"); // Double key origin descriptor + CheckUnparsable("wsh(multi(2,[aaaagaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaagaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))"); // Non hex fingerprint + CheckUnparsable("wsh(multi(2,[aaaaaaaa],xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaa],xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))"); // No public key with origin + CheckUnparsable("wsh(multi(2,[aaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))"); // Too short fingerprint + CheckUnparsable("wsh(multi(2,[aaaaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))"); // Too long fingerprint + + // Check for invalid nesting of structures + CheckUnparsable("sh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)"); // P2SH needs a script, not a key + CheckUnparsable("sh(combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))"); // Old must be top level + CheckUnparsable("wsh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "wsh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)"); // P2WSH needs a script, not a key + CheckUnparsable("wsh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "wsh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))"); // Cannot embed witness inside witness + CheckUnparsable("wsh(sh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "wsh(sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))"); // Cannot embed P2SH inside P2WSH + CheckUnparsable("sh(sh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))"); // Cannot embed P2SH inside P2SH + CheckUnparsable("wsh(wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "wsh(wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))"); // Cannot embed P2WSH inside P2WSH + + // Checksums + Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, {{0x8000006FUL,222},{0}}); + Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, {{0x8000006FUL,222},{0}}); + CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#"); // Empty checksum + CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfyq", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5tq"); // Too long checksum + CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxf", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5"); // Too short checksum + CheckUnparsable("sh(multi(3,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy", "sh(multi(3,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t"); // Error in payload + CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggssrxfy", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjq09x4t"); // Error in checksum +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/flatfile_tests.cpp b/src/test/flatfile_tests.cpp new file mode 100644 index 0000000000..1db2f8054c --- /dev/null +++ b/src/test/flatfile_tests.cpp @@ -0,0 +1,123 @@ +// Copyright (c) 2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <flatfile.h> +#include <test/setup_common.h> + +#include <boost/test/unit_test.hpp> + +BOOST_FIXTURE_TEST_SUITE(flatfile_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(flatfile_filename) +{ + auto data_dir = SetDataDir("flatfile_test"); + + FlatFilePos pos(456, 789); + + FlatFileSeq seq1(data_dir, "a", 16 * 1024); + BOOST_CHECK_EQUAL(seq1.FileName(pos), data_dir / "a00456.dat"); + + FlatFileSeq seq2(data_dir / "a", "b", 16 * 1024); + BOOST_CHECK_EQUAL(seq2.FileName(pos), data_dir / "a" / "b00456.dat"); +} + +BOOST_AUTO_TEST_CASE(flatfile_open) +{ + auto data_dir = SetDataDir("flatfile_test"); + FlatFileSeq seq(data_dir, "a", 16 * 1024); + + std::string line1("A purely peer-to-peer version of electronic cash would allow online " + "payments to be sent directly from one party to another without going " + "through a financial institution."); + std::string line2("Digital signatures provide part of the solution, but the main benefits are " + "lost if a trusted third party is still required to prevent double-spending."); + + size_t pos1 = 0; + size_t pos2 = pos1 + GetSerializeSize(line1, CLIENT_VERSION); + + // Write first line to file. + { + CAutoFile file(seq.Open(FlatFilePos(0, pos1)), SER_DISK, CLIENT_VERSION); + file << LIMITED_STRING(line1, 256); + } + + // Attempt to append to file opened in read-only mode. + { + CAutoFile file(seq.Open(FlatFilePos(0, pos2), true), SER_DISK, CLIENT_VERSION); + BOOST_CHECK_THROW(file << LIMITED_STRING(line2, 256), std::ios_base::failure); + } + + // Append second line to file. + { + CAutoFile file(seq.Open(FlatFilePos(0, pos2)), SER_DISK, CLIENT_VERSION); + file << LIMITED_STRING(line2, 256); + } + + // Read text from file in read-only mode. + { + std::string text; + CAutoFile file(seq.Open(FlatFilePos(0, pos1), true), SER_DISK, CLIENT_VERSION); + + file >> LIMITED_STRING(text, 256); + BOOST_CHECK_EQUAL(text, line1); + + file >> LIMITED_STRING(text, 256); + BOOST_CHECK_EQUAL(text, line2); + } + + // Read text from file with position offset. + { + std::string text; + CAutoFile file(seq.Open(FlatFilePos(0, pos2)), SER_DISK, CLIENT_VERSION); + + file >> LIMITED_STRING(text, 256); + BOOST_CHECK_EQUAL(text, line2); + } + + // Ensure another file in the sequence has no data. + { + std::string text; + CAutoFile file(seq.Open(FlatFilePos(1, pos2)), SER_DISK, CLIENT_VERSION); + BOOST_CHECK_THROW(file >> LIMITED_STRING(text, 256), std::ios_base::failure); + } +} + +BOOST_AUTO_TEST_CASE(flatfile_allocate) +{ + auto data_dir = SetDataDir("flatfile_test"); + FlatFileSeq seq(data_dir, "a", 100); + + bool out_of_space; + + BOOST_CHECK_EQUAL(seq.Allocate(FlatFilePos(0, 0), 1, out_of_space), 100); + BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 0))), 100); + BOOST_CHECK(!out_of_space); + + BOOST_CHECK_EQUAL(seq.Allocate(FlatFilePos(0, 99), 1, out_of_space), 0); + BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 99))), 100); + BOOST_CHECK(!out_of_space); + + BOOST_CHECK_EQUAL(seq.Allocate(FlatFilePos(0, 99), 2, out_of_space), 101); + BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 99))), 200); + BOOST_CHECK(!out_of_space); +} + +BOOST_AUTO_TEST_CASE(flatfile_flush) +{ + auto data_dir = SetDataDir("flatfile_test"); + FlatFileSeq seq(data_dir, "a", 100); + + bool out_of_space; + seq.Allocate(FlatFilePos(0, 0), 1, out_of_space); + + // Flush without finalize should not truncate file. + seq.Flush(FlatFilePos(0, 1)); + BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 1))), 100); + + // Flush with finalize should truncate file. + seq.Flush(FlatFilePos(0, 1), true); + BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 1))), 1); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/fs_tests.cpp b/src/test/fs_tests.cpp new file mode 100644 index 0000000000..6bd6bb1be3 --- /dev/null +++ b/src/test/fs_tests.cpp @@ -0,0 +1,56 @@ +// Copyright (c) 2011-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// +#include <fs.h> +#include <test/setup_common.h> + +#include <boost/test/unit_test.hpp> + +BOOST_FIXTURE_TEST_SUITE(fs_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(fsbridge_fstream) +{ + fs::path tmpfolder = SetDataDir("fsbridge_fstream"); + // tmpfile1 should be the same as tmpfile2 + fs::path tmpfile1 = tmpfolder / "fs_tests_₿_🏃"; + fs::path tmpfile2 = tmpfolder / L"fs_tests_₿_🏃"; + { + fsbridge::ofstream file(tmpfile1); + file << "bitcoin"; + } + { + fsbridge::ifstream file(tmpfile2); + std::string input_buffer; + file >> input_buffer; + BOOST_CHECK_EQUAL(input_buffer, "bitcoin"); + } + { + fsbridge::ifstream file(tmpfile1, std::ios_base::in | std::ios_base::ate); + std::string input_buffer; + file >> input_buffer; + BOOST_CHECK_EQUAL(input_buffer, ""); + } + { + fsbridge::ofstream file(tmpfile2, std::ios_base::out | std::ios_base::app); + file << "tests"; + } + { + fsbridge::ifstream file(tmpfile1); + std::string input_buffer; + file >> input_buffer; + BOOST_CHECK_EQUAL(input_buffer, "bitcointests"); + } + { + fsbridge::ofstream file(tmpfile2, std::ios_base::out | std::ios_base::trunc); + file << "bitcoin"; + } + { + fsbridge::ifstream file(tmpfile1); + std::string input_buffer; + file >> input_buffer; + BOOST_CHECK_EQUAL(input_buffer, "bitcoin"); + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp new file mode 100644 index 0000000000..97d7633715 --- /dev/null +++ b/src/test/fuzz/deserialize.cpp @@ -0,0 +1,167 @@ +// Copyright (c) 2009-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <addrman.h> +#include <blockencodings.h> +#include <chain.h> +#include <coins.h> +#include <compressor.h> +#include <consensus/merkle.h> +#include <net.h> +#include <primitives/block.h> +#include <protocol.h> +#include <pubkey.h> +#include <script/script.h> +#include <streams.h> +#include <undo.h> +#include <version.h> + +#include <stdint.h> +#include <unistd.h> + +#include <algorithm> +#include <memory> +#include <vector> + +#include <test/fuzz/fuzz.h> + +void test_one_input(std::vector<uint8_t> buffer) +{ + CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); + try { + int nVersion; + ds >> nVersion; + ds.SetVersion(nVersion); + } catch (const std::ios_base::failure& e) { + return; + } + +#if BLOCK_DESERIALIZE + try + { + CBlock block; + ds >> block; + } catch (const std::ios_base::failure& e) {return;} +#elif TRANSACTION_DESERIALIZE + try + { + CTransaction tx(deserialize, ds); + } catch (const std::ios_base::failure& e) {return;} +#elif BLOCKLOCATOR_DESERIALIZE + try + { + CBlockLocator bl; + ds >> bl; + } catch (const std::ios_base::failure& e) {return;} +#elif BLOCKMERKLEROOT + try + { + CBlock block; + ds >> block; + bool mutated; + BlockMerkleRoot(block, &mutated); + } catch (const std::ios_base::failure& e) {return;} +#elif ADDRMAN_DESERIALIZE + try + { + CAddrMan am; + ds >> am; + } catch (const std::ios_base::failure& e) {return;} +#elif BLOCKHEADER_DESERIALIZE + try + { + CBlockHeader bh; + ds >> bh; + } catch (const std::ios_base::failure& e) {return;} +#elif BANENTRY_DESERIALIZE + try + { + CBanEntry be; + ds >> be; + } catch (const std::ios_base::failure& e) {return;} +#elif TXUNDO_DESERIALIZE + try + { + CTxUndo tu; + ds >> tu; + } catch (const std::ios_base::failure& e) {return;} +#elif BLOCKUNDO_DESERIALIZE + try + { + CBlockUndo bu; + ds >> bu; + } catch (const std::ios_base::failure& e) {return;} +#elif COINS_DESERIALIZE + try + { + Coin coin; + ds >> coin; + } catch (const std::ios_base::failure& e) {return;} +#elif NETADDR_DESERIALIZE + try + { + CNetAddr na; + ds >> na; + } catch (const std::ios_base::failure& e) {return;} +#elif SERVICE_DESERIALIZE + try + { + CService s; + ds >> s; + } catch (const std::ios_base::failure& e) {return;} +#elif MESSAGEHEADER_DESERIALIZE + CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00}; + try + { + CMessageHeader mh(pchMessageStart); + ds >> mh; + if (!mh.IsValid(pchMessageStart)) {return;} + } catch (const std::ios_base::failure& e) {return;} +#elif ADDRESS_DESERIALIZE + try + { + CAddress a; + ds >> a; + } catch (const std::ios_base::failure& e) {return;} +#elif INV_DESERIALIZE + try + { + CInv i; + ds >> i; + } catch (const std::ios_base::failure& e) {return;} +#elif BLOOMFILTER_DESERIALIZE + try + { + CBloomFilter bf; + ds >> bf; + } catch (const std::ios_base::failure& e) {return;} +#elif DISKBLOCKINDEX_DESERIALIZE + try + { + CDiskBlockIndex dbi; + ds >> dbi; + } catch (const std::ios_base::failure& e) {return;} +#elif TXOUTCOMPRESSOR_DESERIALIZE + CTxOut to; + CTxOutCompressor toc(to); + try + { + ds >> toc; + } catch (const std::ios_base::failure& e) {return;} +#elif BLOCKTRANSACTIONS_DESERIALIZE + try + { + BlockTransactions bt; + ds >> bt; + } catch (const std::ios_base::failure& e) {return;} +#elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE + try + { + BlockTransactionsRequest btr; + ds >> btr; + } catch (const std::ios_base::failure& e) {return;} +#else +#error Need at least one fuzz target to compile +#endif +} diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp new file mode 100644 index 0000000000..0709da5563 --- /dev/null +++ b/src/test/fuzz/fuzz.cpp @@ -0,0 +1,77 @@ +// Copyright (c) 2009-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <test/fuzz/fuzz.h> + +#include <unistd.h> + +#include <pubkey.h> +#include <util/memory.h> + + +static bool read_stdin(std::vector<uint8_t>& data) +{ + uint8_t buffer[1024]; + ssize_t length = 0; + while ((length = read(STDIN_FILENO, buffer, 1024)) > 0) { + data.insert(data.end(), buffer, buffer + length); + + if (data.size() > (1 << 20)) return false; + } + return length == 0; +} + +static void initialize() +{ + const static auto verify_handle = MakeUnique<ECCVerifyHandle>(); +} + +// This function is used by libFuzzer +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + test_one_input(std::vector<uint8_t>(data, data + size)); + return 0; +} + +// This function is used by libFuzzer +extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) +{ + initialize(); + return 0; +} + +// Disabled under WIN32 due to clash with Cygwin's WinMain. +#ifndef WIN32 +// Declare main(...) "weak" to allow for libFuzzer linking. libFuzzer provides +// the main(...) function. +__attribute__((weak)) +#endif +int main(int argc, char **argv) +{ + initialize(); +#ifdef __AFL_INIT + // Enable AFL deferred forkserver mode. Requires compilation using + // afl-clang-fast++. See fuzzing.md for details. + __AFL_INIT(); +#endif + +#ifdef __AFL_LOOP + // Enable AFL persistent mode. Requires compilation using afl-clang-fast++. + // See fuzzing.md for details. + while (__AFL_LOOP(1000)) { + std::vector<uint8_t> buffer; + if (!read_stdin(buffer)) { + continue; + } + test_one_input(buffer); + } +#else + std::vector<uint8_t> buffer; + if (!read_stdin(buffer)) { + return 0; + } + test_one_input(buffer); +#endif + return 0; +} diff --git a/src/test/fuzz/fuzz.h b/src/test/fuzz/fuzz.h new file mode 100644 index 0000000000..8b03a7e46e --- /dev/null +++ b/src/test/fuzz/fuzz.h @@ -0,0 +1,15 @@ +// Copyright (c) 2009-2019 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_FUZZ_FUZZ_H +#define BITCOIN_TEST_FUZZ_FUZZ_H + +#include <functional> +#include <stdint.h> +#include <vector> + + +void test_one_input(std::vector<uint8_t> buffer); + +#endif // BITCOIN_TEST_FUZZ_FUZZ_H diff --git a/src/test/fuzz/script_flags.cpp b/src/test/fuzz/script_flags.cpp new file mode 100644 index 0000000000..2c0bfa360c --- /dev/null +++ b/src/test/fuzz/script_flags.cpp @@ -0,0 +1,72 @@ +// Copyright (c) 2009-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <script/interpreter.h> +#include <script/script.h> +#include <streams.h> +#include <version.h> + +#include <test/fuzz/fuzz.h> + +/** Flags that are not forbidden by an assert */ +static bool IsValidFlagCombination(unsigned flags); + +void test_one_input(std::vector<uint8_t> buffer) +{ + CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); + try { + int nVersion; + ds >> nVersion; + ds.SetVersion(nVersion); + } catch (const std::ios_base::failure&) { + return; + } + + try { + const CTransaction tx(deserialize, ds); + const PrecomputedTransactionData txdata(tx); + + unsigned int verify_flags; + ds >> verify_flags; + + if (!IsValidFlagCombination(verify_flags)) return; + + unsigned int fuzzed_flags; + ds >> fuzzed_flags; + + for (unsigned i = 0; i < tx.vin.size(); ++i) { + CTxOut prevout; + ds >> prevout; + + const TransactionSignatureChecker checker{&tx, i, prevout.nValue, txdata}; + + ScriptError serror; + const bool ret = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror); + assert(ret == (serror == SCRIPT_ERR_OK)); + + // Verify that removing flags from a passing test or adding flags to a failing test does not change the result + if (ret) { + verify_flags &= ~fuzzed_flags; + } else { + verify_flags |= fuzzed_flags; + } + if (!IsValidFlagCombination(verify_flags)) return; + + ScriptError serror_fuzzed; + const bool ret_fuzzed = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror_fuzzed); + assert(ret_fuzzed == (serror_fuzzed == SCRIPT_ERR_OK)); + + assert(ret_fuzzed == ret); + } + } catch (const std::ios_base::failure&) { + return; + } +} + +static bool IsValidFlagCombination(unsigned flags) +{ + if (flags & SCRIPT_VERIFY_CLEANSTACK && ~flags & (SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS)) return false; + if (flags & SCRIPT_VERIFY_WITNESS && ~flags & SCRIPT_VERIFY_P2SH) return false; + return true; +} diff --git a/src/test/gen/crypto_gen.cpp b/src/test/gen/crypto_gen.cpp new file mode 100644 index 0000000000..ca8c65806f --- /dev/null +++ b/src/test/gen/crypto_gen.cpp @@ -0,0 +1,19 @@ +// Copyright (c) 2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include <test/gen/crypto_gen.h> + +#include <key.h> + +#include <rapidcheck/gen/Arbitrary.h> +#include <rapidcheck/Gen.h> +#include <rapidcheck/gen/Predicate.h> +#include <rapidcheck/gen/Container.h> + +/** Generates 1 to 20 keys for OP_CHECKMULTISIG */ +rc::Gen<std::vector<CKey>> MultisigKeys() +{ + return rc::gen::suchThat(rc::gen::arbitrary<std::vector<CKey>>(), [](const std::vector<CKey>& keys) { + return keys.size() >= 1 && keys.size() <= 15; + }); +}; diff --git a/src/test/gen/crypto_gen.h b/src/test/gen/crypto_gen.h new file mode 100644 index 0000000000..7c2fb0350f --- /dev/null +++ b/src/test/gen/crypto_gen.h @@ -0,0 +1,63 @@ +// Copyright (c) 2018 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_GEN_CRYPTO_GEN_H +#define BITCOIN_TEST_GEN_CRYPTO_GEN_H + +#include <key.h> +#include <random.h> +#include <uint256.h> +#include <rapidcheck/gen/Arbitrary.h> +#include <rapidcheck/Gen.h> +#include <rapidcheck/gen/Create.h> +#include <rapidcheck/gen/Numeric.h> + +/** Generates 1 to 15 keys for OP_CHECKMULTISIG */ +rc::Gen<std::vector<CKey>> MultisigKeys(); + +namespace rc +{ +/** Generator for a new CKey */ +template <> +struct Arbitrary<CKey> { + static Gen<CKey> arbitrary() + { + return rc::gen::map<int>([](int x) { + CKey key; + key.MakeNewKey(true); + return key; + }); + }; +}; + +/** Generator for a CPrivKey */ +template <> +struct Arbitrary<CPrivKey> { + static Gen<CPrivKey> arbitrary() + { + return gen::map(gen::arbitrary<CKey>(), [](const CKey& key) { + return key.GetPrivKey(); + }); + }; +}; + +/** Generator for a new CPubKey */ +template <> +struct Arbitrary<CPubKey> { + static Gen<CPubKey> arbitrary() + { + return gen::map(gen::arbitrary<CKey>(), [](const CKey& key) { + return key.GetPubKey(); + }); + }; +}; +/** Generates a arbitrary uint256 */ +template <> +struct Arbitrary<uint256> { + static Gen<uint256> arbitrary() + { + return rc::gen::just(GetRandHash()); + }; +}; +} //namespace rc +#endif diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp index c065e25676..8a42344642 100644 --- a/src/test/getarg_tests.cpp +++ b/src/test/getarg_tests.cpp @@ -1,9 +1,10 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <util.h> -#include <test/test_bitcoin.h> +#include <util/strencodings.h> +#include <util/system.h> +#include <test/setup_common.h> #include <string> #include <vector> @@ -17,18 +18,18 @@ static void ResetArgs(const std::string& strArg) { std::vector<std::string> vecArg; if (strArg.size()) - boost::split(vecArg, strArg, boost::is_space(), boost::token_compress_on); + boost::split(vecArg, strArg, IsSpace, boost::token_compress_on); // Insert dummy executable name: vecArg.insert(vecArg.begin(), "testbitcoin"); // Convert to char*: std::vector<const char*> vecChar; - for (std::string& s : vecArg) + for (const std::string& s : vecArg) vecChar.push_back(s.c_str()); std::string error; - gArgs.ParseParameters(vecChar.size(), vecChar.data(), error); + BOOST_CHECK(gArgs.ParseParameters(vecChar.size(), vecChar.data(), error)); } static void SetupArgs(const std::vector<std::string>& args) diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp index d7d6c9b5a3..325b7002f2 100644 --- a/src/test/hash_tests.cpp +++ b/src/test/hash_tests.cpp @@ -1,10 +1,11 @@ -// Copyright (c) 2013-2017 The Bitcoin Core developers +// Copyright (c) 2013-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include <crypto/siphash.h> #include <hash.h> -#include <utilstrencodings.h> -#include <test/test_bitcoin.h> +#include <util/strencodings.h> +#include <test/setup_common.h> #include <vector> diff --git a/src/test/key_io_tests.cpp b/src/test/key_io_tests.cpp index 1ac1e0015b..e924f27d1b 100644 --- a/src/test/key_io_tests.cpp +++ b/src/test/key_io_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -8,8 +8,8 @@ #include <key.h> #include <key_io.h> #include <script/script.h> -#include <utilstrencodings.h> -#include <test/test_bitcoin.h> +#include <util/strencodings.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> @@ -107,7 +107,7 @@ BOOST_AUTO_TEST_CASE(key_io_valid_gen) } else { CTxDestination dest; CScript exp_script(exp_payload.begin(), exp_payload.end()); - ExtractDestination(exp_script, dest); + BOOST_CHECK(ExtractDestination(exp_script, dest)); std::string address = EncodeDestination(dest); BOOST_CHECK_EQUAL(address, exp_base58string); @@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(key_io_invalid) std::string exp_base58string = test[0].get_str(); // must be invalid as public and as private key - for (auto chain : { CBaseChainParams::MAIN, CBaseChainParams::TESTNET, CBaseChainParams::REGTEST }) { + for (const auto& chain : { CBaseChainParams::MAIN, CBaseChainParams::TESTNET, CBaseChainParams::REGTEST }) { SelectParams(chain); destination = DecodeDestination(exp_base58string); BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid pubkey in mainnet:" + strTest); diff --git a/src/test/key_properties.cpp b/src/test/key_properties.cpp new file mode 100644 index 0000000000..8b508ed7f7 --- /dev/null +++ b/src/test/key_properties.cpp @@ -0,0 +1,53 @@ +// Copyright (c) 2018-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include <key.h> + +#include <base58.h> +#include <script/script.h> +#include <uint256.h> +#include <util/system.h> +#include <util/strencodings.h> +#include <test/setup_common.h> +#include <string> +#include <vector> + +#include <boost/test/unit_test.hpp> +#include <rapidcheck/boost_test.h> +#include <rapidcheck/gen/Arbitrary.h> +#include <rapidcheck/Gen.h> + +#include <test/gen/crypto_gen.h> + +BOOST_FIXTURE_TEST_SUITE(key_properties, BasicTestingSetup) + +/** Check CKey uniqueness */ +RC_BOOST_PROP(key_uniqueness, (const CKey& key1, const CKey& key2)) +{ + RC_ASSERT(!(key1 == key2)); +} + +/** Verify that a private key generates the correct public key */ +RC_BOOST_PROP(key_generates_correct_pubkey, (const CKey& key)) +{ + CPubKey pubKey = key.GetPubKey(); + RC_ASSERT(key.VerifyPubKey(pubKey)); +} + +/** Create a CKey using the 'Set' function must give us the same key */ +RC_BOOST_PROP(key_set_symmetry, (const CKey& key)) +{ + CKey key1; + key1.Set(key.begin(), key.end(), key.IsCompressed()); + RC_ASSERT(key1 == key); +} + +/** Create a CKey, sign a piece of data, then verify it with the public key */ +RC_BOOST_PROP(key_sign_symmetry, (const CKey& key, const uint256& hash)) +{ + std::vector<unsigned char> vchSig; + key.Sign(hash, vchSig, 0); + const CPubKey& pubKey = key.GetPubKey(); + RC_ASSERT(pubKey.Verify(hash, vchSig)); +} +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index 64c57f0705..1b95105eab 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -7,9 +7,9 @@ #include <key_io.h> #include <script/script.h> #include <uint256.h> -#include <util.h> -#include <utilstrencodings.h> -#include <test/test_bitcoin.h> +#include <util/system.h> +#include <util/strencodings.h> +#include <test/setup_common.h> #include <string> #include <vector> @@ -68,10 +68,10 @@ BOOST_AUTO_TEST_CASE(key_test1) BOOST_CHECK(!key2C.VerifyPubKey(pubkey2)); BOOST_CHECK(key2C.VerifyPubKey(pubkey2C)); - BOOST_CHECK(DecodeDestination(addr1) == CTxDestination(pubkey1.GetID())); - BOOST_CHECK(DecodeDestination(addr2) == CTxDestination(pubkey2.GetID())); - BOOST_CHECK(DecodeDestination(addr1C) == CTxDestination(pubkey1C.GetID())); - BOOST_CHECK(DecodeDestination(addr2C) == CTxDestination(pubkey2C.GetID())); + BOOST_CHECK(DecodeDestination(addr1) == CTxDestination(PKHash(pubkey1))); + BOOST_CHECK(DecodeDestination(addr2) == CTxDestination(PKHash(pubkey2))); + BOOST_CHECK(DecodeDestination(addr1C) == CTxDestination(PKHash(pubkey1C))); + BOOST_CHECK(DecodeDestination(addr2C) == CTxDestination(PKHash(pubkey2C))); for (int n=0; n<16; n++) { @@ -152,4 +152,72 @@ BOOST_AUTO_TEST_CASE(key_test1) BOOST_CHECK(detsigc == ParseHex("2052d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd561d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d")); } +BOOST_AUTO_TEST_CASE(key_signature_tests) +{ + // When entropy is specified, we should see at least one high R signature within 20 signatures + CKey key = DecodeSecret(strSecret1); + std::string msg = "A message to be signed"; + uint256 msg_hash = Hash(msg.begin(), msg.end()); + std::vector<unsigned char> sig; + bool found = false; + + for (int i = 1; i <=20; ++i) { + sig.clear(); + BOOST_CHECK(key.Sign(msg_hash, sig, false, i)); + found = sig[3] == 0x21 && sig[4] == 0x00; + if (found) { + break; + } + } + BOOST_CHECK(found); + + // When entropy is not specified, we should always see low R signatures that are less than 70 bytes in 256 tries + // We should see at least one signature that is less than 70 bytes. + found = true; + bool found_small = false; + for (int i = 0; i < 256; ++i) { + sig.clear(); + std::string msg = "A message to be signed" + std::to_string(i); + msg_hash = Hash(msg.begin(), msg.end()); + BOOST_CHECK(key.Sign(msg_hash, sig)); + found = sig[3] == 0x20; + BOOST_CHECK(sig.size() <= 70); + found_small |= sig.size() < 70; + } + BOOST_CHECK(found); + BOOST_CHECK(found_small); +} + +BOOST_AUTO_TEST_CASE(key_key_negation) +{ + // create a dummy hash for signature comparison + unsigned char rnd[8]; + std::string str = "Bitcoin key verification\n"; + GetRandBytes(rnd, sizeof(rnd)); + uint256 hash; + CHash256().Write((unsigned char*)str.data(), str.size()).Write(rnd, sizeof(rnd)).Finalize(hash.begin()); + + // import the static test key + CKey key = DecodeSecret(strSecret1C); + + // create a signature + std::vector<unsigned char> vch_sig; + std::vector<unsigned char> vch_sig_cmp; + key.Sign(hash, vch_sig); + + // negate the key twice + BOOST_CHECK(key.GetPubKey().data()[0] == 0x03); + key.Negate(); + // after the first negation, the signature must be different + key.Sign(hash, vch_sig_cmp); + BOOST_CHECK(vch_sig_cmp != vch_sig); + BOOST_CHECK(key.GetPubKey().data()[0] == 0x02); + key.Negate(); + // after the second negation, we should have the original key and thus the + // same signature + key.Sign(hash, vch_sig_cmp); + BOOST_CHECK(vch_sig_cmp == vch_sig); + BOOST_CHECK(key.GetPubKey().data()[0] == 0x03); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/limitedmap_tests.cpp b/src/test/limitedmap_tests.cpp index a4bd63cdef..00b36f51fb 100644 --- a/src/test/limitedmap_tests.cpp +++ b/src/test/limitedmap_tests.cpp @@ -1,10 +1,10 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <limitedmap.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> @@ -50,10 +50,10 @@ BOOST_AUTO_TEST_CASE(limitedmap_test) // use the iterator to check for the expected key and value BOOST_CHECK(it->first == i); BOOST_CHECK(it->second == i + 1); - + // use find to check for the value BOOST_CHECK(map.find(i)->second == i + 1); - + // update and recheck map.update(it, i + 2); BOOST_CHECK(map.find(i)->second == i + 2); diff --git a/src/test/main.cpp b/src/test/main.cpp new file mode 100644 index 0000000000..ff3f36b561 --- /dev/null +++ b/src/test/main.cpp @@ -0,0 +1,7 @@ +// Copyright (c) 2011-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#define BOOST_TEST_MODULE Bitcoin Core Test Suite + +#include <boost/test/unit_test.hpp> diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp index 0264d29455..0f74b379c0 100644 --- a/src/test/mempool_tests.cpp +++ b/src/test/mempool_tests.cpp @@ -1,12 +1,12 @@ -// Copyright (c) 2011-2017 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <policy/policy.h> #include <txmempool.h> -#include <util.h> +#include <util/system.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> #include <list> @@ -55,52 +55,53 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest) CTxMemPool testPool; + LOCK2(cs_main, testPool.cs); // Nothing in pool, remove should do nothing: unsigned int poolSize = testPool.size(); - testPool.removeRecursive(txParent); + testPool.removeRecursive(CTransaction(txParent)); BOOST_CHECK_EQUAL(testPool.size(), poolSize); // Just the parent: - testPool.addUnchecked(txParent.GetHash(), entry.FromTx(txParent)); + testPool.addUnchecked(entry.FromTx(txParent)); poolSize = testPool.size(); - testPool.removeRecursive(txParent); + testPool.removeRecursive(CTransaction(txParent)); BOOST_CHECK_EQUAL(testPool.size(), poolSize - 1); - + // Parent, children, grandchildren: - testPool.addUnchecked(txParent.GetHash(), entry.FromTx(txParent)); + testPool.addUnchecked(entry.FromTx(txParent)); for (int i = 0; i < 3; i++) { - testPool.addUnchecked(txChild[i].GetHash(), entry.FromTx(txChild[i])); - testPool.addUnchecked(txGrandChild[i].GetHash(), entry.FromTx(txGrandChild[i])); + testPool.addUnchecked(entry.FromTx(txChild[i])); + testPool.addUnchecked(entry.FromTx(txGrandChild[i])); } // Remove Child[0], GrandChild[0] should be removed: poolSize = testPool.size(); - testPool.removeRecursive(txChild[0]); + testPool.removeRecursive(CTransaction(txChild[0])); BOOST_CHECK_EQUAL(testPool.size(), poolSize - 2); // ... make sure grandchild and child are gone: poolSize = testPool.size(); - testPool.removeRecursive(txGrandChild[0]); + testPool.removeRecursive(CTransaction(txGrandChild[0])); BOOST_CHECK_EQUAL(testPool.size(), poolSize); poolSize = testPool.size(); - testPool.removeRecursive(txChild[0]); + testPool.removeRecursive(CTransaction(txChild[0])); BOOST_CHECK_EQUAL(testPool.size(), poolSize); // Remove parent, all children/grandchildren should go: poolSize = testPool.size(); - testPool.removeRecursive(txParent); + testPool.removeRecursive(CTransaction(txParent)); BOOST_CHECK_EQUAL(testPool.size(), poolSize - 5); BOOST_CHECK_EQUAL(testPool.size(), 0U); // Add children and grandchildren, but NOT the parent (simulate the parent being in a block) for (int i = 0; i < 3; i++) { - testPool.addUnchecked(txChild[i].GetHash(), entry.FromTx(txChild[i])); - testPool.addUnchecked(txGrandChild[i].GetHash(), entry.FromTx(txGrandChild[i])); + testPool.addUnchecked(entry.FromTx(txChild[i])); + testPool.addUnchecked(entry.FromTx(txGrandChild[i])); } // Now remove the parent, as might happen if a block-re-org occurs but the parent cannot be // put into the mempool (maybe because it is non-standard): poolSize = testPool.size(); - testPool.removeRecursive(txParent); + testPool.removeRecursive(CTransaction(txParent)); BOOST_CHECK_EQUAL(testPool.size(), poolSize - 6); BOOST_CHECK_EQUAL(testPool.size(), 0U); } @@ -119,6 +120,7 @@ static void CheckSort(CTxMemPool &pool, std::vector<std::string> &sortedOrder) E BOOST_AUTO_TEST_CASE(MempoolIndexingTest) { CTxMemPool pool; + LOCK2(cs_main, pool.cs); TestMemPoolEntryHelper entry; /* 3rd highest fee */ @@ -126,28 +128,28 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest) tx1.vout.resize(1); tx1.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; tx1.vout[0].nValue = 10 * COIN; - pool.addUnchecked(tx1.GetHash(), entry.Fee(10000LL).FromTx(tx1)); + pool.addUnchecked(entry.Fee(10000LL).FromTx(tx1)); /* highest fee */ CMutableTransaction tx2 = CMutableTransaction(); tx2.vout.resize(1); tx2.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; tx2.vout[0].nValue = 2 * COIN; - pool.addUnchecked(tx2.GetHash(), entry.Fee(20000LL).FromTx(tx2)); + pool.addUnchecked(entry.Fee(20000LL).FromTx(tx2)); /* lowest fee */ CMutableTransaction tx3 = CMutableTransaction(); tx3.vout.resize(1); tx3.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; tx3.vout[0].nValue = 5 * COIN; - pool.addUnchecked(tx3.GetHash(), entry.Fee(0LL).FromTx(tx3)); + pool.addUnchecked(entry.Fee(0LL).FromTx(tx3)); /* 2nd highest fee */ CMutableTransaction tx4 = CMutableTransaction(); tx4.vout.resize(1); tx4.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; tx4.vout[0].nValue = 6 * COIN; - pool.addUnchecked(tx4.GetHash(), entry.Fee(15000LL).FromTx(tx4)); + pool.addUnchecked(entry.Fee(15000LL).FromTx(tx4)); /* equal fee rate to tx1, but newer */ CMutableTransaction tx5 = CMutableTransaction(); @@ -155,7 +157,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest) tx5.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; tx5.vout[0].nValue = 11 * COIN; entry.nTime = 1; - pool.addUnchecked(tx5.GetHash(), entry.Fee(10000LL).FromTx(tx5)); + pool.addUnchecked(entry.Fee(10000LL).FromTx(tx5)); BOOST_CHECK_EQUAL(pool.size(), 5U); std::vector<std::string> sortedOrder; @@ -165,7 +167,6 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest) sortedOrder[2] = tx1.GetHash().ToString(); // 10000 sortedOrder[3] = tx4.GetHash().ToString(); // 15000 sortedOrder[4] = tx2.GetHash().ToString(); // 20000 - LOCK(pool.cs); CheckSort<descendant_score>(pool, sortedOrder); /* low fee but with high fee child */ @@ -174,7 +175,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest) tx6.vout.resize(1); tx6.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; tx6.vout[0].nValue = 20 * COIN; - pool.addUnchecked(tx6.GetHash(), entry.Fee(0LL).FromTx(tx6)); + pool.addUnchecked(entry.Fee(0LL).FromTx(tx6)); BOOST_CHECK_EQUAL(pool.size(), 6U); // Check that at this point, tx6 is sorted low sortedOrder.insert(sortedOrder.begin(), tx6.GetHash().ToString()); @@ -197,7 +198,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest) BOOST_CHECK_EQUAL(pool.CalculateMemPoolAncestors(entry.Fee(2000000LL).FromTx(tx7), setAncestorsCalculated, 100, 1000000, 1000, 1000000, dummy), true); BOOST_CHECK(setAncestorsCalculated == setAncestors); - pool.addUnchecked(tx7.GetHash(), entry.FromTx(tx7), setAncestors); + pool.addUnchecked(entry.FromTx(tx7), setAncestors); BOOST_CHECK_EQUAL(pool.size(), 7U); // Now tx6 should be sorted higher (high fee child): tx7, tx6, tx2, ... @@ -215,7 +216,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest) tx8.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; tx8.vout[0].nValue = 10 * COIN; setAncestors.insert(pool.mapTx.find(tx7.GetHash())); - pool.addUnchecked(tx8.GetHash(), entry.Fee(0LL).Time(2).FromTx(tx8), setAncestors); + pool.addUnchecked(entry.Fee(0LL).Time(2).FromTx(tx8), setAncestors); // Now tx8 should be sorted low, but tx6/tx both high sortedOrder.insert(sortedOrder.begin(), tx8.GetHash().ToString()); @@ -229,7 +230,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest) tx9.vout.resize(1); tx9.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; tx9.vout[0].nValue = 1 * COIN; - pool.addUnchecked(tx9.GetHash(), entry.Fee(0LL).Time(3).FromTx(tx9), setAncestors); + pool.addUnchecked(entry.Fee(0LL).Time(3).FromTx(tx9), setAncestors); // tx9 should be sorted low BOOST_CHECK_EQUAL(pool.size(), 9U); @@ -255,7 +256,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest) BOOST_CHECK_EQUAL(pool.CalculateMemPoolAncestors(entry.Fee(200000LL).Time(4).FromTx(tx10), setAncestorsCalculated, 100, 1000000, 1000, 1000000, dummy), true); BOOST_CHECK(setAncestorsCalculated == setAncestors); - pool.addUnchecked(tx10.GetHash(), entry.FromTx(tx10), setAncestors); + pool.addUnchecked(entry.FromTx(tx10), setAncestors); /** * tx8 and tx9 should both now be sorted higher @@ -292,6 +293,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest) BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest) { CTxMemPool pool; + LOCK2(cs_main, pool.cs); TestMemPoolEntryHelper entry; /* 3rd highest fee */ @@ -299,36 +301,36 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest) tx1.vout.resize(1); tx1.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; tx1.vout[0].nValue = 10 * COIN; - pool.addUnchecked(tx1.GetHash(), entry.Fee(10000LL).FromTx(tx1)); + pool.addUnchecked(entry.Fee(10000LL).FromTx(tx1)); /* highest fee */ CMutableTransaction tx2 = CMutableTransaction(); tx2.vout.resize(1); tx2.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; tx2.vout[0].nValue = 2 * COIN; - pool.addUnchecked(tx2.GetHash(), entry.Fee(20000LL).FromTx(tx2)); - uint64_t tx2Size = GetVirtualTransactionSize(tx2); + pool.addUnchecked(entry.Fee(20000LL).FromTx(tx2)); + uint64_t tx2Size = GetVirtualTransactionSize(CTransaction(tx2)); /* lowest fee */ CMutableTransaction tx3 = CMutableTransaction(); tx3.vout.resize(1); tx3.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; tx3.vout[0].nValue = 5 * COIN; - pool.addUnchecked(tx3.GetHash(), entry.Fee(0LL).FromTx(tx3)); + pool.addUnchecked(entry.Fee(0LL).FromTx(tx3)); /* 2nd highest fee */ CMutableTransaction tx4 = CMutableTransaction(); tx4.vout.resize(1); tx4.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; tx4.vout[0].nValue = 6 * COIN; - pool.addUnchecked(tx4.GetHash(), entry.Fee(15000LL).FromTx(tx4)); + pool.addUnchecked(entry.Fee(15000LL).FromTx(tx4)); /* equal fee rate to tx1, but newer */ CMutableTransaction tx5 = CMutableTransaction(); tx5.vout.resize(1); tx5.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; tx5.vout[0].nValue = 11 * COIN; - pool.addUnchecked(tx5.GetHash(), entry.Fee(10000LL).FromTx(tx5)); + pool.addUnchecked(entry.Fee(10000LL).FromTx(tx5)); BOOST_CHECK_EQUAL(pool.size(), 5U); std::vector<std::string> sortedOrder; @@ -347,7 +349,6 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest) } sortedOrder[4] = tx3.GetHash().ToString(); // 0 - LOCK(pool.cs); CheckSort<ancestor_score>(pool, sortedOrder); /* low fee parent with high fee child */ @@ -356,9 +357,9 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest) tx6.vout.resize(1); tx6.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; tx6.vout[0].nValue = 20 * COIN; - uint64_t tx6Size = GetVirtualTransactionSize(tx6); + uint64_t tx6Size = GetVirtualTransactionSize(CTransaction(tx6)); - pool.addUnchecked(tx6.GetHash(), entry.Fee(0LL).FromTx(tx6)); + pool.addUnchecked(entry.Fee(0LL).FromTx(tx6)); BOOST_CHECK_EQUAL(pool.size(), 6U); // Ties are broken by hash if (tx3.GetHash() < tx6.GetHash()) @@ -375,12 +376,12 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest) tx7.vout.resize(1); tx7.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; tx7.vout[0].nValue = 10 * COIN; - uint64_t tx7Size = GetVirtualTransactionSize(tx7); + uint64_t tx7Size = GetVirtualTransactionSize(CTransaction(tx7)); /* set the fee to just below tx2's feerate when including ancestor */ CAmount fee = (20000/tx2Size)*(tx7Size + tx6Size) - 1; - pool.addUnchecked(tx7.GetHash(), entry.Fee(fee).FromTx(tx7)); + pool.addUnchecked(entry.Fee(fee).FromTx(tx7)); BOOST_CHECK_EQUAL(pool.size(), 7U); sortedOrder.insert(sortedOrder.begin()+1, tx7.GetHash().ToString()); CheckSort<ancestor_score>(pool, sortedOrder); @@ -412,7 +413,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest) // Check that we sort by min(feerate, ancestor_feerate): // set the fee so that the ancestor feerate is above tx1/5, // but the transaction's own feerate is lower - pool.addUnchecked(tx8.GetHash(), entry.Fee(5000LL).FromTx(tx8)); + pool.addUnchecked(entry.Fee(5000LL).FromTx(tx8)); sortedOrder.insert(sortedOrder.end()-1, tx8.GetHash().ToString()); CheckSort<ancestor_score>(pool, sortedOrder); } @@ -421,6 +422,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest) BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest) { CTxMemPool pool; + LOCK2(cs_main, pool.cs); TestMemPoolEntryHelper entry; CMutableTransaction tx1 = CMutableTransaction(); @@ -429,7 +431,7 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest) tx1.vout.resize(1); tx1.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL; tx1.vout[0].nValue = 10 * COIN; - pool.addUnchecked(tx1.GetHash(), entry.Fee(10000LL).FromTx(tx1)); + pool.addUnchecked(entry.Fee(10000LL).FromTx(tx1)); CMutableTransaction tx2 = CMutableTransaction(); tx2.vin.resize(1); @@ -437,7 +439,7 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest) tx2.vout.resize(1); tx2.vout[0].scriptPubKey = CScript() << OP_2 << OP_EQUAL; tx2.vout[0].nValue = 10 * COIN; - pool.addUnchecked(tx2.GetHash(), entry.Fee(5000LL).FromTx(tx2)); + pool.addUnchecked(entry.Fee(5000LL).FromTx(tx2)); pool.TrimToSize(pool.DynamicMemoryUsage()); // should do nothing BOOST_CHECK(pool.exists(tx1.GetHash())); @@ -447,7 +449,7 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest) BOOST_CHECK(pool.exists(tx1.GetHash())); BOOST_CHECK(!pool.exists(tx2.GetHash())); - pool.addUnchecked(tx2.GetHash(), entry.FromTx(tx2)); + pool.addUnchecked(entry.FromTx(tx2)); CMutableTransaction tx3 = CMutableTransaction(); tx3.vin.resize(1); tx3.vin[0].prevout = COutPoint(tx2.GetHash(), 0); @@ -455,19 +457,19 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest) tx3.vout.resize(1); tx3.vout[0].scriptPubKey = CScript() << OP_3 << OP_EQUAL; tx3.vout[0].nValue = 10 * COIN; - pool.addUnchecked(tx3.GetHash(), entry.Fee(20000LL).FromTx(tx3)); + pool.addUnchecked(entry.Fee(20000LL).FromTx(tx3)); pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // tx3 should pay for tx2 (CPFP) BOOST_CHECK(!pool.exists(tx1.GetHash())); BOOST_CHECK(pool.exists(tx2.GetHash())); BOOST_CHECK(pool.exists(tx3.GetHash())); - pool.TrimToSize(GetVirtualTransactionSize(tx1)); // mempool is limited to tx1's size in memory usage, so nothing fits + pool.TrimToSize(GetVirtualTransactionSize(CTransaction(tx1))); // mempool is limited to tx1's size in memory usage, so nothing fits BOOST_CHECK(!pool.exists(tx1.GetHash())); BOOST_CHECK(!pool.exists(tx2.GetHash())); BOOST_CHECK(!pool.exists(tx3.GetHash())); - CFeeRate maxFeeRateRemoved(25000, GetVirtualTransactionSize(tx3) + GetVirtualTransactionSize(tx2)); + CFeeRate maxFeeRateRemoved(25000, GetVirtualTransactionSize(CTransaction(tx3)) + GetVirtualTransactionSize(CTransaction(tx2))); BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000); CMutableTransaction tx4 = CMutableTransaction(); @@ -518,10 +520,10 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest) tx7.vout[1].scriptPubKey = CScript() << OP_7 << OP_EQUAL; tx7.vout[1].nValue = 10 * COIN; - pool.addUnchecked(tx4.GetHash(), entry.Fee(7000LL).FromTx(tx4)); - pool.addUnchecked(tx5.GetHash(), entry.Fee(1000LL).FromTx(tx5)); - pool.addUnchecked(tx6.GetHash(), entry.Fee(1100LL).FromTx(tx6)); - pool.addUnchecked(tx7.GetHash(), entry.Fee(9000LL).FromTx(tx7)); + pool.addUnchecked(entry.Fee(7000LL).FromTx(tx4)); + pool.addUnchecked(entry.Fee(1000LL).FromTx(tx5)); + pool.addUnchecked(entry.Fee(1100LL).FromTx(tx6)); + pool.addUnchecked(entry.Fee(9000LL).FromTx(tx7)); // we only require this to remove, at max, 2 txn, because it's not clear what we're really optimizing for aside from that pool.TrimToSize(pool.DynamicMemoryUsage() - 1); @@ -530,8 +532,8 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest) BOOST_CHECK(!pool.exists(tx7.GetHash())); if (!pool.exists(tx5.GetHash())) - pool.addUnchecked(tx5.GetHash(), entry.Fee(1000LL).FromTx(tx5)); - pool.addUnchecked(tx7.GetHash(), entry.Fee(9000LL).FromTx(tx7)); + pool.addUnchecked(entry.Fee(1000LL).FromTx(tx5)); + pool.addUnchecked(entry.Fee(9000LL).FromTx(tx7)); pool.TrimToSize(pool.DynamicMemoryUsage() / 2); // should maximize mempool size by only removing 5/7 BOOST_CHECK(pool.exists(tx4.GetHash())); @@ -539,8 +541,8 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest) BOOST_CHECK(pool.exists(tx6.GetHash())); BOOST_CHECK(!pool.exists(tx7.GetHash())); - pool.addUnchecked(tx5.GetHash(), entry.Fee(1000LL).FromTx(tx5)); - pool.addUnchecked(tx7.GetHash(), entry.Fee(9000LL).FromTx(tx7)); + pool.addUnchecked(entry.Fee(1000LL).FromTx(tx5)); + pool.addUnchecked(entry.Fee(9000LL).FromTx(tx7)); std::vector<CTransactionRef> vtx; SetMockTime(42); @@ -593,6 +595,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests) size_t ancestors, descendants; CTxMemPool pool; + LOCK2(cs_main, pool.cs); TestMemPoolEntryHelper entry; /* Base transaction */ @@ -600,7 +603,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests) // [tx1] // CTransactionRef tx1 = make_tx(/* output_values */ {10 * COIN}); - pool.addUnchecked(tx1->GetHash(), entry.Fee(10000LL).FromTx(tx1)); + pool.addUnchecked(entry.Fee(10000LL).FromTx(tx1)); // Ancestors / descendants should be 1 / 1 (itself / itself) pool.GetTransactionAncestry(tx1->GetHash(), ancestors, descendants); @@ -612,7 +615,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests) // [tx1].0 <- [tx2] // CTransactionRef tx2 = make_tx(/* output_values */ {495 * CENT, 5 * COIN}, /* inputs */ {tx1}); - pool.addUnchecked(tx2->GetHash(), entry.Fee(10000LL).FromTx(tx2)); + pool.addUnchecked(entry.Fee(10000LL).FromTx(tx2)); // Ancestors / descendants should be: // transaction ancestors descendants @@ -631,7 +634,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests) // [tx1].0 <- [tx2].0 <- [tx3] // CTransactionRef tx3 = make_tx(/* output_values */ {290 * CENT, 200 * CENT}, /* inputs */ {tx2}); - pool.addUnchecked(tx3->GetHash(), entry.Fee(10000LL).FromTx(tx3)); + pool.addUnchecked(entry.Fee(10000LL).FromTx(tx3)); // Ancestors / descendants should be: // transaction ancestors descendants @@ -656,7 +659,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests) // \---1 <- [tx4] // CTransactionRef tx4 = make_tx(/* output_values */ {290 * CENT, 250 * CENT}, /* inputs */ {tx2}, /* input_indices */ {1}); - pool.addUnchecked(tx4->GetHash(), entry.Fee(10000LL).FromTx(tx4)); + pool.addUnchecked(entry.Fee(10000LL).FromTx(tx4)); // Ancestors / descendants should be: // transaction ancestors descendants @@ -693,13 +696,13 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests) CTransactionRef& tyi = *ty[i]; tyi = make_tx(/* output_values */ {v}, /* inputs */ i > 0 ? std::vector<CTransactionRef>{*ty[i - 1]} : std::vector<CTransactionRef>{}); v -= 50 * CENT; - pool.addUnchecked(tyi->GetHash(), entry.Fee(10000LL).FromTx(tyi)); + pool.addUnchecked(entry.Fee(10000LL).FromTx(tyi)); pool.GetTransactionAncestry(tyi->GetHash(), ancestors, descendants); BOOST_CHECK_EQUAL(ancestors, i+1); BOOST_CHECK_EQUAL(descendants, i+1); } CTransactionRef ty6 = make_tx(/* output_values */ {5 * COIN}, /* inputs */ {tx3, ty5}); - pool.addUnchecked(ty6->GetHash(), entry.Fee(10000LL).FromTx(ty6)); + pool.addUnchecked(entry.Fee(10000LL).FromTx(ty6)); // Ancestors / descendants should be: // transaction ancestors descendants diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index 259e45dacf..1684258c9f 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -1,9 +1,9 @@ -// Copyright (c) 2015-2017 The Bitcoin Core developers +// Copyright (c) 2015-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <consensus/merkle.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> @@ -13,9 +13,9 @@ static uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vecto uint256 hash = leaf; for (std::vector<uint256>::const_iterator it = vMerkleBranch.begin(); it != vMerkleBranch.end(); ++it) { if (nIndex & 1) { - hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash)); + hash = Hash(it->begin(), it->end(), hash.begin(), hash.end()); } else { - hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it)); + hash = Hash(hash.begin(), hash.end(), it->begin(), it->end()); } nIndex >>= 1; } diff --git a/src/test/merkleblock_tests.cpp b/src/test/merkleblock_tests.cpp index 2472ea9950..eac43471c7 100644 --- a/src/test/merkleblock_tests.cpp +++ b/src/test/merkleblock_tests.cpp @@ -1,10 +1,10 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <merkleblock.h> #include <uint256.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 9a325f5f4c..4321d7d16e 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2017 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -8,17 +8,17 @@ #include <consensus/merkle.h> #include <consensus/tx_verify.h> #include <consensus/validation.h> -#include <validation.h> #include <miner.h> #include <policy/policy.h> #include <pubkey.h> #include <script/standard.h> #include <txmempool.h> #include <uint256.h> -#include <util.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> +#include <util/system.h> +#include <validation.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <memory> @@ -29,7 +29,7 @@ BOOST_FIXTURE_TEST_SUITE(miner_tests, TestingSetup) // BOOST_CHECK_EXCEPTION predicates to check the specific validation error class HasReason { public: - HasReason(const std::string& reason) : m_reason(reason) {} + explicit HasReason(const std::string& reason) : m_reason(reason) {} bool operator() (const std::runtime_error& e) const { return std::string(e.what()).find(m_reason) != std::string::npos; }; @@ -82,24 +82,24 @@ struct { {2, 0xbbbeb305}, {2, 0xfe1c810a}, }; -static CBlockIndex CreateBlockIndex(int nHeight) +static CBlockIndex CreateBlockIndex(int nHeight) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { CBlockIndex index; index.nHeight = nHeight; - index.pprev = chainActive.Tip(); + index.pprev = ::ChainActive().Tip(); return index; } -static bool TestSequenceLocks(const CTransaction &tx, int flags) +static bool TestSequenceLocks(const CTransaction &tx, int flags) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { - LOCK(mempool.cs); - return CheckSequenceLocks(tx, flags); + LOCK(::mempool.cs); + return CheckSequenceLocks(::mempool, tx, flags); } // Test suite for ancestor feerate transaction selection. // Implemented as an additional function, rather than a separate test case, // to allow reusing the blockchain created in CreateNewBlock_validity. -static void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey, std::vector<CTransactionRef>& txFirst) +static void TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(cs_main, ::mempool.cs) { // Test the ancestor feerate transaction selection. TestMemPoolEntryHelper entry; @@ -115,19 +115,19 @@ static void TestPackageSelection(const CChainParams& chainparams, CScript script tx.vout[0].nValue = 5000000000LL - 1000; // This tx has a low fee: 1000 satoshis uint256 hashParentTx = tx.GetHash(); // save this txid for later use - mempool.addUnchecked(hashParentTx, entry.Fee(1000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + mempool.addUnchecked(entry.Fee(1000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); // This tx has a medium fee: 10000 satoshis tx.vin[0].prevout.hash = txFirst[1]->GetHash(); tx.vout[0].nValue = 5000000000LL - 10000; uint256 hashMediumFeeTx = tx.GetHash(); - mempool.addUnchecked(hashMediumFeeTx, entry.Fee(10000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + mempool.addUnchecked(entry.Fee(10000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); // This tx has a high fee, but depends on the first transaction tx.vin[0].prevout.hash = hashParentTx; tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 50k satoshi fee uint256 hashHighFeeTx = tx.GetHash(); - mempool.addUnchecked(hashHighFeeTx, entry.Fee(50000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); + mempool.addUnchecked(entry.Fee(50000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); std::unique_ptr<CBlockTemplate> pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashParentTx); @@ -138,8 +138,8 @@ static void TestPackageSelection(const CChainParams& chainparams, CScript script tx.vin[0].prevout.hash = hashHighFeeTx; tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 0 fee uint256 hashFreeTx = tx.GetHash(); - mempool.addUnchecked(hashFreeTx, entry.Fee(0).FromTx(tx)); - size_t freeTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); + mempool.addUnchecked(entry.Fee(0).FromTx(tx)); + size_t freeTxSize = ::GetSerializeSize(tx, PROTOCOL_VERSION); // Calculate a fee on child transaction that will put the package just // below the block min tx fee (assuming 1 child tx of the same size). @@ -148,7 +148,7 @@ static void TestPackageSelection(const CChainParams& chainparams, CScript script tx.vin[0].prevout.hash = hashFreeTx; tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse; uint256 hashLowFeeTx = tx.GetHash(); - mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse).FromTx(tx)); + mempool.addUnchecked(entry.Fee(feeToUse).FromTx(tx)); pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); // Verify that the free tx and the low fee tx didn't get selected for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) { @@ -159,10 +159,10 @@ static void TestPackageSelection(const CChainParams& chainparams, CScript script // Test that packages above the min relay fee do get included, even if one // of the transactions is below the min relay fee // Remove the low fee transaction and replace with a higher fee transaction - mempool.removeRecursive(tx); + mempool.removeRecursive(CTransaction(tx)); tx.vout[0].nValue -= 2; // Now we should be just over the min relay fee hashLowFeeTx = tx.GetHash(); - mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse+2).FromTx(tx)); + mempool.addUnchecked(entry.Fee(feeToUse+2).FromTx(tx)); pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); BOOST_CHECK(pblocktemplate->block.vtx[4]->GetHash() == hashFreeTx); BOOST_CHECK(pblocktemplate->block.vtx[5]->GetHash() == hashLowFeeTx); @@ -175,7 +175,7 @@ static void TestPackageSelection(const CChainParams& chainparams, CScript script tx.vout[0].nValue = 5000000000LL - 100000000; tx.vout[1].nValue = 100000000; // 1BTC output uint256 hashFreeTx2 = tx.GetHash(); - mempool.addUnchecked(hashFreeTx2, entry.Fee(0).SpendsCoinbase(true).FromTx(tx)); + mempool.addUnchecked(entry.Fee(0).SpendsCoinbase(true).FromTx(tx)); // This tx can't be mined by itself tx.vin[0].prevout.hash = hashFreeTx2; @@ -183,7 +183,7 @@ static void TestPackageSelection(const CChainParams& chainparams, CScript script feeToUse = blockMinFeeRate.GetFee(freeTxSize); tx.vout[0].nValue = 5000000000LL - 100000000 - feeToUse; uint256 hashLowFeeTx2 = tx.GetHash(); - mempool.addUnchecked(hashLowFeeTx2, entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx)); + mempool.addUnchecked(entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx)); pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); // Verify that this tx isn't selected. @@ -196,7 +196,7 @@ static void TestPackageSelection(const CChainParams& chainparams, CScript script // as well. tx.vin[0].prevout.n = 1; tx.vout[0].nValue = 100000000 - 10000; // 10k satoshi fee - mempool.addUnchecked(tx.GetHash(), entry.Fee(10000).FromTx(tx)); + mempool.addUnchecked(entry.Fee(10000).FromTx(tx)); pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); BOOST_CHECK(pblocktemplate->block.vtx[8]->GetHash() == hashLowFeeTx2); } @@ -209,7 +209,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) const CChainParams& chainparams = *chainParams; CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; std::unique_ptr<CBlockTemplate> pblocktemplate; - CMutableTransaction tx,tx2; + CMutableTransaction tx; CScript script; uint256 hash; TestMemPoolEntryHelper entry; @@ -231,17 +231,17 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) { LOCK(cs_main); pblock->nVersion = 1; - pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1; + pblock->nTime = ::ChainActive().Tip()->GetMedianTimePast()+1; CMutableTransaction txCoinbase(*pblock->vtx[0]); txCoinbase.nVersion = 1; txCoinbase.vin[0].scriptSig = CScript(); txCoinbase.vin[0].scriptSig.push_back(blockinfo[i].extranonce); - txCoinbase.vin[0].scriptSig.push_back(chainActive.Height()); + txCoinbase.vin[0].scriptSig.push_back(::ChainActive().Height()); txCoinbase.vout.resize(1); // Ignore the (optional) segwit commitment added by CreateNewBlock (as the hardcoded nonces don't account for this) txCoinbase.vout[0].scriptPubKey = CScript(); pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase)); if (txFirst.size() == 0) - baseheight = chainActive.Height(); + baseheight = ::ChainActive().Height(); if (txFirst.size() < 4) txFirst.push_back(pblock->vtx[0]); pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); @@ -253,6 +253,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) } LOCK(cs_main); + LOCK(::mempool.cs); // Just to make sure we can still make simple blocks BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); @@ -276,7 +277,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) hash = tx.GetHash(); 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)); + mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } @@ -291,7 +292,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) hash = tx.GetHash(); 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)); + mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx)); tx.vin[0].prevout.hash = hash; } BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); @@ -311,7 +312,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue -= LOWFEE; hash = tx.GetHash(); bool spendsCoinbase = i == 0; // only first tx spends coinbase - mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); + mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); @@ -319,7 +320,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) // orphan in mempool, template creation fails hash = tx.GetHash(); - mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).FromTx(tx)); + mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).FromTx(tx)); BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent")); mempool.clear(); @@ -328,7 +329,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vin[0].prevout.hash = txFirst[1]->GetHash(); tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE; hash = tx.GetHash(); - mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + mempool.addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); tx.vin[0].prevout.hash = hash; tx.vin.resize(2); tx.vin[1].scriptSig = CScript() << OP_1; @@ -336,7 +337,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vin[1].prevout.n = 0; tx.vout[0].nValue = tx.vout[0].nValue+BLOCKSUBSIDY-HIGHERFEE; //First txn output + fresh coinbase - new txn fee hash = tx.GetHash(); - mempool.addUnchecked(hash, entry.Fee(HIGHERFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + mempool.addUnchecked(entry.Fee(HIGHERFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); mempool.clear(); @@ -347,7 +348,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue = 0; hash = tx.GetHash(); // give it a fee so it'll get mined - mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); + mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); // Should throw bad-cb-multiple BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-cb-multiple")); mempool.clear(); @@ -358,37 +359,37 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE; tx.vout[0].scriptPubKey = CScript() << OP_1; hash = tx.GetHash(); - mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + mempool.addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); tx.vout[0].scriptPubKey = CScript() << OP_2; hash = tx.GetHash(); - mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + mempool.addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent")); mempool.clear(); // subsidy changing - int nHeight = chainActive.Height(); + int nHeight = ::ChainActive().Height(); // Create an actual 209999-long block chain (without valid blocks). - while (chainActive.Tip()->nHeight < 209999) { - CBlockIndex* prev = chainActive.Tip(); + while (::ChainActive().Tip()->nHeight < 209999) { + CBlockIndex* prev = ::ChainActive().Tip(); CBlockIndex* next = new CBlockIndex(); next->phashBlock = new uint256(InsecureRand256()); pcoinsTip->SetBestBlock(next->GetBlockHash()); next->pprev = prev; next->nHeight = prev->nHeight + 1; next->BuildSkip(); - chainActive.SetTip(next); + ::ChainActive().SetTip(next); } BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); // Extend to a 210000-long block chain. - while (chainActive.Tip()->nHeight < 210000) { - CBlockIndex* prev = chainActive.Tip(); + while (::ChainActive().Tip()->nHeight < 210000) { + CBlockIndex* prev = ::ChainActive().Tip(); CBlockIndex* next = new CBlockIndex(); next->phashBlock = new uint256(InsecureRand256()); pcoinsTip->SetBestBlock(next->GetBlockHash()); next->pprev = prev; next->nHeight = prev->nHeight + 1; next->BuildSkip(); - chainActive.SetTip(next); + ::ChainActive().SetTip(next); } BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); @@ -398,29 +399,29 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vin[0].scriptSig = CScript() << OP_1; tx.vout[0].nValue = BLOCKSUBSIDY-LOWFEE; script = CScript() << OP_0; - tx.vout[0].scriptPubKey = GetScriptForDestination(CScriptID(script)); + tx.vout[0].scriptPubKey = GetScriptForDestination(ScriptHash(script)); hash = tx.GetHash(); - mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); tx.vin[0].prevout.hash = hash; tx.vin[0].scriptSig = CScript() << std::vector<unsigned char>(script.begin(), script.end()); tx.vout[0].nValue -= LOWFEE; hash = tx.GetHash(); - mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); + mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); // Should throw block-validation-failed BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("block-validation-failed")); mempool.clear(); // Delete the dummy blocks again. - while (chainActive.Tip()->nHeight > nHeight) { - CBlockIndex* del = chainActive.Tip(); - chainActive.SetTip(del->pprev); + while (::ChainActive().Tip()->nHeight > nHeight) { + CBlockIndex* del = ::ChainActive().Tip(); + ::ChainActive().SetTip(del->pprev); pcoinsTip->SetBestBlock(del->pprev->GetBlockHash()); delete del->phashBlock; delete del; } // non-final txs in mempool - SetMockTime(chainActive.Tip()->GetMedianTimePast()+1); + SetMockTime(::ChainActive().Tip()->GetMedianTimePast()+1); int flags = LOCKTIME_VERIFY_SEQUENCE|LOCKTIME_MEDIAN_TIME_PAST; // height map std::vector<int> prevheights; @@ -432,68 +433,68 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vin[0].prevout.hash = txFirst[0]->GetHash(); // only 1 transaction tx.vin[0].prevout.n = 0; tx.vin[0].scriptSig = CScript() << OP_1; - tx.vin[0].nSequence = chainActive.Tip()->nHeight + 1; // txFirst[0] is the 2nd block + tx.vin[0].nSequence = ::ChainActive().Tip()->nHeight + 1; // txFirst[0] is the 2nd block prevheights[0] = baseheight + 1; tx.vout.resize(1); tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE; tx.vout[0].scriptPubKey = CScript() << OP_1; tx.nLockTime = 0; hash = tx.GetHash(); - mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); - BOOST_CHECK(CheckFinalTx(tx, flags)); // Locktime passes - BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail - BOOST_CHECK(SequenceLocks(tx, flags, &prevheights, CreateBlockIndex(chainActive.Tip()->nHeight + 2))); // Sequence locks pass on 2nd block + mempool.addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + BOOST_CHECK(CheckFinalTx(CTransaction(tx), flags)); // Locktime passes + BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail + BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, &prevheights, CreateBlockIndex(::ChainActive().Tip()->nHeight + 2))); // Sequence locks pass on 2nd block // relative time locked tx.vin[0].prevout.hash = txFirst[1]->GetHash(); - tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | (((chainActive.Tip()->GetMedianTimePast()+1-chainActive[1]->GetMedianTimePast()) >> CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) + 1); // txFirst[1] is the 3rd block + tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | (((::ChainActive().Tip()->GetMedianTimePast()+1-::ChainActive()[1]->GetMedianTimePast()) >> CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) + 1); // txFirst[1] is the 3rd block prevheights[0] = baseheight + 2; hash = tx.GetHash(); - mempool.addUnchecked(hash, entry.Time(GetTime()).FromTx(tx)); - BOOST_CHECK(CheckFinalTx(tx, flags)); // Locktime passes - BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail + mempool.addUnchecked(entry.Time(GetTime()).FromTx(tx)); + BOOST_CHECK(CheckFinalTx(CTransaction(tx), flags)); // Locktime passes + BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++) - chainActive.Tip()->GetAncestor(chainActive.Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast - BOOST_CHECK(SequenceLocks(tx, flags, &prevheights, CreateBlockIndex(chainActive.Tip()->nHeight + 1))); // Sequence locks pass 512 seconds later + ::ChainActive().Tip()->GetAncestor(::ChainActive().Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast + BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, &prevheights, CreateBlockIndex(::ChainActive().Tip()->nHeight + 1))); // Sequence locks pass 512 seconds later for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++) - chainActive.Tip()->GetAncestor(chainActive.Tip()->nHeight - i)->nTime -= 512; //undo tricked MTP + ::ChainActive().Tip()->GetAncestor(::ChainActive().Tip()->nHeight - i)->nTime -= 512; //undo tricked MTP // absolute height locked tx.vin[0].prevout.hash = txFirst[2]->GetHash(); tx.vin[0].nSequence = CTxIn::SEQUENCE_FINAL - 1; prevheights[0] = baseheight + 3; - tx.nLockTime = chainActive.Tip()->nHeight + 1; + tx.nLockTime = ::ChainActive().Tip()->nHeight + 1; hash = tx.GetHash(); - mempool.addUnchecked(hash, entry.Time(GetTime()).FromTx(tx)); - BOOST_CHECK(!CheckFinalTx(tx, flags)); // Locktime fails - BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass - BOOST_CHECK(IsFinalTx(tx, chainActive.Tip()->nHeight + 2, chainActive.Tip()->GetMedianTimePast())); // Locktime passes on 2nd block + mempool.addUnchecked(entry.Time(GetTime()).FromTx(tx)); + BOOST_CHECK(!CheckFinalTx(CTransaction(tx), flags)); // Locktime fails + BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass + BOOST_CHECK(IsFinalTx(CTransaction(tx), ::ChainActive().Tip()->nHeight + 2, ::ChainActive().Tip()->GetMedianTimePast())); // Locktime passes on 2nd block // absolute time locked tx.vin[0].prevout.hash = txFirst[3]->GetHash(); - tx.nLockTime = chainActive.Tip()->GetMedianTimePast(); + tx.nLockTime = ::ChainActive().Tip()->GetMedianTimePast(); prevheights.resize(1); prevheights[0] = baseheight + 4; hash = tx.GetHash(); - mempool.addUnchecked(hash, entry.Time(GetTime()).FromTx(tx)); - BOOST_CHECK(!CheckFinalTx(tx, flags)); // Locktime fails - BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass - BOOST_CHECK(IsFinalTx(tx, chainActive.Tip()->nHeight + 2, chainActive.Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later + mempool.addUnchecked(entry.Time(GetTime()).FromTx(tx)); + BOOST_CHECK(!CheckFinalTx(CTransaction(tx), flags)); // Locktime fails + BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass + BOOST_CHECK(IsFinalTx(CTransaction(tx), ::ChainActive().Tip()->nHeight + 2, ::ChainActive().Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later // mempool-dependent transactions (not added) tx.vin[0].prevout.hash = hash; - prevheights[0] = chainActive.Tip()->nHeight + 1; + prevheights[0] = ::ChainActive().Tip()->nHeight + 1; tx.nLockTime = 0; tx.vin[0].nSequence = 0; - BOOST_CHECK(CheckFinalTx(tx, flags)); // Locktime passes - BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass + BOOST_CHECK(CheckFinalTx(CTransaction(tx), flags)); // Locktime passes + BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass tx.vin[0].nSequence = 1; - BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail + BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG; - BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass + BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | 1; - BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail + BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); @@ -504,14 +505,14 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 3U); // However if we advance height by 1 and time by 512, all of them should be mined for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++) - chainActive.Tip()->GetAncestor(chainActive.Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast - chainActive.Tip()->nHeight++; - SetMockTime(chainActive.Tip()->GetMedianTimePast() + 1); + ::ChainActive().Tip()->GetAncestor(::ChainActive().Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast + ::ChainActive().Tip()->nHeight++; + SetMockTime(::ChainActive().Tip()->GetMedianTimePast() + 1); BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5U); - chainActive.Tip()->nHeight--; + ::ChainActive().Tip()->nHeight--; SetMockTime(0); mempool.clear(); diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index 77db9f5c57..682f1bee26 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2017 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -11,7 +11,7 @@ #include <script/sign.h> #include <script/ismine.h> #include <uint256.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> @@ -76,20 +76,20 @@ BOOST_AUTO_TEST_CASE(multisig_verify) // Test a AND b: keys.assign(1,key[0]); keys.push_back(key[1]); - s = sign_multisig(a_and_b, keys, txTo[0], 0); + s = sign_multisig(a_and_b, keys, CTransaction(txTo[0]), 0); BOOST_CHECK(VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); for (int i = 0; i < 4; i++) { keys.assign(1,key[i]); - s = sign_multisig(a_and_b, keys, txTo[0], 0); + s = sign_multisig(a_and_b, keys, CTransaction(txTo[0]), 0); BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 1: %d", i)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err)); keys.assign(1,key[1]); keys.push_back(key[i]); - s = sign_multisig(a_and_b, keys, txTo[0], 0); + s = sign_multisig(a_and_b, keys, CTransaction(txTo[0]), 0); BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 2: %d", i)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); } @@ -98,7 +98,7 @@ BOOST_AUTO_TEST_CASE(multisig_verify) for (int i = 0; i < 4; i++) { keys.assign(1,key[i]); - s = sign_multisig(a_or_b, keys, txTo[1], 0); + s = sign_multisig(a_or_b, keys, CTransaction(txTo[1]), 0); if (i == 0 || i == 1) { BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i)); @@ -121,7 +121,7 @@ BOOST_AUTO_TEST_CASE(multisig_verify) { keys.assign(1,key[i]); keys.push_back(key[j]); - s = sign_multisig(escrow, keys, txTo[2], 0); + s = sign_multisig(escrow, keys, CTransaction(txTo[2]), 0); if (i < j && i < 3 && j < 3) { BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, nullptr, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 1: %d %d", i, j)); @@ -179,7 +179,7 @@ BOOST_AUTO_TEST_CASE(multisig_Sign) for (int i = 0; i < 4; i++) { key[i].MakeNewKey(true); - keystore.AddKey(key[i]); + BOOST_CHECK(keystore.AddKey(key[i])); } CScript a_and_b; @@ -209,7 +209,7 @@ BOOST_AUTO_TEST_CASE(multisig_Sign) for (int i = 0; i < 3; i++) { - BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i)); + BOOST_CHECK_MESSAGE(SignSignature(keystore, CTransaction(txFrom), txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i)); } } diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 42e615ab0c..54d18c0a1c 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -1,8 +1,8 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <addrman.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <string> #include <boost/test/unit_test.hpp> #include <hash.h> @@ -11,7 +11,7 @@ #include <net.h> #include <netbase.h> #include <chainparams.h> -#include <util.h> +#include <util/system.h> #include <memory> @@ -54,10 +54,10 @@ public: s << nUBuckets; CService serv; - Lookup("252.1.1.1", serv, 7777, false); + BOOST_CHECK(Lookup("252.1.1.1", serv, 7777, false)); CAddress addr = CAddress(serv, NODE_NONE); CNetAddr resolved; - LookupHost("252.2.2.2", resolved, false); + BOOST_CHECK(LookupHost("252.2.2.2", resolved, false)); CAddrInfo info = CAddrInfo(addr, resolved); s << info; } @@ -82,27 +82,28 @@ BOOST_AUTO_TEST_CASE(cnode_listen_port) BOOST_CHECK(port == Params().GetDefaultPort()); // test set port unsigned short altPort = 12345; - gArgs.SoftSetArg("-port", std::to_string(altPort)); + BOOST_CHECK(gArgs.SoftSetArg("-port", std::to_string(altPort))); port = GetListenPort(); BOOST_CHECK(port == altPort); } BOOST_AUTO_TEST_CASE(caddrdb_read) { + SetDataDir("caddrdb_read"); CAddrManUncorrupted addrmanUncorrupted; addrmanUncorrupted.MakeDeterministic(); CService addr1, addr2, addr3; - Lookup("250.7.1.1", addr1, 8333, false); - Lookup("250.7.2.2", addr2, 9999, false); - Lookup("250.7.3.3", addr3, 9999, false); + BOOST_CHECK(Lookup("250.7.1.1", addr1, 8333, false)); + BOOST_CHECK(Lookup("250.7.2.2", addr2, 9999, false)); + BOOST_CHECK(Lookup("250.7.3.3", addr3, 9999, false)); // Add three addresses to new table. CService source; - Lookup("252.5.1.1", source, 8333, false); - addrmanUncorrupted.Add(CAddress(addr1, NODE_NONE), source); - addrmanUncorrupted.Add(CAddress(addr2, NODE_NONE), source); - addrmanUncorrupted.Add(CAddress(addr3, NODE_NONE), source); + BOOST_CHECK(Lookup("252.5.1.1", source, 8333, false)); + BOOST_CHECK(addrmanUncorrupted.Add(CAddress(addr1, NODE_NONE), source)); + BOOST_CHECK(addrmanUncorrupted.Add(CAddress(addr2, NODE_NONE), source)); + BOOST_CHECK(addrmanUncorrupted.Add(CAddress(addr3, NODE_NONE), source)); // Test that the de-serialization does not throw an exception. CDataStream ssPeers1 = AddrmanToStream(addrmanUncorrupted); @@ -114,7 +115,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read) unsigned char pchMsgTmp[4]; ssPeers1 >> pchMsgTmp; ssPeers1 >> addrman1; - } catch (const std::exception& e) { + } catch (const std::exception&) { exceptionThrown = true; } @@ -127,13 +128,14 @@ BOOST_AUTO_TEST_CASE(caddrdb_read) CAddrMan addrman2; CAddrDB adb; BOOST_CHECK(addrman2.size() == 0); - adb.Read(addrman2, ssPeers2); + BOOST_CHECK(adb.Read(addrman2, ssPeers2)); BOOST_CHECK(addrman2.size() == 3); } BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted) { + SetDataDir("caddrdb_read_corrupted"); CAddrManCorrupted addrmanCorrupted; addrmanCorrupted.MakeDeterministic(); @@ -146,7 +148,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted) unsigned char pchMsgTmp[4]; ssPeers1 >> pchMsgTmp; ssPeers1 >> addrman1; - } catch (const std::exception& e) { + } catch (const std::exception&) { exceptionThrown = true; } // Even through de-serialization failed addrman is not left in a clean state. @@ -159,7 +161,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted) CAddrMan addrman2; CAddrDB adb; BOOST_CHECK(addrman2.size() == 0); - adb.Read(addrman2, ssPeers2); + BOOST_CHECK(!adb.Read(addrman2, ssPeers2)); BOOST_CHECK(addrman2.size() == 0); } @@ -171,20 +173,134 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test) in_addr ipv4Addr; ipv4Addr.s_addr = 0xa0b0c001; - + CAddress addr = CAddress(CService(ipv4Addr, 7777), NODE_NETWORK); std::string pszDest; bool fInboundIn = false; // Test that fFeeler is false by default. - std::unique_ptr<CNode> pnode1(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 0, 0, CAddress(), pszDest, fInboundIn)); + std::unique_ptr<CNode> pnode1 = MakeUnique<CNode>(id++, NODE_NETWORK, height, hSocket, addr, 0, 0, CAddress(), pszDest, fInboundIn); BOOST_CHECK(pnode1->fInbound == false); BOOST_CHECK(pnode1->fFeeler == false); fInboundIn = true; - std::unique_ptr<CNode> pnode2(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 1, 1, CAddress(), pszDest, fInboundIn)); + std::unique_ptr<CNode> pnode2 = MakeUnique<CNode>(id++, NODE_NETWORK, height, hSocket, addr, 1, 1, CAddress(), pszDest, fInboundIn); BOOST_CHECK(pnode2->fInbound == true); BOOST_CHECK(pnode2->fFeeler == false); } +// prior to PR #14728, this test triggers an undefined behavior +BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test) +{ + // set up local addresses; all that's necessary to reproduce the bug is + // that a normal IPv4 address is among the entries, but if this address is + // !IsRoutable the undefined behavior is easier to trigger deterministically + { + LOCK(cs_mapLocalHost); + in_addr ipv4AddrLocal; + ipv4AddrLocal.s_addr = 0x0100007f; + CNetAddr addr = CNetAddr(ipv4AddrLocal); + LocalServiceInfo lsi; + lsi.nScore = 23; + lsi.nPort = 42; + mapLocalHost[addr] = lsi; + } + + // create a peer with an IPv4 address + in_addr ipv4AddrPeer; + ipv4AddrPeer.s_addr = 0xa0b0c001; + CAddress addr = CAddress(CService(ipv4AddrPeer, 7777), NODE_NETWORK); + std::unique_ptr<CNode> pnode = MakeUnique<CNode>(0, NODE_NETWORK, 0, INVALID_SOCKET, addr, 0, 0, CAddress{}, std::string{}, false); + pnode->fSuccessfullyConnected.store(true); + + // the peer claims to be reaching us via IPv6 + in6_addr ipv6AddrLocal; + memset(ipv6AddrLocal.s6_addr, 0, 16); + ipv6AddrLocal.s6_addr[0] = 0xcc; + CAddress addrLocal = CAddress(CService(ipv6AddrLocal, 7777), NODE_NETWORK); + pnode->SetAddrLocal(addrLocal); + + // before patch, this causes undefined behavior detectable with clang's -fsanitize=memory + AdvertiseLocal(&*pnode); + + // suppress no-checks-run warning; if this test fails, it's by triggering a sanitizer + BOOST_CHECK(1); +} + + +BOOST_AUTO_TEST_CASE(LimitedAndReachable_Network) +{ + BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), true); + BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), true); + BOOST_CHECK_EQUAL(IsReachable(NET_ONION), true); + + SetReachable(NET_IPV4, false); + SetReachable(NET_IPV6, false); + SetReachable(NET_ONION, false); + + BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), false); + BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), false); + BOOST_CHECK_EQUAL(IsReachable(NET_ONION), false); + + SetReachable(NET_IPV4, true); + SetReachable(NET_IPV6, true); + SetReachable(NET_ONION, true); + + BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), true); + BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), true); + BOOST_CHECK_EQUAL(IsReachable(NET_ONION), true); +} + +BOOST_AUTO_TEST_CASE(LimitedAndReachable_NetworkCaseUnroutableAndInternal) +{ + BOOST_CHECK_EQUAL(IsReachable(NET_UNROUTABLE), true); + BOOST_CHECK_EQUAL(IsReachable(NET_INTERNAL), true); + + SetReachable(NET_UNROUTABLE, false); + SetReachable(NET_INTERNAL, false); + + BOOST_CHECK_EQUAL(IsReachable(NET_UNROUTABLE), true); // Ignored for both networks + BOOST_CHECK_EQUAL(IsReachable(NET_INTERNAL), true); +} + +CNetAddr UtilBuildAddress(unsigned char p1, unsigned char p2, unsigned char p3, unsigned char p4) +{ + unsigned char ip[] = {p1, p2, p3, p4}; + + struct sockaddr_in sa; + memset(&sa, 0, sizeof(sockaddr_in)); // initialize the memory block + memcpy(&(sa.sin_addr), &ip, sizeof(ip)); + return CNetAddr(sa.sin_addr); +} + + +BOOST_AUTO_TEST_CASE(LimitedAndReachable_CNetAddr) +{ + CNetAddr addr = UtilBuildAddress(0x001, 0x001, 0x001, 0x001); // 1.1.1.1 + + SetReachable(NET_IPV4, true); + BOOST_CHECK_EQUAL(IsReachable(addr), true); + + SetReachable(NET_IPV4, false); + BOOST_CHECK_EQUAL(IsReachable(addr), false); + + SetReachable(NET_IPV4, true); // have to reset this, because this is stateful. +} + + +BOOST_AUTO_TEST_CASE(LocalAddress_BasicLifecycle) +{ + CService addr = CService(UtilBuildAddress(0x002, 0x001, 0x001, 0x001), 1000); // 2.1.1.1:1000 + + SetReachable(NET_IPV4, true); + + BOOST_CHECK_EQUAL(IsLocal(addr), false); + BOOST_CHECK_EQUAL(AddLocal(addr, 1000), true); + BOOST_CHECK_EQUAL(IsLocal(addr), true); + + RemoveLocal(addr); + BOOST_CHECK_EQUAL(IsLocal(addr), false); +} + + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index 027214e512..dd5e3eb6d5 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -1,10 +1,10 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <netbase.h> -#include <test/test_bitcoin.h> -#include <utilstrencodings.h> +#include <test/setup_common.h> +#include <util/strencodings.h> #include <string> @@ -39,7 +39,7 @@ BOOST_AUTO_TEST_CASE(netbase_networks) BOOST_CHECK(ResolveIP("::1").GetNetwork() == NET_UNROUTABLE); 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(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() == NET_ONION); BOOST_CHECK(CreateInternal("foo.com").GetNetwork() == NET_INTERNAL); } @@ -82,10 +82,10 @@ bool static TestSplitHost(std::string test, std::string host, int port) BOOST_AUTO_TEST_CASE(netbase_splithost) { - BOOST_CHECK(TestSplitHost("www.bitcoin.org", "www.bitcoin.org", -1)); - BOOST_CHECK(TestSplitHost("[www.bitcoin.org]", "www.bitcoin.org", -1)); - BOOST_CHECK(TestSplitHost("www.bitcoin.org:80", "www.bitcoin.org", 80)); - BOOST_CHECK(TestSplitHost("[www.bitcoin.org]:80", "www.bitcoin.org", 80)); + BOOST_CHECK(TestSplitHost("www.bitcoincore.org", "www.bitcoincore.org", -1)); + BOOST_CHECK(TestSplitHost("[www.bitcoincore.org]", "www.bitcoincore.org", -1)); + BOOST_CHECK(TestSplitHost("www.bitcoincore.org:80", "www.bitcoincore.org", 80)); + BOOST_CHECK(TestSplitHost("[www.bitcoincore.org]:80", "www.bitcoincore.org", 80)); BOOST_CHECK(TestSplitHost("127.0.0.1", "127.0.0.1", -1)); BOOST_CHECK(TestSplitHost("127.0.0.1:8333", "127.0.0.1", 8333)); BOOST_CHECK(TestSplitHost("[127.0.0.1]", "127.0.0.1", -1)); @@ -293,7 +293,7 @@ BOOST_AUTO_TEST_CASE(netbase_getgroup) 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("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_ONION, 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 @@ -302,4 +302,22 @@ BOOST_AUTO_TEST_CASE(netbase_getgroup) BOOST_CHECK(CreateInternal("baz.net").GetGroup() == internal_group); } +BOOST_AUTO_TEST_CASE(netbase_parsenetwork) +{ + BOOST_CHECK_EQUAL(ParseNetwork("ipv4"), NET_IPV4); + BOOST_CHECK_EQUAL(ParseNetwork("ipv6"), NET_IPV6); + BOOST_CHECK_EQUAL(ParseNetwork("onion"), NET_ONION); + BOOST_CHECK_EQUAL(ParseNetwork("tor"), NET_ONION); + + BOOST_CHECK_EQUAL(ParseNetwork("IPv4"), NET_IPV4); + BOOST_CHECK_EQUAL(ParseNetwork("IPv6"), NET_IPV6); + BOOST_CHECK_EQUAL(ParseNetwork("ONION"), NET_ONION); + BOOST_CHECK_EQUAL(ParseNetwork("TOR"), NET_ONION); + + BOOST_CHECK_EQUAL(ParseNetwork(":)"), NET_UNROUTABLE); + BOOST_CHECK_EQUAL(ParseNetwork("tÖr"), NET_UNROUTABLE); + BOOST_CHECK_EQUAL(ParseNetwork("\xfe\xff"), NET_UNROUTABLE); + BOOST_CHECK_EQUAL(ParseNetwork(""), NET_UNROUTABLE); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index 4825c92296..c5513ae9fa 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -9,7 +9,7 @@ #include <uint256.h> #include <arith_uint256.h> #include <version.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <vector> diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp index 8d288ec993..149094fc00 100644 --- a/src/test/policyestimator_tests.cpp +++ b/src/test/policyestimator_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2017 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -6,9 +6,9 @@ #include <policy/fees.h> #include <txmempool.h> #include <uint256.h> -#include <util.h> +#include <util/system.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> @@ -18,6 +18,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) { CBlockPolicyEstimator feeEst; CTxMemPool mpool(&feeEst); + LOCK2(cs_main, mpool.cs); TestMemPoolEntryHelper entry; CAmount basefee(2000); CAmount deltaFee(100); @@ -43,7 +44,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) tx.vin[0].scriptSig = garbage; tx.vout.resize(1); tx.vout[0].nValue=0LL; - CFeeRate baseRate(basefee, GetVirtualTransactionSize(tx)); + CFeeRate baseRate(basefee, GetVirtualTransactionSize(CTransaction(tx))); // Create a fake block std::vector<CTransactionRef> block; @@ -57,7 +58,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) for (int k = 0; k < 4; k++) { // add 4 fee txs tx.vin[0].prevout.n = 10000*blocknum+100*j+k; // make transaction unique uint256 hash = tx.GetHash(); - mpool.addUnchecked(hash, entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx)); + mpool.addUnchecked(entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx)); txHashes[j].push_back(hash); } } @@ -128,7 +129,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) for (int k = 0; k < 4; k++) { // add 4 fee txs tx.vin[0].prevout.n = 10000*blocknum+100*j+k; uint256 hash = tx.GetHash(); - mpool.addUnchecked(hash, entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx)); + mpool.addUnchecked(entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx)); txHashes[j].push_back(hash); } } @@ -163,7 +164,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) for (int k = 0; k < 4; k++) { // add 4 fee txs tx.vin[0].prevout.n = 10000*blocknum+100*j+k; uint256 hash = tx.GetHash(); - mpool.addUnchecked(hash, entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx)); + mpool.addUnchecked(entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx)); CTransactionRef ptx = mpool.get(hash); if (ptx) block.push_back(ptx); diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 9abfd5ebd8..653433bfce 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -1,13 +1,13 @@ -// Copyright (c) 2015-2017 The Bitcoin Core developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2015-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <chain.h> #include <chainparams.h> #include <pow.h> #include <random.h> -#include <util.h> -#include <test/test_bitcoin.h> +#include <util/system.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index fe6f10d845..141be50f50 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2017 The Bitcoin Core developers +// Copyright (c) 2015-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -9,7 +9,7 @@ #include <serialize.h> #include <streams.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> @@ -36,7 +36,7 @@ class prevector_tester { { local_check(a == b); } - void local_check(bool b) + void local_check(bool b) { passed &= b; } @@ -189,8 +189,8 @@ public: prevector_tester() { SeedInsecureRand(); - rand_seed = insecure_rand_seed; - rand_cache = insecure_rand_ctx; + rand_seed = InsecureRand256(); + rand_cache = FastRandomContext(rand_seed); } }; diff --git a/src/test/raii_event_tests.cpp b/src/test/raii_event_tests.cpp index 7bc81c7f64..2b01acf7fa 100644 --- a/src/test/raii_event_tests.cpp +++ b/src/test/raii_event_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2017 The Bitcoin Core developers +// Copyright (c) 2016-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -12,7 +12,7 @@ #include <support/events.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <vector> @@ -41,7 +41,7 @@ BOOST_FIXTURE_TEST_SUITE(raii_event_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(raii_event_creation) { event_set_mem_functions(tag_malloc, realloc, tag_free); - + void* base_ptr = nullptr; { auto base = obtain_event_base(); @@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE(raii_event_creation) BOOST_CHECK(tags[base_ptr] == 1); } BOOST_CHECK(tags[base_ptr] == 0); - + void* event_ptr = nullptr; { auto base = obtain_event_base(); @@ -63,14 +63,14 @@ BOOST_AUTO_TEST_CASE(raii_event_creation) } BOOST_CHECK(tags[base_ptr] == 0); BOOST_CHECK(tags[event_ptr] == 0); - + event_set_mem_functions(malloc, realloc, free); } BOOST_AUTO_TEST_CASE(raii_event_order) { event_set_mem_functions(tag_malloc, realloc, tag_free); - + void* base_ptr = nullptr; void* event_ptr = nullptr; { diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp index 80a294d129..e6fbe2355d 100644 --- a/src/test/random_tests.cpp +++ b/src/test/random_tests.cpp @@ -1,10 +1,10 @@ -// Copyright (c) 2017 The Bitcoin Core developers +// Copyright (c) 2017-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <random.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> @@ -21,9 +21,14 @@ BOOST_AUTO_TEST_CASE(osrandom_tests) BOOST_AUTO_TEST_CASE(fastrandom_tests) { // Check that deterministic FastRandomContexts are deterministic + g_mock_deterministic_tests = true; FastRandomContext ctx1(true); FastRandomContext ctx2(true); + for (int i = 10; i > 0; --i) { + BOOST_CHECK_EQUAL(GetRand(std::numeric_limits<uint64_t>::max()), uint64_t{10393729187455219830U}); + BOOST_CHECK_EQUAL(GetRandInt(std::numeric_limits<int>::max()), int{769702006}); + } BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); BOOST_CHECK_EQUAL(ctx1.rand64(), ctx2.rand64()); @@ -38,11 +43,23 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests) 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)); + g_mock_deterministic_tests = false; + for (int i = 10; i > 0; --i) { + BOOST_CHECK(GetRand(std::numeric_limits<uint64_t>::max()) != uint64_t{10393729187455219830U}); + BOOST_CHECK(GetRandInt(std::numeric_limits<int>::max()) != int{769702006}); + } + { + FastRandomContext ctx3, ctx4; + BOOST_CHECK(ctx3.rand64() != ctx4.rand64()); // extremely unlikely to be equal + } + { + FastRandomContext ctx3, ctx4; + BOOST_CHECK(ctx3.rand256() != ctx4.rand256()); + } + { + FastRandomContext ctx3, ctx4; + BOOST_CHECK(ctx3.randbytes(7) != ctx4.randbytes(7)); + } } BOOST_AUTO_TEST_CASE(fastrandom_randbits) @@ -75,8 +92,42 @@ BOOST_AUTO_TEST_CASE(stdrandom_test) for (int j = 1; j <= 10; ++j) { BOOST_CHECK(std::find(test.begin(), test.end(), j) != test.end()); } + Shuffle(test.begin(), test.end(), ctx); + for (int j = 1; j <= 10; ++j) { + BOOST_CHECK(std::find(test.begin(), test.end(), j) != test.end()); + } } } +/** Test that Shuffle reaches every permutation with equal probability. */ +BOOST_AUTO_TEST_CASE(shuffle_stat_test) +{ + FastRandomContext ctx(true); + uint32_t counts[5 * 5 * 5 * 5 * 5] = {0}; + for (int i = 0; i < 12000; ++i) { + int data[5] = {0, 1, 2, 3, 4}; + Shuffle(std::begin(data), std::end(data), ctx); + int pos = data[0] + data[1] * 5 + data[2] * 25 + data[3] * 125 + data[4] * 625; + ++counts[pos]; + } + unsigned int sum = 0; + double chi_score = 0.0; + for (int i = 0; i < 5 * 5 * 5 * 5 * 5; ++i) { + int i1 = i % 5, i2 = (i / 5) % 5, i3 = (i / 25) % 5, i4 = (i / 125) % 5, i5 = i / 625; + uint32_t count = counts[i]; + if (i1 == i2 || i1 == i3 || i1 == i4 || i1 == i5 || i2 == i3 || i2 == i4 || i2 == i5 || i3 == i4 || i3 == i5 || i4 == i5) { + BOOST_CHECK(count == 0); + } else { + chi_score += ((count - 100.0) * (count - 100.0)) / 100.0; + BOOST_CHECK(count > 50); + BOOST_CHECK(count < 150); + sum += count; + } + } + BOOST_CHECK(chi_score > 58.1411); // 99.9999% confidence interval + BOOST_CHECK(chi_score < 210.275); + BOOST_CHECK_EQUAL(sum, 12000); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/reverselock_tests.cpp b/src/test/reverselock_tests.cpp index 0a91c65afa..69db9dcf4e 100644 --- a/src/test/reverselock_tests.cpp +++ b/src/test/reverselock_tests.cpp @@ -1,9 +1,9 @@ -// Copyright (c) 2015-2017 The Bitcoin Core developers +// Copyright (c) 2015-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <reverselock.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index da591547d7..07d1326bcb 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -1,21 +1,26 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <rpc/server.h> #include <rpc/client.h> +#include <rpc/util.h> #include <core_io.h> +#include <init.h> +#include <interfaces/chain.h> #include <key_io.h> #include <netbase.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/algorithm/string.hpp> #include <boost/test/unit_test.hpp> #include <univalue.h> +#include <rpc/blockchain.h> + UniValue CallRPC(std::string args) { std::vector<std::string> vArgs; @@ -26,10 +31,9 @@ UniValue CallRPC(std::string args) request.strMethod = strMethod; request.params = RPCConvertValues(strMethod, vArgs); request.fHelp = false; - BOOST_CHECK(tableRPC[strMethod]); - rpcfn_type method = tableRPC[strMethod]->actor; + if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished(); try { - UniValue result = (*method)(request); + UniValue result = tableRPC.execute(request); return result; } catch (const UniValue& objError) { @@ -110,19 +114,20 @@ BOOST_AUTO_TEST_CASE(rpc_rawsign) std::string notsigned = r.get_str(); std::string privkey1 = "\"KzsXybp9jX64P5ekX1KUxRQ79Jht9uzW7LorgwE65i5rWACL6LQe\""; std::string privkey2 = "\"Kyhdf5LuKTRx4ge69ybABsiUAWjVRK4XGxAKk2FQLp2HjGMy87Z4\""; + InitInterfaces interfaces; + interfaces.chain = interfaces::MakeChain(); + g_rpc_interfaces = &interfaces; r = CallRPC(std::string("signrawtransactionwithkey ")+notsigned+" [] "+prevout); BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == false); r = CallRPC(std::string("signrawtransactionwithkey ")+notsigned+" ["+privkey1+","+privkey2+"] "+prevout); BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == true); + g_rpc_interfaces = nullptr; } BOOST_AUTO_TEST_CASE(rpc_createraw_op_return) { BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"68656c6c6f776f726c64\"}")); - // Allow more than one data transaction output - BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"68656c6c6f776f726c64\",\"data\":\"68656c6c6f776f726c64\"}")); - // Key not "data" (bad address) BOOST_CHECK_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"somedata\":\"68656c6c6f776f726c64\"}"), std::runtime_error); @@ -336,4 +341,82 @@ BOOST_AUTO_TEST_CASE(rpc_convert_values_generatetoaddress) BOOST_CHECK_EQUAL(result[2].get_int(), 9); } +BOOST_AUTO_TEST_CASE(rpc_getblockstats_calculate_percentiles_by_weight) +{ + int64_t total_weight = 200; + std::vector<std::pair<CAmount, int64_t>> feerates; + CAmount result[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 }; + + for (int64_t i = 0; i < 100; i++) { + feerates.emplace_back(std::make_pair(1 ,1)); + } + + for (int64_t i = 0; i < 100; i++) { + feerates.emplace_back(std::make_pair(2 ,1)); + } + + CalculatePercentilesByWeight(result, feerates, total_weight); + BOOST_CHECK_EQUAL(result[0], 1); + BOOST_CHECK_EQUAL(result[1], 1); + BOOST_CHECK_EQUAL(result[2], 1); + BOOST_CHECK_EQUAL(result[3], 2); + BOOST_CHECK_EQUAL(result[4], 2); + + // Test with more pairs, and two pairs overlapping 2 percentiles. + total_weight = 100; + CAmount result2[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 }; + feerates.clear(); + + feerates.emplace_back(std::make_pair(1, 9)); + feerates.emplace_back(std::make_pair(2 , 16)); //10th + 25th percentile + feerates.emplace_back(std::make_pair(4 ,50)); //50th + 75th percentile + feerates.emplace_back(std::make_pair(5 ,10)); + feerates.emplace_back(std::make_pair(9 ,15)); // 90th percentile + + CalculatePercentilesByWeight(result2, feerates, total_weight); + + BOOST_CHECK_EQUAL(result2[0], 2); + BOOST_CHECK_EQUAL(result2[1], 2); + BOOST_CHECK_EQUAL(result2[2], 4); + BOOST_CHECK_EQUAL(result2[3], 4); + BOOST_CHECK_EQUAL(result2[4], 9); + + // Same test as above, but one of the percentile-overlapping pairs is split in 2. + total_weight = 100; + CAmount result3[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 }; + feerates.clear(); + + feerates.emplace_back(std::make_pair(1, 9)); + feerates.emplace_back(std::make_pair(2 , 11)); // 10th percentile + feerates.emplace_back(std::make_pair(2 , 5)); // 25th percentile + feerates.emplace_back(std::make_pair(4 ,50)); //50th + 75th percentile + feerates.emplace_back(std::make_pair(5 ,10)); + feerates.emplace_back(std::make_pair(9 ,15)); // 90th percentile + + CalculatePercentilesByWeight(result3, feerates, total_weight); + + BOOST_CHECK_EQUAL(result3[0], 2); + BOOST_CHECK_EQUAL(result3[1], 2); + BOOST_CHECK_EQUAL(result3[2], 4); + BOOST_CHECK_EQUAL(result3[3], 4); + BOOST_CHECK_EQUAL(result3[4], 9); + + // Test with one transaction spanning all percentiles. + total_weight = 104; + CAmount result4[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 }; + feerates.clear(); + + feerates.emplace_back(std::make_pair(1, 100)); + feerates.emplace_back(std::make_pair(2, 1)); + feerates.emplace_back(std::make_pair(3, 1)); + feerates.emplace_back(std::make_pair(3, 1)); + feerates.emplace_back(std::make_pair(999999, 1)); + + CalculatePercentilesByWeight(result4, feerates, total_weight); + + for (int64_t i = 0; i < NUM_GETBLOCKSTATS_PERCENTILES; i++) { + BOOST_CHECK_EQUAL(result4[i], 1); + } +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/sanity_tests.cpp b/src/test/sanity_tests.cpp index e97ad2ee6a..891aa8e5c3 100644 --- a/src/test/sanity_tests.cpp +++ b/src/test/sanity_tests.cpp @@ -1,10 +1,10 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <compat/sanity.h> #include <key.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp index 179df7dd38..42242b962b 100644 --- a/src/test/scheduler_tests.cpp +++ b/src/test/scheduler_tests.cpp @@ -1,13 +1,12 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <random.h> #include <scheduler.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> -#include <boost/bind.hpp> #include <boost/thread.hpp> #include <boost/test/unit_test.hpp> @@ -21,7 +20,7 @@ static void microTask(CScheduler& s, boost::mutex& mutex, int& counter, int delt } boost::chrono::system_clock::time_point noTime = boost::chrono::system_clock::time_point::min(); if (rescheduleTime != noTime) { - CScheduler::Function f = boost::bind(µTask, boost::ref(s), boost::ref(mutex), boost::ref(counter), -delta + 1, noTime); + CScheduler::Function f = std::bind(µTask, std::ref(s), std::ref(mutex), std::ref(counter), -delta + 1, noTime); s.schedule(f, rescheduleTime); } } @@ -54,7 +53,7 @@ BOOST_AUTO_TEST_CASE(manythreads) boost::mutex counterMutex[10]; int counter[10] = { 0 }; - FastRandomContext rng(42); + FastRandomContext rng{/* fDeterministic */ true}; auto zeroToNine = [](FastRandomContext& rc) -> int { return rc.randrange(10); }; // [0, 9] auto randomMsec = [](FastRandomContext& rc) -> int { return -11 + (int)rc.randrange(1012); }; // [-11, 1000] auto randomDelta = [](FastRandomContext& rc) -> int { return -1000 + (int)rc.randrange(2001); }; // [-1000, 1000] @@ -65,12 +64,12 @@ BOOST_AUTO_TEST_CASE(manythreads) size_t nTasks = microTasks.getQueueInfo(first, last); BOOST_CHECK(nTasks == 0); - for (int i = 0; i < 100; i++) { + for (int i = 0; i < 100; ++i) { boost::chrono::system_clock::time_point t = now + boost::chrono::microseconds(randomMsec(rng)); boost::chrono::system_clock::time_point tReschedule = now + boost::chrono::microseconds(500 + randomMsec(rng)); int whichCounter = zeroToNine(rng); - CScheduler::Function f = boost::bind(µTask, boost::ref(microTasks), - boost::ref(counterMutex[whichCounter]), boost::ref(counter[whichCounter]), + CScheduler::Function f = std::bind(µTask, std::ref(microTasks), + std::ref(counterMutex[whichCounter]), std::ref(counter[whichCounter]), randomDelta(rng), tReschedule); microTasks.schedule(f, t); } @@ -82,20 +81,20 @@ BOOST_AUTO_TEST_CASE(manythreads) // As soon as these are created they will start running and servicing the queue boost::thread_group microThreads; for (int i = 0; i < 5; i++) - microThreads.create_thread(boost::bind(&CScheduler::serviceQueue, µTasks)); + microThreads.create_thread(std::bind(&CScheduler::serviceQueue, µTasks)); MicroSleep(600); now = boost::chrono::system_clock::now(); // More threads and more tasks: for (int i = 0; i < 5; i++) - microThreads.create_thread(boost::bind(&CScheduler::serviceQueue, µTasks)); + microThreads.create_thread(std::bind(&CScheduler::serviceQueue, µTasks)); for (int i = 0; i < 100; i++) { boost::chrono::system_clock::time_point t = now + boost::chrono::microseconds(randomMsec(rng)); boost::chrono::system_clock::time_point tReschedule = now + boost::chrono::microseconds(500 + randomMsec(rng)); int whichCounter = zeroToNine(rng); - CScheduler::Function f = boost::bind(µTask, boost::ref(microTasks), - boost::ref(counterMutex[whichCounter]), boost::ref(counter[whichCounter]), + CScheduler::Function f = std::bind(µTask, std::ref(microTasks), + std::ref(counterMutex[whichCounter]), std::ref(counter[whichCounter]), randomDelta(rng), tReschedule); microTasks.schedule(f, t); } @@ -112,4 +111,48 @@ BOOST_AUTO_TEST_CASE(manythreads) BOOST_CHECK_EQUAL(counterSum, 200); } +BOOST_AUTO_TEST_CASE(singlethreadedscheduler_ordered) +{ + CScheduler scheduler; + + // each queue should be well ordered with respect to itself but not other queues + SingleThreadedSchedulerClient queue1(&scheduler); + SingleThreadedSchedulerClient queue2(&scheduler); + + // create more threads than queues + // if the queues only permit execution of one task at once then + // the extra threads should effectively be doing nothing + // if they don't we'll get out of order behaviour + boost::thread_group threads; + for (int i = 0; i < 5; ++i) { + threads.create_thread(std::bind(&CScheduler::serviceQueue, &scheduler)); + } + + // these are not atomic, if SinglethreadedSchedulerClient prevents + // parallel execution at the queue level no synchronization should be required here + int counter1 = 0; + int counter2 = 0; + + // just simply count up on each queue - if execution is properly ordered then + // the callbacks should run in exactly the order in which they were enqueued + for (int i = 0; i < 100; ++i) { + queue1.AddToProcessQueue([i, &counter1]() { + bool expectation = i == counter1++; + assert(expectation); + }); + + queue2.AddToProcessQueue([i, &counter2]() { + bool expectation = i == counter2++; + assert(expectation); + }); + } + + // finish up + scheduler.stop(true); + threads.join_all(); + + BOOST_CHECK_EQUAL(counter1, 100); + BOOST_CHECK_EQUAL(counter2, 100); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/script_p2sh_tests.cpp b/src/test/script_p2sh_tests.cpp index 803a673fab..9c4606f1b3 100644 --- a/src/test/script_p2sh_tests.cpp +++ b/src/test/script_p2sh_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -10,9 +10,10 @@ #include <policy/policy.h> #include <script/script.h> #include <script/script_error.h> +#include <policy/settings.h> #include <script/sign.h> #include <script/ismine.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <vector> @@ -61,21 +62,21 @@ BOOST_AUTO_TEST_CASE(sign) for (int i = 0; i < 4; i++) { key[i].MakeNewKey(true); - keystore.AddKey(key[i]); + BOOST_CHECK(keystore.AddKey(key[i])); } // 8 Scripts: checking all combinations of // different keys, straight/P2SH, pubkey/pubkeyhash CScript standardScripts[4]; standardScripts[0] << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG; - standardScripts[1] = GetScriptForDestination(key[1].GetPubKey().GetID()); + standardScripts[1] = GetScriptForDestination(PKHash(key[1].GetPubKey())); standardScripts[2] << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG; - standardScripts[3] = GetScriptForDestination(key[2].GetPubKey().GetID()); + standardScripts[3] = GetScriptForDestination(PKHash(key[2].GetPubKey())); CScript evalScripts[4]; for (int i = 0; i < 4; i++) { - keystore.AddCScript(standardScripts[i]); - evalScripts[i] = GetScriptForDestination(CScriptID(standardScripts[i])); + BOOST_CHECK(keystore.AddCScript(standardScripts[i])); + evalScripts[i] = GetScriptForDestination(ScriptHash(standardScripts[i])); } CMutableTransaction txFrom; // Funding transaction: @@ -88,7 +89,7 @@ BOOST_AUTO_TEST_CASE(sign) txFrom.vout[i+4].scriptPubKey = standardScripts[i]; txFrom.vout[i+4].nValue = COIN; } - BOOST_CHECK(IsStandardTx(txFrom, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(txFrom), reason)); CMutableTransaction txTo[8]; // Spending transactions for (int i = 0; i < 8; i++) @@ -102,7 +103,7 @@ BOOST_AUTO_TEST_CASE(sign) } for (int i = 0; i < 8; i++) { - BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i)); + BOOST_CHECK_MESSAGE(SignSignature(keystore, CTransaction(txFrom), txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i)); } // All of the above should be OK, and the txTos have valid signatures // Check to make sure signature verification fails if we use the wrong ScriptSig: @@ -112,7 +113,7 @@ BOOST_AUTO_TEST_CASE(sign) { CScript sigSave = txTo[i].vin[0].scriptSig; txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig; - bool sigOK = CScriptCheck(txFrom.vout[txTo[i].vin[0].prevout.n], txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, &txdata)(); + bool sigOK = CScriptCheck(txFrom.vout[txTo[i].vin[0].prevout.n], CTransaction(txTo[i]), 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, &txdata)(); if (i == j) BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j)); else @@ -130,7 +131,7 @@ BOOST_AUTO_TEST_CASE(norecurse) CScript invalidAsScript; invalidAsScript << OP_INVALIDOPCODE << OP_INVALIDOPCODE; - CScript p2sh = GetScriptForDestination(CScriptID(invalidAsScript)); + CScript p2sh = GetScriptForDestination(ScriptHash(invalidAsScript)); CScript scriptSig; scriptSig << Serialize(invalidAsScript); @@ -141,7 +142,7 @@ BOOST_AUTO_TEST_CASE(norecurse) // Try to recur, and verification should succeed because // the inner HASH160 <> EQUAL should only check the hash: - CScript p2sh2 = GetScriptForDestination(CScriptID(p2sh)); + CScript p2sh2 = GetScriptForDestination(ScriptHash(p2sh)); CScript scriptSig2; scriptSig2 << Serialize(invalidAsScript) << Serialize(p2sh); @@ -159,12 +160,12 @@ BOOST_AUTO_TEST_CASE(set) for (int i = 0; i < 4; i++) { key[i].MakeNewKey(true); - keystore.AddKey(key[i]); + BOOST_CHECK(keystore.AddKey(key[i])); keys.push_back(key[i].GetPubKey()); } CScript inner[4]; - inner[0] = GetScriptForDestination(key[0].GetPubKey().GetID()); + inner[0] = GetScriptForDestination(PKHash(key[0].GetPubKey())); inner[1] = GetScriptForMultisig(2, std::vector<CPubKey>(keys.begin(), keys.begin()+2)); inner[2] = GetScriptForMultisig(1, std::vector<CPubKey>(keys.begin(), keys.begin()+2)); inner[3] = GetScriptForMultisig(2, std::vector<CPubKey>(keys.begin(), keys.begin()+3)); @@ -172,8 +173,8 @@ BOOST_AUTO_TEST_CASE(set) CScript outer[4]; for (int i = 0; i < 4; i++) { - outer[i] = GetScriptForDestination(CScriptID(inner[i])); - keystore.AddCScript(inner[i]); + outer[i] = GetScriptForDestination(ScriptHash(inner[i])); + BOOST_CHECK(keystore.AddCScript(inner[i])); } CMutableTransaction txFrom; // Funding transaction: @@ -184,7 +185,7 @@ BOOST_AUTO_TEST_CASE(set) txFrom.vout[i].scriptPubKey = outer[i]; txFrom.vout[i].nValue = CENT; } - BOOST_CHECK(IsStandardTx(txFrom, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(txFrom), reason)); CMutableTransaction txTo[4]; // Spending transactions for (int i = 0; i < 4; i++) @@ -199,8 +200,8 @@ BOOST_AUTO_TEST_CASE(set) } for (int i = 0; i < 4; i++) { - BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i)); - BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i], reason), strprintf("txTo[%d].IsStandard", i)); + BOOST_CHECK_MESSAGE(SignSignature(keystore, CTransaction(txFrom), txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i)); + BOOST_CHECK_MESSAGE(IsStandardTx(CTransaction(txTo[i]), reason), strprintf("txTo[%d].IsStandard", i)); } } @@ -213,14 +214,22 @@ BOOST_AUTO_TEST_CASE(is) BOOST_CHECK(p2sh.IsPayToScriptHash()); // Not considered pay-to-script-hash if using one of the OP_PUSHDATA opcodes: - static const unsigned char direct[] = { OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL }; - BOOST_CHECK(CScript(direct, direct+sizeof(direct)).IsPayToScriptHash()); - static const unsigned char pushdata1[] = { OP_HASH160, OP_PUSHDATA1, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL }; - BOOST_CHECK(!CScript(pushdata1, pushdata1+sizeof(pushdata1)).IsPayToScriptHash()); - static const unsigned char pushdata2[] = { OP_HASH160, OP_PUSHDATA2, 20,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL }; - BOOST_CHECK(!CScript(pushdata2, pushdata2+sizeof(pushdata2)).IsPayToScriptHash()); - static const unsigned char pushdata4[] = { OP_HASH160, OP_PUSHDATA4, 20,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL }; - BOOST_CHECK(!CScript(pushdata4, pushdata4+sizeof(pushdata4)).IsPayToScriptHash()); + std::vector<unsigned char> direct = {OP_HASH160, 20}; + direct.insert(direct.end(), 20, 0); + direct.push_back(OP_EQUAL); + BOOST_CHECK(CScript(direct.begin(), direct.end()).IsPayToScriptHash()); + std::vector<unsigned char> pushdata1 = {OP_HASH160, OP_PUSHDATA1, 20}; + pushdata1.insert(pushdata1.end(), 20, 0); + pushdata1.push_back(OP_EQUAL); + BOOST_CHECK(!CScript(pushdata1.begin(), pushdata1.end()).IsPayToScriptHash()); + std::vector<unsigned char> pushdata2 = {OP_HASH160, 20, 0}; + pushdata2.insert(pushdata2.end(), 20, 0); + pushdata2.push_back(OP_EQUAL); + BOOST_CHECK(!CScript(pushdata2.begin(), pushdata2.end()).IsPayToScriptHash()); + std::vector<unsigned char> pushdata4 = {OP_HASH160, 20, 0, 0, 0}; + pushdata4.insert(pushdata4.end(), 20, 0); + pushdata4.push_back(OP_EQUAL); + BOOST_CHECK(!CScript(pushdata4.begin(), pushdata4.end()).IsPayToScriptHash()); CScript not_p2sh; BOOST_CHECK(!not_p2sh.IsPayToScriptHash()); @@ -244,7 +253,7 @@ BOOST_AUTO_TEST_CASE(switchover) CScript scriptSig; scriptSig << Serialize(notValid); - CScript fund = GetScriptForDestination(CScriptID(notValid)); + CScript fund = GetScriptForDestination(ScriptHash(notValid)); // Validation should succeed under old rules (hash is correct): @@ -266,7 +275,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) for (int i = 0; i < 6; i++) { key[i].MakeNewKey(true); - keystore.AddKey(key[i]); + BOOST_CHECK(keystore.AddKey(key[i])); } for (int i = 0; i < 3; i++) keys.push_back(key[i].GetPubKey()); @@ -275,11 +284,11 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) txFrom.vout.resize(7); // First three are standard: - CScript pay1 = GetScriptForDestination(key[0].GetPubKey().GetID()); - keystore.AddCScript(pay1); + CScript pay1 = GetScriptForDestination(PKHash(key[0].GetPubKey())); + BOOST_CHECK(keystore.AddCScript(pay1)); CScript pay1of3 = GetScriptForMultisig(1, keys); - txFrom.vout[0].scriptPubKey = GetScriptForDestination(CScriptID(pay1)); // P2SH (OP_CHECKSIG) + txFrom.vout[0].scriptPubKey = GetScriptForDestination(ScriptHash(pay1)); // P2SH (OP_CHECKSIG) txFrom.vout[0].nValue = 1000; txFrom.vout[1].scriptPubKey = pay1; // ordinary OP_CHECKSIG txFrom.vout[1].nValue = 2000; @@ -293,8 +302,8 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) oneAndTwo << OP_3 << OP_CHECKMULTISIGVERIFY; oneAndTwo << OP_2 << ToByteVector(key[3].GetPubKey()) << ToByteVector(key[4].GetPubKey()) << ToByteVector(key[5].GetPubKey()); oneAndTwo << OP_3 << OP_CHECKMULTISIG; - keystore.AddCScript(oneAndTwo); - txFrom.vout[3].scriptPubKey = GetScriptForDestination(CScriptID(oneAndTwo)); + BOOST_CHECK(keystore.AddCScript(oneAndTwo)); + txFrom.vout[3].scriptPubKey = GetScriptForDestination(ScriptHash(oneAndTwo)); txFrom.vout[3].nValue = 4000; // vout[4] is max sigops: @@ -302,25 +311,25 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) for (unsigned i = 0; i < MAX_P2SH_SIGOPS; i++) fifteenSigops << ToByteVector(key[i%3].GetPubKey()); fifteenSigops << OP_15 << OP_CHECKMULTISIG; - keystore.AddCScript(fifteenSigops); - txFrom.vout[4].scriptPubKey = GetScriptForDestination(CScriptID(fifteenSigops)); + BOOST_CHECK(keystore.AddCScript(fifteenSigops)); + txFrom.vout[4].scriptPubKey = GetScriptForDestination(ScriptHash(fifteenSigops)); txFrom.vout[4].nValue = 5000; // vout[5/6] are non-standard because they exceed MAX_P2SH_SIGOPS CScript sixteenSigops; sixteenSigops << OP_16 << OP_CHECKMULTISIG; - keystore.AddCScript(sixteenSigops); - txFrom.vout[5].scriptPubKey = GetScriptForDestination(CScriptID(fifteenSigops)); + BOOST_CHECK(keystore.AddCScript(sixteenSigops)); + txFrom.vout[5].scriptPubKey = GetScriptForDestination(ScriptHash(sixteenSigops)); txFrom.vout[5].nValue = 5000; CScript twentySigops; twentySigops << OP_CHECKMULTISIG; - keystore.AddCScript(twentySigops); - txFrom.vout[6].scriptPubKey = GetScriptForDestination(CScriptID(twentySigops)); + BOOST_CHECK(keystore.AddCScript(twentySigops)); + txFrom.vout[6].scriptPubKey = GetScriptForDestination(ScriptHash(twentySigops)); txFrom.vout[6].nValue = 6000; - AddCoins(coins, txFrom, 0); + AddCoins(coins, CTransaction(txFrom), 0); CMutableTransaction txTo; txTo.vout.resize(1); - txTo.vout[0].scriptPubKey = GetScriptForDestination(key[1].GetPubKey().GetID()); + txTo.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[1].GetPubKey())); txTo.vin.resize(5); for (int i = 0; i < 5; i++) @@ -328,42 +337,42 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) txTo.vin[i].prevout.n = i; txTo.vin[i].prevout.hash = txFrom.GetHash(); } - BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL)); - BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 1, SIGHASH_ALL)); - BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2, SIGHASH_ALL)); + BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 0, SIGHASH_ALL)); + BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 1, SIGHASH_ALL)); + BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 2, SIGHASH_ALL)); // SignSignature doesn't know how to sign these. We're // not testing validating signatures, so just create // dummy signatures that DO include the correct P2SH scripts: txTo.vin[3].scriptSig << OP_11 << OP_11 << std::vector<unsigned char>(oneAndTwo.begin(), oneAndTwo.end()); txTo.vin[4].scriptSig << std::vector<unsigned char>(fifteenSigops.begin(), fifteenSigops.end()); - BOOST_CHECK(::AreInputsStandard(txTo, coins)); + BOOST_CHECK(::AreInputsStandard(CTransaction(txTo), coins)); // 22 P2SH sigops for all inputs (1 for vin[0], 6 for vin[3], 15 for vin[4] - BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txTo, coins), 22U); + BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txTo), coins), 22U); CMutableTransaction txToNonStd1; txToNonStd1.vout.resize(1); - txToNonStd1.vout[0].scriptPubKey = GetScriptForDestination(key[1].GetPubKey().GetID()); + txToNonStd1.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[1].GetPubKey())); txToNonStd1.vout[0].nValue = 1000; txToNonStd1.vin.resize(1); txToNonStd1.vin[0].prevout.n = 5; txToNonStd1.vin[0].prevout.hash = txFrom.GetHash(); txToNonStd1.vin[0].scriptSig << std::vector<unsigned char>(sixteenSigops.begin(), sixteenSigops.end()); - BOOST_CHECK(!::AreInputsStandard(txToNonStd1, coins)); - BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txToNonStd1, coins), 16U); + BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd1), coins)); + BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txToNonStd1), coins), 16U); CMutableTransaction txToNonStd2; txToNonStd2.vout.resize(1); - txToNonStd2.vout[0].scriptPubKey = GetScriptForDestination(key[1].GetPubKey().GetID()); + txToNonStd2.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[1].GetPubKey())); txToNonStd2.vout[0].nValue = 1000; txToNonStd2.vin.resize(1); txToNonStd2.vin[0].prevout.n = 6; txToNonStd2.vin[0].prevout.hash = txFrom.GetHash(); txToNonStd2.vin[0].scriptSig << std::vector<unsigned char>(twentySigops.begin(), twentySigops.end()); - BOOST_CHECK(!::AreInputsStandard(txToNonStd2, coins)); - BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txToNonStd2, coins), 20U); + BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd2), coins)); + BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txToNonStd2), coins), 20U); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/script_standard_tests.cpp b/src/test/script_standard_tests.cpp index 7ab0978228..9f50083335 100644 --- a/src/test/script_standard_tests.cpp +++ b/src/test/script_standard_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017 The Bitcoin Core developers +// Copyright (c) 2017-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -8,7 +8,7 @@ #include <script/script.h> #include <script/script_error.h> #include <script/standard.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> @@ -25,22 +25,19 @@ BOOST_AUTO_TEST_CASE(script_standard_Solver_success) } CScript s; - txnouttype whichType; std::vector<std::vector<unsigned char> > solutions; // TX_PUBKEY s.clear(); s << ToByteVector(pubkeys[0]) << OP_CHECKSIG; - BOOST_CHECK(Solver(s, whichType, solutions)); - BOOST_CHECK_EQUAL(whichType, TX_PUBKEY); + BOOST_CHECK_EQUAL(Solver(s, solutions), TX_PUBKEY); BOOST_CHECK_EQUAL(solutions.size(), 1U); BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0])); // TX_PUBKEYHASH s.clear(); s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; - BOOST_CHECK(Solver(s, whichType, solutions)); - BOOST_CHECK_EQUAL(whichType, TX_PUBKEYHASH); + BOOST_CHECK_EQUAL(Solver(s, solutions), TX_PUBKEYHASH); BOOST_CHECK_EQUAL(solutions.size(), 1U); BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID())); @@ -48,8 +45,7 @@ BOOST_AUTO_TEST_CASE(script_standard_Solver_success) CScript redeemScript(s); // initialize with leftover P2PKH script s.clear(); s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; - BOOST_CHECK(Solver(s, whichType, solutions)); - BOOST_CHECK_EQUAL(whichType, TX_SCRIPTHASH); + BOOST_CHECK_EQUAL(Solver(s, solutions), TX_SCRIPTHASH); BOOST_CHECK_EQUAL(solutions.size(), 1U); BOOST_CHECK(solutions[0] == ToByteVector(CScriptID(redeemScript))); @@ -59,8 +55,7 @@ BOOST_AUTO_TEST_CASE(script_standard_Solver_success) ToByteVector(pubkeys[0]) << ToByteVector(pubkeys[1]) << OP_2 << OP_CHECKMULTISIG; - BOOST_CHECK(Solver(s, whichType, solutions)); - BOOST_CHECK_EQUAL(whichType, TX_MULTISIG); + BOOST_CHECK_EQUAL(Solver(s, solutions), TX_MULTISIG); BOOST_CHECK_EQUAL(solutions.size(), 4U); BOOST_CHECK(solutions[0] == std::vector<unsigned char>({1})); BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0])); @@ -73,8 +68,7 @@ BOOST_AUTO_TEST_CASE(script_standard_Solver_success) ToByteVector(pubkeys[1]) << ToByteVector(pubkeys[2]) << OP_3 << OP_CHECKMULTISIG; - BOOST_CHECK(Solver(s, whichType, solutions)); - BOOST_CHECK_EQUAL(whichType, TX_MULTISIG); + BOOST_CHECK_EQUAL(Solver(s, solutions), TX_MULTISIG); BOOST_CHECK_EQUAL(solutions.size(), 5U); BOOST_CHECK(solutions[0] == std::vector<unsigned char>({2})); BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0])); @@ -88,15 +82,13 @@ BOOST_AUTO_TEST_CASE(script_standard_Solver_success) std::vector<unsigned char>({0}) << std::vector<unsigned char>({75}) << std::vector<unsigned char>({255}); - BOOST_CHECK(Solver(s, whichType, solutions)); - BOOST_CHECK_EQUAL(whichType, TX_NULL_DATA); + BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NULL_DATA); BOOST_CHECK_EQUAL(solutions.size(), 0U); // TX_WITNESS_V0_KEYHASH s.clear(); s << OP_0 << ToByteVector(pubkeys[0].GetID()); - BOOST_CHECK(Solver(s, whichType, solutions)); - BOOST_CHECK_EQUAL(whichType, TX_WITNESS_V0_KEYHASH); + BOOST_CHECK_EQUAL(Solver(s, solutions), TX_WITNESS_V0_KEYHASH); BOOST_CHECK_EQUAL(solutions.size(), 1U); BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID())); @@ -107,16 +99,14 @@ BOOST_AUTO_TEST_CASE(script_standard_Solver_success) s.clear(); s << OP_0 << ToByteVector(scriptHash); - BOOST_CHECK(Solver(s, whichType, solutions)); - BOOST_CHECK_EQUAL(whichType, TX_WITNESS_V0_SCRIPTHASH); + BOOST_CHECK_EQUAL(Solver(s, solutions), TX_WITNESS_V0_SCRIPTHASH); BOOST_CHECK_EQUAL(solutions.size(), 1U); BOOST_CHECK(solutions[0] == ToByteVector(scriptHash)); // TX_NONSTANDARD s.clear(); s << OP_9 << OP_ADD << OP_11 << OP_EQUAL; - BOOST_CHECK(!Solver(s, whichType, solutions)); - BOOST_CHECK_EQUAL(whichType, TX_NONSTANDARD); + BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD); } BOOST_AUTO_TEST_CASE(script_standard_Solver_failure) @@ -127,53 +117,52 @@ BOOST_AUTO_TEST_CASE(script_standard_Solver_failure) pubkey = key.GetPubKey(); CScript s; - txnouttype whichType; std::vector<std::vector<unsigned char> > solutions; // TX_PUBKEY with incorrectly sized pubkey s.clear(); s << std::vector<unsigned char>(30, 0x01) << OP_CHECKSIG; - BOOST_CHECK(!Solver(s, whichType, solutions)); + BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD); // TX_PUBKEYHASH with incorrectly sized key hash s.clear(); s << OP_DUP << OP_HASH160 << ToByteVector(pubkey) << OP_EQUALVERIFY << OP_CHECKSIG; - BOOST_CHECK(!Solver(s, whichType, solutions)); + BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD); // TX_SCRIPTHASH with incorrectly sized script hash s.clear(); s << OP_HASH160 << std::vector<unsigned char>(21, 0x01) << OP_EQUAL; - BOOST_CHECK(!Solver(s, whichType, solutions)); + BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD); // TX_MULTISIG 0/2 s.clear(); s << OP_0 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG; - BOOST_CHECK(!Solver(s, whichType, solutions)); + BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD); // TX_MULTISIG 2/1 s.clear(); s << OP_2 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG; - BOOST_CHECK(!Solver(s, whichType, solutions)); + BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD); // TX_MULTISIG n = 2 with 1 pubkey s.clear(); s << OP_1 << ToByteVector(pubkey) << OP_2 << OP_CHECKMULTISIG; - BOOST_CHECK(!Solver(s, whichType, solutions)); + BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD); // TX_MULTISIG n = 1 with 0 pubkeys s.clear(); s << OP_1 << OP_1 << OP_CHECKMULTISIG; - BOOST_CHECK(!Solver(s, whichType, solutions)); + BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD); // TX_NULL_DATA with other opcodes s.clear(); s << OP_RETURN << std::vector<unsigned char>({75}) << OP_ADD; - BOOST_CHECK(!Solver(s, whichType, solutions)); + BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD); // TX_WITNESS with incorrect program size s.clear(); s << OP_0 << std::vector<unsigned char>(19, 0x01); - BOOST_CHECK(!Solver(s, whichType, solutions)); + BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD); } BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination) @@ -190,23 +179,23 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination) s.clear(); s << ToByteVector(pubkey) << OP_CHECKSIG; BOOST_CHECK(ExtractDestination(s, address)); - BOOST_CHECK(boost::get<CKeyID>(&address) && - *boost::get<CKeyID>(&address) == pubkey.GetID()); + BOOST_CHECK(boost::get<PKHash>(&address) && + *boost::get<PKHash>(&address) == PKHash(pubkey)); // TX_PUBKEYHASH s.clear(); s << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; BOOST_CHECK(ExtractDestination(s, address)); - BOOST_CHECK(boost::get<CKeyID>(&address) && - *boost::get<CKeyID>(&address) == pubkey.GetID()); + BOOST_CHECK(boost::get<PKHash>(&address) && + *boost::get<PKHash>(&address) == PKHash(pubkey)); // TX_SCRIPTHASH CScript redeemScript(s); // initialize with leftover P2PKH script s.clear(); s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; BOOST_CHECK(ExtractDestination(s, address)); - BOOST_CHECK(boost::get<CScriptID>(&address) && - *boost::get<CScriptID>(&address) == CScriptID(redeemScript)); + BOOST_CHECK(boost::get<ScriptHash>(&address) && + *boost::get<ScriptHash>(&address) == ScriptHash(redeemScript)); // TX_MULTISIG s.clear(); @@ -266,8 +255,8 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations) BOOST_CHECK_EQUAL(whichType, TX_PUBKEY); BOOST_CHECK_EQUAL(addresses.size(), 1U); BOOST_CHECK_EQUAL(nRequired, 1); - BOOST_CHECK(boost::get<CKeyID>(&addresses[0]) && - *boost::get<CKeyID>(&addresses[0]) == pubkeys[0].GetID()); + BOOST_CHECK(boost::get<PKHash>(&addresses[0]) && + *boost::get<PKHash>(&addresses[0]) == PKHash(pubkeys[0])); // TX_PUBKEYHASH s.clear(); @@ -276,8 +265,8 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations) BOOST_CHECK_EQUAL(whichType, TX_PUBKEYHASH); BOOST_CHECK_EQUAL(addresses.size(), 1U); BOOST_CHECK_EQUAL(nRequired, 1); - BOOST_CHECK(boost::get<CKeyID>(&addresses[0]) && - *boost::get<CKeyID>(&addresses[0]) == pubkeys[0].GetID()); + BOOST_CHECK(boost::get<PKHash>(&addresses[0]) && + *boost::get<PKHash>(&addresses[0]) == PKHash(pubkeys[0])); // TX_SCRIPTHASH CScript redeemScript(s); // initialize with leftover P2PKH script @@ -287,8 +276,8 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations) BOOST_CHECK_EQUAL(whichType, TX_SCRIPTHASH); BOOST_CHECK_EQUAL(addresses.size(), 1U); BOOST_CHECK_EQUAL(nRequired, 1); - BOOST_CHECK(boost::get<CScriptID>(&addresses[0]) && - *boost::get<CScriptID>(&addresses[0]) == CScriptID(redeemScript)); + BOOST_CHECK(boost::get<ScriptHash>(&addresses[0]) && + *boost::get<ScriptHash>(&addresses[0]) == ScriptHash(redeemScript)); // TX_MULTISIG s.clear(); @@ -300,10 +289,10 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations) BOOST_CHECK_EQUAL(whichType, TX_MULTISIG); BOOST_CHECK_EQUAL(addresses.size(), 2U); BOOST_CHECK_EQUAL(nRequired, 2); - BOOST_CHECK(boost::get<CKeyID>(&addresses[0]) && - *boost::get<CKeyID>(&addresses[0]) == pubkeys[0].GetID()); - BOOST_CHECK(boost::get<CKeyID>(&addresses[1]) && - *boost::get<CKeyID>(&addresses[1]) == pubkeys[1].GetID()); + BOOST_CHECK(boost::get<PKHash>(&addresses[0]) && + *boost::get<PKHash>(&addresses[0]) == PKHash(pubkeys[0])); + BOOST_CHECK(boost::get<PKHash>(&addresses[1]) && + *boost::get<PKHash>(&addresses[1]) == PKHash(pubkeys[1])); // TX_NULL_DATA s.clear(); @@ -322,17 +311,17 @@ BOOST_AUTO_TEST_CASE(script_standard_GetScriptFor_) CScript expected, result; - // CKeyID + // PKHash expected.clear(); expected << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; - result = GetScriptForDestination(pubkeys[0].GetID()); + result = GetScriptForDestination(PKHash(pubkeys[0])); BOOST_CHECK(result == expected); // CScriptID CScript redeemScript(result); expected.clear(); expected << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; - result = GetScriptForDestination(CScriptID(redeemScript)); + result = GetScriptForDestination(ScriptHash(redeemScript)); BOOST_CHECK(result == expected); // CNoDestination @@ -398,371 +387,348 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine) CScript scriptPubKey; isminetype result; - bool isInvalid; // P2PK compressed { CBasicKeyStore keystore; - scriptPubKey.clear(); - scriptPubKey << ToByteVector(pubkeys[0]) << OP_CHECKSIG; + scriptPubKey = GetScriptForRawPubKey(pubkeys[0]); // Keystore does not have key - result = IsMine(keystore, scriptPubKey, isInvalid); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); // Keystore has key - keystore.AddKey(keys[0]); - result = IsMine(keystore, scriptPubKey, isInvalid); + BOOST_CHECK(keystore.AddKey(keys[0])); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); - BOOST_CHECK(!isInvalid); } // P2PK uncompressed { CBasicKeyStore keystore; - scriptPubKey.clear(); - scriptPubKey << ToByteVector(uncompressedPubkey) << OP_CHECKSIG; + scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey); // Keystore does not have key - result = IsMine(keystore, scriptPubKey, isInvalid); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); // Keystore has key - keystore.AddKey(uncompressedKey); - result = IsMine(keystore, scriptPubKey, isInvalid); + BOOST_CHECK(keystore.AddKey(uncompressedKey)); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); - BOOST_CHECK(!isInvalid); } // P2PKH compressed { CBasicKeyStore keystore; - scriptPubKey.clear(); - scriptPubKey << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; + scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0])); // Keystore does not have key - result = IsMine(keystore, scriptPubKey, isInvalid); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); // Keystore has key - keystore.AddKey(keys[0]); - result = IsMine(keystore, scriptPubKey, isInvalid); + BOOST_CHECK(keystore.AddKey(keys[0])); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); - BOOST_CHECK(!isInvalid); } // P2PKH uncompressed { CBasicKeyStore keystore; - scriptPubKey.clear(); - scriptPubKey << OP_DUP << OP_HASH160 << ToByteVector(uncompressedPubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; + scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey)); // Keystore does not have key - result = IsMine(keystore, scriptPubKey, isInvalid); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); // Keystore has key - keystore.AddKey(uncompressedKey); - result = IsMine(keystore, scriptPubKey, isInvalid); + BOOST_CHECK(keystore.AddKey(uncompressedKey)); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); - BOOST_CHECK(!isInvalid); } // P2SH { CBasicKeyStore keystore; - CScript redeemScript; - redeemScript << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; - - scriptPubKey.clear(); - scriptPubKey << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; + CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0])); + scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript)); // Keystore does not have redeemScript or key - result = IsMine(keystore, scriptPubKey, isInvalid); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); // Keystore has redeemScript but no key - keystore.AddCScript(redeemScript); - result = IsMine(keystore, scriptPubKey, isInvalid); + BOOST_CHECK(keystore.AddCScript(redeemScript)); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); // Keystore has redeemScript and key - keystore.AddKey(keys[0]); - result = IsMine(keystore, scriptPubKey, isInvalid); + BOOST_CHECK(keystore.AddKey(keys[0])); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); - BOOST_CHECK(!isInvalid); + } + + // (P2PKH inside) P2SH inside P2SH (invalid) + { + CBasicKeyStore keystore; + + CScript redeemscript_inner = GetScriptForDestination(PKHash(pubkeys[0])); + CScript redeemscript = GetScriptForDestination(ScriptHash(redeemscript_inner)); + scriptPubKey = GetScriptForDestination(ScriptHash(redeemscript)); + + BOOST_CHECK(keystore.AddCScript(redeemscript)); + BOOST_CHECK(keystore.AddCScript(redeemscript_inner)); + BOOST_CHECK(keystore.AddCScript(scriptPubKey)); + BOOST_CHECK(keystore.AddKey(keys[0])); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + } + + // (P2PKH inside) P2SH inside P2WSH (invalid) + { + CBasicKeyStore keystore; + + CScript redeemscript = GetScriptForDestination(PKHash(pubkeys[0])); + CScript witnessscript = GetScriptForDestination(ScriptHash(redeemscript)); + scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript)); + + BOOST_CHECK(keystore.AddCScript(witnessscript)); + BOOST_CHECK(keystore.AddCScript(redeemscript)); + BOOST_CHECK(keystore.AddCScript(scriptPubKey)); + BOOST_CHECK(keystore.AddKey(keys[0])); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + } + + // P2WPKH inside P2WSH (invalid) + { + CBasicKeyStore keystore; + + CScript witnessscript = GetScriptForDestination(WitnessV0KeyHash(PKHash(pubkeys[0]))); + scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript)); + + BOOST_CHECK(keystore.AddCScript(witnessscript)); + BOOST_CHECK(keystore.AddCScript(scriptPubKey)); + BOOST_CHECK(keystore.AddKey(keys[0])); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + } + + // (P2PKH inside) P2WSH inside P2WSH (invalid) + { + CBasicKeyStore keystore; + + CScript witnessscript_inner = GetScriptForDestination(PKHash(pubkeys[0])); + CScript witnessscript = GetScriptForDestination(WitnessV0ScriptHash(witnessscript_inner)); + scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript)); + + BOOST_CHECK(keystore.AddCScript(witnessscript_inner)); + BOOST_CHECK(keystore.AddCScript(witnessscript)); + BOOST_CHECK(keystore.AddCScript(scriptPubKey)); + BOOST_CHECK(keystore.AddKey(keys[0])); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); } // P2WPKH compressed { CBasicKeyStore keystore; - keystore.AddKey(keys[0]); + BOOST_CHECK(keystore.AddKey(keys[0])); - scriptPubKey.clear(); - scriptPubKey << OP_0 << ToByteVector(pubkeys[0].GetID()); + scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(PKHash(pubkeys[0]))); // Keystore implicitly has key and P2SH redeemScript - keystore.AddCScript(scriptPubKey); - result = IsMine(keystore, scriptPubKey, isInvalid); + BOOST_CHECK(keystore.AddCScript(scriptPubKey)); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); - BOOST_CHECK(!isInvalid); } // P2WPKH uncompressed { CBasicKeyStore keystore; - keystore.AddKey(uncompressedKey); + BOOST_CHECK(keystore.AddKey(uncompressedKey)); - scriptPubKey.clear(); - scriptPubKey << OP_0 << ToByteVector(uncompressedPubkey.GetID()); + scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(PKHash(uncompressedPubkey))); // Keystore has key, but no P2SH redeemScript - result = IsMine(keystore, scriptPubKey, isInvalid); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); // Keystore has key and P2SH redeemScript - keystore.AddCScript(scriptPubKey); - result = IsMine(keystore, scriptPubKey, isInvalid); + BOOST_CHECK(keystore.AddCScript(scriptPubKey)); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(isInvalid); } // scriptPubKey multisig { CBasicKeyStore keystore; - scriptPubKey.clear(); - scriptPubKey << OP_2 << - ToByteVector(uncompressedPubkey) << - ToByteVector(pubkeys[1]) << - OP_2 << OP_CHECKMULTISIG; + scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]}); // Keystore does not have any keys - result = IsMine(keystore, scriptPubKey, isInvalid); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); // Keystore has 1/2 keys - keystore.AddKey(uncompressedKey); + BOOST_CHECK(keystore.AddKey(uncompressedKey)); - result = IsMine(keystore, scriptPubKey, isInvalid); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); // Keystore has 2/2 keys - keystore.AddKey(keys[1]); + BOOST_CHECK(keystore.AddKey(keys[1])); - result = IsMine(keystore, scriptPubKey, isInvalid); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); // Keystore has 2/2 keys and the script - keystore.AddCScript(scriptPubKey); + BOOST_CHECK(keystore.AddCScript(scriptPubKey)); - result = IsMine(keystore, scriptPubKey, isInvalid); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); } // P2SH multisig { CBasicKeyStore keystore; - keystore.AddKey(uncompressedKey); - keystore.AddKey(keys[1]); + BOOST_CHECK(keystore.AddKey(uncompressedKey)); + BOOST_CHECK(keystore.AddKey(keys[1])); - CScript redeemScript; - redeemScript << OP_2 << - ToByteVector(uncompressedPubkey) << - ToByteVector(pubkeys[1]) << - OP_2 << OP_CHECKMULTISIG; - - scriptPubKey.clear(); - scriptPubKey << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; + CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]}); + scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript)); // Keystore has no redeemScript - result = IsMine(keystore, scriptPubKey, isInvalid); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); // Keystore has redeemScript - keystore.AddCScript(redeemScript); - result = IsMine(keystore, scriptPubKey, isInvalid); + BOOST_CHECK(keystore.AddCScript(redeemScript)); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); - BOOST_CHECK(!isInvalid); } // P2WSH multisig with compressed keys { CBasicKeyStore keystore; - keystore.AddKey(keys[0]); - keystore.AddKey(keys[1]); + BOOST_CHECK(keystore.AddKey(keys[0])); + BOOST_CHECK(keystore.AddKey(keys[1])); - CScript witnessScript; - witnessScript << OP_2 << - ToByteVector(pubkeys[0]) << - ToByteVector(pubkeys[1]) << - OP_2 << OP_CHECKMULTISIG; - - uint256 scriptHash; - CSHA256().Write(&witnessScript[0], witnessScript.size()) - .Finalize(scriptHash.begin()); - - scriptPubKey.clear(); - scriptPubKey << OP_0 << ToByteVector(scriptHash); + CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]}); + scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript)); // Keystore has keys, but no witnessScript or P2SH redeemScript - result = IsMine(keystore, scriptPubKey, isInvalid); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); // Keystore has keys and witnessScript, but no P2SH redeemScript - keystore.AddCScript(witnessScript); - result = IsMine(keystore, scriptPubKey, isInvalid); + BOOST_CHECK(keystore.AddCScript(witnessScript)); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); // Keystore has keys, witnessScript, P2SH redeemScript - keystore.AddCScript(scriptPubKey); - result = IsMine(keystore, scriptPubKey, isInvalid); + BOOST_CHECK(keystore.AddCScript(scriptPubKey)); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); - BOOST_CHECK(!isInvalid); } // P2WSH multisig with uncompressed key { CBasicKeyStore keystore; - keystore.AddKey(uncompressedKey); - keystore.AddKey(keys[1]); + BOOST_CHECK(keystore.AddKey(uncompressedKey)); + BOOST_CHECK(keystore.AddKey(keys[1])); - CScript witnessScript; - witnessScript << OP_2 << - ToByteVector(uncompressedPubkey) << - ToByteVector(pubkeys[1]) << - OP_2 << OP_CHECKMULTISIG; - - uint256 scriptHash; - CSHA256().Write(&witnessScript[0], witnessScript.size()) - .Finalize(scriptHash.begin()); - - scriptPubKey.clear(); - scriptPubKey << OP_0 << ToByteVector(scriptHash); + CScript witnessScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]}); + scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript)); // Keystore has keys, but no witnessScript or P2SH redeemScript - result = IsMine(keystore, scriptPubKey, isInvalid); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); // Keystore has keys and witnessScript, but no P2SH redeemScript - keystore.AddCScript(witnessScript); - result = IsMine(keystore, scriptPubKey, isInvalid); + BOOST_CHECK(keystore.AddCScript(witnessScript)); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); // Keystore has keys, witnessScript, P2SH redeemScript - keystore.AddCScript(scriptPubKey); - result = IsMine(keystore, scriptPubKey, isInvalid); + BOOST_CHECK(keystore.AddCScript(scriptPubKey)); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(isInvalid); } // P2WSH multisig wrapped in P2SH { CBasicKeyStore keystore; - CScript witnessScript; - witnessScript << OP_2 << - ToByteVector(pubkeys[0]) << - ToByteVector(pubkeys[1]) << - OP_2 << OP_CHECKMULTISIG; - - uint256 scriptHash; - CSHA256().Write(&witnessScript[0], witnessScript.size()) - .Finalize(scriptHash.begin()); - - CScript redeemScript; - redeemScript << OP_0 << ToByteVector(scriptHash); - - scriptPubKey.clear(); - scriptPubKey << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; + CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]}); + CScript redeemScript = GetScriptForDestination(WitnessV0ScriptHash(witnessScript)); + scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript)); // Keystore has no witnessScript, P2SH redeemScript, or keys - result = IsMine(keystore, scriptPubKey, isInvalid); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); // Keystore has witnessScript and P2SH redeemScript, but no keys - keystore.AddCScript(redeemScript); - keystore.AddCScript(witnessScript); - result = IsMine(keystore, scriptPubKey, isInvalid); + BOOST_CHECK(keystore.AddCScript(redeemScript)); + BOOST_CHECK(keystore.AddCScript(witnessScript)); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); // Keystore has keys, witnessScript, P2SH redeemScript - keystore.AddKey(keys[0]); - keystore.AddKey(keys[1]); - result = IsMine(keystore, scriptPubKey, isInvalid); + BOOST_CHECK(keystore.AddKey(keys[0])); + BOOST_CHECK(keystore.AddKey(keys[1])); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); - BOOST_CHECK(!isInvalid); } // OP_RETURN { CBasicKeyStore keystore; - keystore.AddKey(keys[0]); + BOOST_CHECK(keystore.AddKey(keys[0])); scriptPubKey.clear(); scriptPubKey << OP_RETURN << ToByteVector(pubkeys[0]); - result = IsMine(keystore, scriptPubKey, isInvalid); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); } // witness unspendable { CBasicKeyStore keystore; - keystore.AddKey(keys[0]); + BOOST_CHECK(keystore.AddKey(keys[0])); scriptPubKey.clear(); scriptPubKey << OP_0 << ToByteVector(ParseHex("aabb")); - result = IsMine(keystore, scriptPubKey, isInvalid); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); } // witness unknown { CBasicKeyStore keystore; - keystore.AddKey(keys[0]); + BOOST_CHECK(keystore.AddKey(keys[0])); scriptPubKey.clear(); scriptPubKey << OP_16 << ToByteVector(ParseHex("aabb")); - result = IsMine(keystore, scriptPubKey, isInvalid); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); } // Nonstandard { CBasicKeyStore keystore; - keystore.AddKey(keys[0]); + BOOST_CHECK(keystore.AddKey(keys[0])); scriptPubKey.clear(); scriptPubKey << OP_9 << OP_ADD << OP_11 << OP_EQUAL; - result = IsMine(keystore, scriptPubKey, isInvalid); + result = IsMine(keystore, scriptPubKey); BOOST_CHECK_EQUAL(result, ISMINE_NO); - BOOST_CHECK(!isInvalid); } } diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index c05e60996d..4798909e2f 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2017 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -10,10 +10,10 @@ #include <script/script.h> #include <script/script_error.h> #include <script/sign.h> -#include <util.h> -#include <utilstrencodings.h> -#include <test/test_bitcoin.h> -#include <rpc/server.h> +#include <util/system.h> +#include <util/strencodings.h> +#include <test/setup_common.h> +#include <rpc/util.h> #if defined(HAVE_CONSENSUS_LIB) #include <script/bitcoinconsensus.h> @@ -184,11 +184,12 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScript stream << tx2; int libconsensus_flags = flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_ALL; if (libconsensus_flags == flags) { + int expectedSuccessCode = expect ? 1 : 0; if (flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS) { - BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(scriptPubKey.data(), scriptPubKey.size(), txCredit.vout[0].nValue, (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, nullptr) == expect, message); + BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(scriptPubKey.data(), scriptPubKey.size(), txCredit.vout[0].nValue, (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, nullptr) == expectedSuccessCode, message); } else { - BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(scriptPubKey.data(), scriptPubKey.size(), 0, (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, nullptr) == expect, message); - BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, nullptr) == expect,message); + BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(scriptPubKey.data(), scriptPubKey.size(), 0, (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, nullptr) == expectedSuccessCode, message); + BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, nullptr) == expectedSuccessCode, message); } } #endif @@ -369,7 +370,7 @@ public: std::vector<unsigned char> vchSig, r, s; uint32_t iter = 0; do { - key.Sign(hash, vchSig, iter++); + key.Sign(hash, vchSig, false, iter++); if ((lenS == 33) != (vchSig[5 + vchSig[3]] == 33)) { NegateSignatureS(vchSig); } @@ -515,7 +516,7 @@ BOOST_AUTO_TEST_CASE(script_build) tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG, "P2SH(P2PK), bad redeemscript", SCRIPT_VERIFY_P2SH, true ).PushSig(keys.key0).PushRedeem().DamagePush(10).ScriptError(SCRIPT_ERR_EVAL_FALSE)); - + tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey0.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG, "P2SH(P2PKH)", SCRIPT_VERIFY_P2SH, true ).PushSig(keys.key0).Push(keys.pubkey0).PushRedeem()); @@ -937,17 +938,19 @@ BOOST_AUTO_TEST_CASE(script_build) } } +#ifdef UPDATE_JSON_TESTS std::string strGen; - +#endif for (TestBuilder& test : tests) { test.Test(); std::string str = JSONPrettyPrint(test.GetJSON()); -#ifndef UPDATE_JSON_TESTS +#ifdef UPDATE_JSON_TESTS + strGen += str + ",\n"; +#else if (tests_set.count(str) == 0) { BOOST_CHECK_MESSAGE(false, "Missing auto script_valid test: " + test.GetComment()); } #endif - strGen += str + ",\n"; } #ifdef UPDATE_JSON_TESTS @@ -1011,23 +1014,45 @@ BOOST_AUTO_TEST_CASE(script_PushData) ScriptError err; std::vector<std::vector<unsigned char> > directStack; - BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err)); + BOOST_CHECK(EvalScript(directStack, CScript(direct, direct + sizeof(direct)), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); std::vector<std::vector<unsigned char> > pushdata1Stack; - BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err)); + BOOST_CHECK(EvalScript(pushdata1Stack, CScript(pushdata1, pushdata1 + sizeof(pushdata1)), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err)); BOOST_CHECK(pushdata1Stack == directStack); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); std::vector<std::vector<unsigned char> > pushdata2Stack; - BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err)); + BOOST_CHECK(EvalScript(pushdata2Stack, CScript(pushdata2, pushdata2 + sizeof(pushdata2)), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err)); BOOST_CHECK(pushdata2Stack == directStack); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); std::vector<std::vector<unsigned char> > pushdata4Stack; - BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err)); + BOOST_CHECK(EvalScript(pushdata4Stack, CScript(pushdata4, pushdata4 + sizeof(pushdata4)), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err)); BOOST_CHECK(pushdata4Stack == directStack); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); + + const std::vector<unsigned char> pushdata1_trunc{OP_PUSHDATA1, 1}; + const std::vector<unsigned char> pushdata2_trunc{OP_PUSHDATA2, 1, 0}; + const std::vector<unsigned char> pushdata4_trunc{OP_PUSHDATA4, 1, 0, 0, 0}; + + std::vector<std::vector<unsigned char>> stack_ignore; + BOOST_CHECK(!EvalScript(stack_ignore, CScript(pushdata1_trunc.begin(), pushdata1_trunc.end()), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err)); + BOOST_CHECK_EQUAL(err, SCRIPT_ERR_BAD_OPCODE); + BOOST_CHECK(!EvalScript(stack_ignore, CScript(pushdata2_trunc.begin(), pushdata2_trunc.end()), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err)); + BOOST_CHECK_EQUAL(err, SCRIPT_ERR_BAD_OPCODE); + BOOST_CHECK(!EvalScript(stack_ignore, CScript(pushdata4_trunc.begin(), pushdata4_trunc.end()), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err)); + BOOST_CHECK_EQUAL(err, SCRIPT_ERR_BAD_OPCODE); +} + +BOOST_AUTO_TEST_CASE(script_cltv_truncated) +{ + const auto script_cltv_trunc = CScript() << OP_CHECKLOCKTIMEVERIFY; + + std::vector<std::vector<unsigned char>> stack_ignore; + ScriptError err; + BOOST_CHECK(!EvalScript(stack_ignore, script_cltv_trunc, SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, BaseSignatureChecker(), SigVersion::BASE, &err)); + BOOST_CHECK_EQUAL(err, SCRIPT_ERR_INVALID_STACK_OPERATION); } static CScript @@ -1076,18 +1101,18 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12) const CTransaction txFrom12{BuildCreditingTransaction(scriptPubKey12)}; CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), CScriptWitness(), txFrom12); - CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12); + CScript goodsig1 = sign_multisig(scriptPubKey12, key1, CTransaction(txTo12)); BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); txTo12.vout[0].nValue = 2; BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); - CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12); + CScript goodsig2 = sign_multisig(scriptPubKey12, key2, CTransaction(txTo12)); BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); - CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12); + CScript badsig1 = sign_multisig(scriptPubKey12, key3, CTransaction(txTo12)); BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); } @@ -1109,62 +1134,71 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) std::vector<CKey> keys; keys.push_back(key1); keys.push_back(key2); - CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23); + CScript goodsig1 = sign_multisig(scriptPubKey23, keys, CTransaction(txTo23)); BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); keys.clear(); keys.push_back(key1); keys.push_back(key3); - CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23); + CScript goodsig2 = sign_multisig(scriptPubKey23, keys, CTransaction(txTo23)); BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); keys.clear(); keys.push_back(key2); keys.push_back(key3); - CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23); + CScript goodsig3 = sign_multisig(scriptPubKey23, keys, CTransaction(txTo23)); BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); keys.clear(); keys.push_back(key2); keys.push_back(key2); // Can't re-use sig - CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23); + CScript badsig1 = sign_multisig(scriptPubKey23, keys, CTransaction(txTo23)); BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order - CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23); + CScript badsig2 = sign_multisig(scriptPubKey23, keys, CTransaction(txTo23)); BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order - CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23); + CScript badsig3 = sign_multisig(scriptPubKey23, keys, CTransaction(txTo23)); BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys - CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23); + CScript badsig4 = sign_multisig(scriptPubKey23, keys, CTransaction(txTo23)); BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys - CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23); + CScript badsig5 = sign_multisig(scriptPubKey23, keys, CTransaction(txTo23)); BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); // Must have signatures - CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23); + CScript badsig6 = sign_multisig(scriptPubKey23, keys, CTransaction(txTo23)); BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err)); } +/* Wrapper around ProduceSignature to combine two scriptsigs */ +SignatureData CombineSignatures(const CTxOut& txout, const CMutableTransaction& tx, const SignatureData& scriptSig1, const SignatureData& scriptSig2) +{ + SignatureData data; + data.MergeSignatureData(scriptSig1); + data.MergeSignatureData(scriptSig2); + ProduceSignature(DUMMY_SIGNING_PROVIDER, MutableTransactionSignatureCreator(&tx, 0, txout.nValue), txout.scriptPubKey, data); + return data; +} + BOOST_AUTO_TEST_CASE(script_combineSigs) { - // Test the CombineSignatures function - CAmount amount = 0; + // Test the ProduceSignature's ability to combine signatures function CBasicKeyStore keystore; std::vector<CKey> keys; std::vector<CPubKey> pubkeys; @@ -1174,58 +1208,57 @@ BOOST_AUTO_TEST_CASE(script_combineSigs) key.MakeNewKey(i%2 == 1); keys.push_back(key); pubkeys.push_back(key.GetPubKey()); - keystore.AddKey(key); + BOOST_CHECK(keystore.AddKey(key)); } - CMutableTransaction txFrom = BuildCreditingTransaction(GetScriptForDestination(keys[0].GetPubKey().GetID())); - CMutableTransaction txTo = BuildSpendingTransaction(CScript(), CScriptWitness(), txFrom); + CMutableTransaction txFrom = BuildCreditingTransaction(GetScriptForDestination(PKHash(keys[0].GetPubKey()))); + CMutableTransaction txTo = BuildSpendingTransaction(CScript(), CScriptWitness(), CTransaction(txFrom)); CScript& scriptPubKey = txFrom.vout[0].scriptPubKey; - CScript& scriptSig = txTo.vin[0].scriptSig; + SignatureData scriptSig; SignatureData empty; - SignatureData combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, empty); + SignatureData combined = CombineSignatures(txFrom.vout[0], txTo, empty, empty); BOOST_CHECK(combined.scriptSig.empty()); // Single signature case: - SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); // changes scriptSig - combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty); - BOOST_CHECK(combined.scriptSig == scriptSig); - combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig)); - BOOST_CHECK(combined.scriptSig == scriptSig); - CScript scriptSigCopy = scriptSig; + BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 0, SIGHASH_ALL)); // changes scriptSig + scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]); + combined = CombineSignatures(txFrom.vout[0], txTo, scriptSig, empty); + BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig); + combined = CombineSignatures(txFrom.vout[0], txTo, empty, scriptSig); + BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig); + SignatureData scriptSigCopy = scriptSig; // Signing again will give a different, valid signature: - SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); - combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig)); - BOOST_CHECK(combined.scriptSig == scriptSigCopy || combined.scriptSig == scriptSig); + BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 0, SIGHASH_ALL)); + scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]); + combined = CombineSignatures(txFrom.vout[0], txTo, scriptSigCopy, scriptSig); + BOOST_CHECK(combined.scriptSig == scriptSigCopy.scriptSig || combined.scriptSig == scriptSig.scriptSig); // P2SH, single-signature case: CScript pkSingle; pkSingle << ToByteVector(keys[0].GetPubKey()) << OP_CHECKSIG; - keystore.AddCScript(pkSingle); - scriptPubKey = GetScriptForDestination(CScriptID(pkSingle)); - SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); - combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty); - BOOST_CHECK(combined.scriptSig == scriptSig); - combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig)); - BOOST_CHECK(combined.scriptSig == scriptSig); + BOOST_CHECK(keystore.AddCScript(pkSingle)); + scriptPubKey = GetScriptForDestination(ScriptHash(pkSingle)); + BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 0, SIGHASH_ALL)); + scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]); + combined = CombineSignatures(txFrom.vout[0], txTo, scriptSig, empty); + BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig); + combined = CombineSignatures(txFrom.vout[0], txTo, empty, scriptSig); + BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig); scriptSigCopy = scriptSig; - SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); - combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig)); - BOOST_CHECK(combined.scriptSig == scriptSigCopy || combined.scriptSig == scriptSig); - // dummy scriptSigCopy with placeholder, should always choose non-placeholder: - scriptSigCopy = CScript() << OP_0 << std::vector<unsigned char>(pkSingle.begin(), pkSingle.end()); - combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig)); - BOOST_CHECK(combined.scriptSig == scriptSig); - combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), SignatureData(scriptSigCopy)); - BOOST_CHECK(combined.scriptSig == scriptSig); + BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 0, SIGHASH_ALL)); + scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]); + combined = CombineSignatures(txFrom.vout[0], txTo, scriptSigCopy, scriptSig); + BOOST_CHECK(combined.scriptSig == scriptSigCopy.scriptSig || combined.scriptSig == scriptSig.scriptSig); // Hardest case: Multisig 2-of-3 scriptPubKey = GetScriptForMultisig(2, pubkeys); - keystore.AddCScript(scriptPubKey); - SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); - combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty); - BOOST_CHECK(combined.scriptSig == scriptSig); - combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig)); - BOOST_CHECK(combined.scriptSig == scriptSig); + BOOST_CHECK(keystore.AddCScript(scriptPubKey)); + BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 0, SIGHASH_ALL)); + scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]); + combined = CombineSignatures(txFrom.vout[0], txTo, scriptSig, empty); + BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig); + combined = CombineSignatures(txFrom.vout[0], txTo, empty, scriptSig); + BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig); // A couple of partially-signed versions: std::vector<unsigned char> sig1; @@ -1252,22 +1285,28 @@ BOOST_AUTO_TEST_CASE(script_combineSigs) CScript complete12 = CScript() << OP_0 << sig1 << sig2; CScript complete13 = CScript() << OP_0 << sig1 << sig3; CScript complete23 = CScript() << OP_0 << sig2 << sig3; - - combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1a), SignatureData(partial1b)); + SignatureData partial1_sigs; + partial1_sigs.signatures.emplace(keys[0].GetPubKey().GetID(), SigPair(keys[0].GetPubKey(), sig1)); + SignatureData partial2_sigs; + partial2_sigs.signatures.emplace(keys[1].GetPubKey().GetID(), SigPair(keys[1].GetPubKey(), sig2)); + SignatureData partial3_sigs; + partial3_sigs.signatures.emplace(keys[2].GetPubKey().GetID(), SigPair(keys[2].GetPubKey(), sig3)); + + combined = CombineSignatures(txFrom.vout[0], txTo, partial1_sigs, partial1_sigs); BOOST_CHECK(combined.scriptSig == partial1a); - combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1a), SignatureData(partial2a)); + combined = CombineSignatures(txFrom.vout[0], txTo, partial1_sigs, partial2_sigs); BOOST_CHECK(combined.scriptSig == complete12); - combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial2a), SignatureData(partial1a)); + combined = CombineSignatures(txFrom.vout[0], txTo, partial2_sigs, partial1_sigs); BOOST_CHECK(combined.scriptSig == complete12); - combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1b), SignatureData(partial2b)); + combined = CombineSignatures(txFrom.vout[0], txTo, partial1_sigs, partial2_sigs); BOOST_CHECK(combined.scriptSig == complete12); - combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial1b)); + combined = CombineSignatures(txFrom.vout[0], txTo, partial3_sigs, partial1_sigs); BOOST_CHECK(combined.scriptSig == complete13); - combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial2a), SignatureData(partial3a)); + combined = CombineSignatures(txFrom.vout[0], txTo, partial2_sigs, partial3_sigs); BOOST_CHECK(combined.scriptSig == complete23); - combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial2b)); + combined = CombineSignatures(txFrom.vout[0], txTo, partial3_sigs, partial2_sigs); BOOST_CHECK(combined.scriptSig == complete23); - combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial3a)); + combined = CombineSignatures(txFrom.vout[0], txTo, partial3_sigs, partial3_sigs); BOOST_CHECK(combined.scriptSig == partial3c); } @@ -1481,4 +1520,146 @@ BOOST_AUTO_TEST_CASE(script_can_append_self) BOOST_CHECK(s == d); } + +#if defined(HAVE_CONSENSUS_LIB) + +/* Test simple (successful) usage of bitcoinconsensus_verify_script */ +BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_returns_true) +{ + unsigned int libconsensus_flags = 0; + int nIn = 0; + + CScript scriptPubKey; + CScript scriptSig; + CScriptWitness wit; + + scriptPubKey << OP_1; + CTransaction creditTx = BuildCreditingTransaction(scriptPubKey, 1); + CTransaction spendTx = BuildSpendingTransaction(scriptSig, wit, creditTx); + + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << spendTx; + + bitcoinconsensus_error err; + int result = bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), nIn, libconsensus_flags, &err); + BOOST_CHECK_EQUAL(result, 1); + BOOST_CHECK_EQUAL(err, bitcoinconsensus_ERR_OK); +} + +/* Test bitcoinconsensus_verify_script returns invalid tx index err*/ +BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_tx_index_err) +{ + unsigned int libconsensus_flags = 0; + int nIn = 3; + + CScript scriptPubKey; + CScript scriptSig; + CScriptWitness wit; + + scriptPubKey << OP_EQUAL; + CTransaction creditTx = BuildCreditingTransaction(scriptPubKey, 1); + CTransaction spendTx = BuildSpendingTransaction(scriptSig, wit, creditTx); + + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << spendTx; + + bitcoinconsensus_error err; + int result = bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), nIn, libconsensus_flags, &err); + BOOST_CHECK_EQUAL(result, 0); + BOOST_CHECK_EQUAL(err, bitcoinconsensus_ERR_TX_INDEX); +} + +/* Test bitcoinconsensus_verify_script returns tx size mismatch err*/ +BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_tx_size) +{ + unsigned int libconsensus_flags = 0; + int nIn = 0; + + CScript scriptPubKey; + CScript scriptSig; + CScriptWitness wit; + + scriptPubKey << OP_EQUAL; + CTransaction creditTx = BuildCreditingTransaction(scriptPubKey, 1); + CTransaction spendTx = BuildSpendingTransaction(scriptSig, wit, creditTx); + + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << spendTx; + + bitcoinconsensus_error err; + int result = bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size() * 2, nIn, libconsensus_flags, &err); + BOOST_CHECK_EQUAL(result, 0); + BOOST_CHECK_EQUAL(err, bitcoinconsensus_ERR_TX_SIZE_MISMATCH); +} + +/* Test bitcoinconsensus_verify_script returns invalid tx serialization error */ +BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_tx_serialization) +{ + unsigned int libconsensus_flags = 0; + int nIn = 0; + + CScript scriptPubKey; + CScript scriptSig; + CScriptWitness wit; + + scriptPubKey << OP_EQUAL; + CTransaction creditTx = BuildCreditingTransaction(scriptPubKey, 1); + CTransaction spendTx = BuildSpendingTransaction(scriptSig, wit, creditTx); + + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << 0xffffffff; + + bitcoinconsensus_error err; + int result = bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), nIn, libconsensus_flags, &err); + BOOST_CHECK_EQUAL(result, 0); + BOOST_CHECK_EQUAL(err, bitcoinconsensus_ERR_TX_DESERIALIZE); +} + +/* Test bitcoinconsensus_verify_script returns amount required error */ +BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_amount_required_err) +{ + unsigned int libconsensus_flags = bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS; + int nIn = 0; + + CScript scriptPubKey; + CScript scriptSig; + CScriptWitness wit; + + scriptPubKey << OP_EQUAL; + CTransaction creditTx = BuildCreditingTransaction(scriptPubKey, 1); + CTransaction spendTx = BuildSpendingTransaction(scriptSig, wit, creditTx); + + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << spendTx; + + bitcoinconsensus_error err; + int result = bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), nIn, libconsensus_flags, &err); + BOOST_CHECK_EQUAL(result, 0); + BOOST_CHECK_EQUAL(err, bitcoinconsensus_ERR_AMOUNT_REQUIRED); +} + +/* Test bitcoinconsensus_verify_script returns invalid flags err */ +BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_invalid_flags) +{ + unsigned int libconsensus_flags = 1 << 3; + int nIn = 0; + + CScript scriptPubKey; + CScript scriptSig; + CScriptWitness wit; + + scriptPubKey << OP_EQUAL; + CTransaction creditTx = BuildCreditingTransaction(scriptPubKey, 1); + CTransaction spendTx = BuildSpendingTransaction(scriptSig, wit, creditTx); + + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << spendTx; + + bitcoinconsensus_error err; + int result = bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), nIn, libconsensus_flags, &err); + BOOST_CHECK_EQUAL(result, 0); + BOOST_CHECK_EQUAL(err, bitcoinconsensus_ERR_INVALID_FLAGS); +} + +#endif BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/scriptnum10.h b/src/test/scriptnum10.h index 9e88866cb0..e763b64275 100644 --- a/src/test/scriptnum10.h +++ b/src/test/scriptnum10.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2017 The Bitcoin Core developers +// Copyright (c) 2009-2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/scriptnum_tests.cpp b/src/test/scriptnum_tests.cpp index cd6e27d248..e7916f5000 100644 --- a/src/test/scriptnum_tests.cpp +++ b/src/test/scriptnum_tests.cpp @@ -1,10 +1,10 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <test/scriptnum10.h> #include <script/script.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> #include <limits.h> diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp index eba58e0042..2fab309aa4 100644 --- a/src/test/serialize_tests.cpp +++ b/src/test/serialize_tests.cpp @@ -1,11 +1,11 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <serialize.h> #include <streams.h> #include <hash.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <stdint.h> @@ -182,13 +182,13 @@ BOOST_AUTO_TEST_CASE(varints) CDataStream::size_type size = 0; for (int i = 0; i < 100000; i++) { ss << VARINT(i, VarIntMode::NONNEGATIVE_SIGNED); - size += ::GetSerializeSize(VARINT(i, VarIntMode::NONNEGATIVE_SIGNED), 0, 0); + size += ::GetSerializeSize(VARINT(i, VarIntMode::NONNEGATIVE_SIGNED), 0); BOOST_CHECK(size == ss.size()); } for (uint64_t i = 0; i < 100000000000ULL; i += 999999937) { ss << VARINT(i); - size += ::GetSerializeSize(VARINT(i), 0, 0); + size += ::GetSerializeSize(VARINT(i), 0); BOOST_CHECK(size == ss.size()); } @@ -200,7 +200,7 @@ BOOST_AUTO_TEST_CASE(varints) } for (uint64_t i = 0; i < 100000000000ULL; i += 999999937) { - uint64_t j = -1; + uint64_t j = std::numeric_limits<uint64_t>::max(); ss >> VARINT(j); BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i); } @@ -252,8 +252,8 @@ static bool isCanonicalException(const std::ios_base::failure& ex) // The string returned by what() can be different for different platforms. // Instead of directly comparing the ex.what() with an expected string, - // create an instance of exception to see if ex.what() matches - // the expected explanatory string returned by the exception instance. + // create an instance of exception to see if ex.what() matches + // the expected explanatory string returned by the exception instance. return strcmp(expectedException.what(), ex.what()) == 0; } diff --git a/src/test/test_bitcoin.cpp b/src/test/setup_common.cpp index e9814edc23..5b454da52b 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/setup_common.cpp @@ -1,43 +1,30 @@ -// Copyright (c) 2011-2017 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <test/test_bitcoin.h> +#include <test/setup_common.h> +#include <banman.h> #include <chainparams.h> #include <consensus/consensus.h> +#include <consensus/params.h> #include <consensus/validation.h> #include <crypto/sha256.h> -#include <validation.h> #include <miner.h> #include <net_processing.h> +#include <noui.h> #include <pow.h> -#include <ui_interface.h> -#include <streams.h> -#include <rpc/server.h> #include <rpc/register.h> +#include <rpc/server.h> #include <script/sigcache.h> +#include <streams.h> +#include <ui_interface.h> +#include <util/validation.h> +#include <validation.h> -void CConnmanTest::AddNode(CNode& node) -{ - LOCK(g_connman->cs_vNodes); - g_connman->vNodes.push_back(&node); -} - -void CConnmanTest::ClearNodes() -{ - LOCK(g_connman->cs_vNodes); - for (CNode* node : g_connman->vNodes) { - delete node; - } - g_connman->vNodes.clear(); -} - -uint256 insecure_rand_seed = GetRandHash(); -FastRandomContext insecure_rand_ctx(insecure_rand_seed); +const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr; -extern bool fPrintToConsole; -extern void noui_connect(); +FastRandomContext g_insecure_rand_ctx; std::ostream& operator<<(std::ostream& os, const uint256& num) { @@ -46,82 +33,94 @@ std::ostream& operator<<(std::ostream& os, const uint256& num) } BasicTestingSetup::BasicTestingSetup(const std::string& chainName) + : m_path_root(fs::temp_directory_path() / "test_common_" PACKAGE_NAME / strprintf("%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(1 << 30)))) { - SHA256AutoDetect(); - RandomInit(); - ECC_Start(); - SetupEnvironment(); - SetupNetworking(); - InitSignatureCache(); - InitScriptExecutionCache(); - fCheckBlockIndex = true; - SelectParams(chainName); + SHA256AutoDetect(); + ECC_Start(); + SetupEnvironment(); + SetupNetworking(); + InitSignatureCache(); + InitScriptExecutionCache(); + fCheckBlockIndex = true; + SelectParams(chainName); + static bool noui_connected = false; + if (!noui_connected) { noui_connect(); + noui_connected = true; + } } BasicTestingSetup::~BasicTestingSetup() { - ECC_Stop(); + fs::remove_all(m_path_root); + ECC_Stop(); +} + +fs::path BasicTestingSetup::SetDataDir(const std::string& name) +{ + fs::path ret = m_path_root / name; + fs::create_directories(ret); + gArgs.ForceSetArg("-datadir", ret.string()); + return ret; } TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(chainName) { + SetDataDir("tempdir"); const CChainParams& chainparams = Params(); - // Ideally we'd move all the RPC tests to the functional testing framework - // instead of unit tests, but for now we need these here. - - RegisterAllCoreRPCCommands(tableRPC); - ClearDatadirCache(); - pathTemp = fs::temp_directory_path() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(1 << 30))); - fs::create_directories(pathTemp); - gArgs.ForceSetArg("-datadir", pathTemp.string()); - - // We have to run a scheduler thread to prevent ActivateBestChain - // from blocking due to queue overrun. - threadGroup.create_thread(boost::bind(&CScheduler::serviceQueue, &scheduler)); - GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); - - mempool.setSanityCheck(1.0); - pblocktree.reset(new CBlockTreeDB(1 << 20, true)); - pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true)); - pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get())); - if (!LoadGenesisBlock(chainparams)) { - throw std::runtime_error("LoadGenesisBlock failed."); - } - { - CValidationState state; - if (!ActivateBestChain(state, chainparams)) { - throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", FormatStateMessage(state))); - } - } - nScriptCheckThreads = 3; - for (int i=0; i < nScriptCheckThreads-1; i++) - threadGroup.create_thread(&ThreadScriptCheck); - g_connman = std::unique_ptr<CConnman>(new CConnman(0x1337, 0x1337)); // Deterministic randomness for tests. - connman = g_connman.get(); - peerLogic.reset(new PeerLogicValidation(connman, scheduler)); + // Ideally we'd move all the RPC tests to the functional testing framework + // instead of unit tests, but for now we need these here. + + RegisterAllCoreRPCCommands(tableRPC); + ClearDatadirCache(); + + // We have to run a scheduler thread to prevent ActivateBestChain + // from blocking due to queue overrun. + threadGroup.create_thread(std::bind(&CScheduler::serviceQueue, &scheduler)); + GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); + + mempool.setSanityCheck(1.0); + pblocktree.reset(new CBlockTreeDB(1 << 20, true)); + pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true)); + pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get())); + if (!LoadGenesisBlock(chainparams)) { + throw std::runtime_error("LoadGenesisBlock failed."); + } + + CValidationState state; + if (!ActivateBestChain(state, chainparams)) { + throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", FormatStateMessage(state))); + } + + nScriptCheckThreads = 3; + for (int i = 0; i < nScriptCheckThreads - 1; i++) + threadGroup.create_thread([i]() { return ThreadScriptCheck(i); }); + + g_banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); + g_connman = MakeUnique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests. } TestingSetup::~TestingSetup() { - threadGroup.interrupt_all(); - threadGroup.join_all(); - GetMainSignals().FlushBackgroundCallbacks(); - GetMainSignals().UnregisterBackgroundSignalScheduler(); - g_connman.reset(); - peerLogic.reset(); - UnloadBlockIndex(); - pcoinsTip.reset(); - pcoinsdbview.reset(); - pblocktree.reset(); - fs::remove_all(pathTemp); + threadGroup.interrupt_all(); + threadGroup.join_all(); + GetMainSignals().FlushBackgroundCallbacks(); + GetMainSignals().UnregisterBackgroundSignalScheduler(); + g_connman.reset(); + g_banman.reset(); + UnloadBlockIndex(); + pcoinsTip.reset(); + pcoinsdbview.reset(); + pblocktree.reset(); } TestChain100Setup::TestChain100Setup() : TestingSetup(CBaseChainParams::REGTEST) { // CreateAndProcessBlock() does not support building SegWit blocks, so don't activate in these tests. // TODO: fix the code to support SegWit blocks. - UpdateVersionBitsParameters(Consensus::DEPLOYMENT_SEGWIT, 0, Consensus::BIP9Deployment::NO_TIMEOUT); + gArgs.ForceSetArg("-vbparams", strprintf("segwit:0:%d", (int64_t)Consensus::BIP9Deployment::NO_TIMEOUT)); + SelectParams(CBaseChainParams::REGTEST); + // Generate a 100-block chain: coinbaseKey.MakeNewKey(true); CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG; @@ -152,7 +151,7 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>& { LOCK(cs_main); unsigned int extraNonce = 0; - IncrementExtraNonce(&block, chainActive.Tip(), extraNonce); + IncrementExtraNonce(&block, ::ChainActive().Tip(), extraNonce); } while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce; diff --git a/src/test/test_bitcoin.h b/src/test/setup_common.h index d013613de2..893eca216d 100644 --- a/src/test/test_bitcoin.h +++ b/src/test/setup_common.h @@ -1,9 +1,9 @@ -// Copyright (c) 2015-2017 The Bitcoin Core developers +// Copyright (c) 2015-2019 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_TEST_BITCOIN_H -#define BITCOIN_TEST_TEST_BITCOIN_H +#ifndef BITCOIN_TEST_SETUP_COMMON_H +#define BITCOIN_TEST_SETUP_COMMON_H #include <chainparamsbase.h> #include <fs.h> @@ -15,27 +15,43 @@ #include <txmempool.h> #include <memory> +#include <type_traits> #include <boost/thread.hpp> -extern uint256 insecure_rand_seed; -extern FastRandomContext insecure_rand_ctx; +// Enable BOOST_CHECK_EQUAL for enum class types +template <typename T> +std::ostream& operator<<(typename std::enable_if<std::is_enum<T>::value, std::ostream>::type& stream, const T& e) +{ + return stream << static_cast<typename std::underlying_type<T>::type>(e); +} + +/** + * This global and the helpers that use it are not thread-safe. + * + * If thread-safety is needed, the global could be made thread_local (given + * that thread_local is supported on all architectures we support) or a + * per-thread instance could be used in the multi-threaded test. + */ +extern FastRandomContext g_insecure_rand_ctx; + +/** + * Flag to make GetRand in random.h return the same number + */ +extern bool g_mock_deterministic_tests; -static inline void SeedInsecureRand(bool fDeterministic = false) +static inline void SeedInsecureRand(bool deterministic = false) { - if (fDeterministic) { - insecure_rand_seed = uint256(); - } else { - insecure_rand_seed = GetRandHash(); - } - insecure_rand_ctx = FastRandomContext(insecure_rand_seed); + g_insecure_rand_ctx = FastRandomContext(deterministic); } -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(); } +static inline uint32_t InsecureRand32() { return g_insecure_rand_ctx.rand32(); } +static inline uint256 InsecureRand256() { return g_insecure_rand_ctx.rand256(); } +static inline uint64_t InsecureRandBits(int bits) { return g_insecure_rand_ctx.randbits(bits); } +static inline uint64_t InsecureRandRange(uint64_t range) { return g_insecure_rand_ctx.randrange(range); } +static inline bool InsecureRandBool() { return g_insecure_rand_ctx.randbool(); } + +static constexpr CAmount CENT{1000000}; /** Basic testing setup. * This just configures logging and chain parameters. @@ -45,25 +61,19 @@ struct BasicTestingSetup { explicit BasicTestingSetup(const std::string& chainName = CBaseChainParams::MAIN); ~BasicTestingSetup(); + + fs::path SetDataDir(const std::string& name); + +private: + const fs::path m_path_root; }; /** Testing setup that configures a complete environment. * Included are data directory, coins database, script check threads setup. */ -class CConnman; -class CNode; -struct CConnmanTest { - static void AddNode(CNode& node); - static void ClearNodes(); -}; - -class PeerLogicValidation; -struct TestingSetup: public BasicTestingSetup { - fs::path pathTemp; +struct TestingSetup : public BasicTestingSetup { boost::thread_group threadGroup; - CConnman* connman; CScheduler scheduler; - std::unique_ptr<PeerLogicValidation> peerLogic; explicit TestingSetup(const std::string& chainName = CBaseChainParams::MAIN); ~TestingSetup(); diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 6b8856ef47..15f8db899b 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -1,8 +1,8 @@ -// Copyright (c) 2013-2017 The Bitcoin Core developers +// Copyright (c) 2013-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <consensus/tx_verify.h> +#include <consensus/tx_check.h> #include <consensus/validation.h> #include <test/data/sighash.json.h> #include <hash.h> @@ -10,9 +10,9 @@ #include <script/script.h> #include <serialize.h> #include <streams.h> -#include <test/test_bitcoin.h> -#include <util.h> -#include <utilstrencodings.h> +#include <test/setup_common.h> +#include <util/system.h> +#include <util/strencodings.h> #include <version.h> #include <iostream> @@ -105,7 +105,7 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle) { txin.prevout.hash = InsecureRand256(); txin.prevout.n = InsecureRandBits(2); RandomScript(txin.scriptSig); - txin.nSequence = (InsecureRandBool()) ? InsecureRand32() : (unsigned int)-1; + txin.nSequence = (InsecureRandBool()) ? InsecureRand32() : std::numeric_limits<uint32_t>::max(); } for (int out = 0; out < outs; out++) { tx.vout.push_back(CTxOut()); @@ -137,7 +137,7 @@ BOOST_AUTO_TEST_CASE(sighash_test) int nIn = InsecureRandRange(txTo.vin.size()); uint256 sh, sho; - sho = SignatureHashOld(scriptCode, txTo, nIn, nHashType); + sho = SignatureHashOld(scriptCode, CTransaction(txTo), nIn, nHashType); sh = SignatureHash(scriptCode, txTo, nIn, nHashType, 0, SigVersion::BASE); #if defined(PRINT_SIGHASH_JSON) CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp index 86647e72eb..5c12ec13d2 100644 --- a/src/test/sigopcount_tests.cpp +++ b/src/test/sigopcount_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -9,7 +9,7 @@ #include <script/script.h> #include <script/standard.h> #include <uint256.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <vector> @@ -39,7 +39,7 @@ BOOST_AUTO_TEST_CASE(GetSigOpCount) BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 3U); BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 21U); - CScript p2sh = GetScriptForDestination(CScriptID(s1)); + CScript p2sh = GetScriptForDestination(ScriptHash(s1)); CScript scriptSig; scriptSig << OP_0 << Serialize(s1); BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig), 3U); @@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(GetSigOpCount) BOOST_CHECK_EQUAL(s2.GetSigOpCount(true), 3U); BOOST_CHECK_EQUAL(s2.GetSigOpCount(false), 20U); - p2sh = GetScriptForDestination(CScriptID(s2)); + p2sh = GetScriptForDestination(ScriptHash(s2)); BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(true), 0U); BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(false), 0U); CScript scriptSig2; @@ -102,7 +102,7 @@ static void BuildTxs(CMutableTransaction& spendingTx, CCoinsViewCache& coins, CM spendingTx.vout[0].nValue = 1; spendingTx.vout[0].scriptPubKey = CScript(); - AddCoins(coins, creationTx, 0); + AddCoins(coins, CTransaction(creationTx), 0); } BOOST_AUTO_TEST_CASE(GetTxSigOpCost) @@ -138,18 +138,18 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost) // is not accurate. assert(GetTransactionSigOpCost(CTransaction(creationTx), coins, flags) == MAX_PUBKEYS_PER_MULTISIG * WITNESS_SCALE_FACTOR); // Sanity check: script verification fails because of an invalid signature. - assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY); + assert(VerifyWithFlag(CTransaction(creationTx), spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY); } // Multisig nested in P2SH { CScript redeemScript = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY; - CScript scriptPubKey = GetScriptForDestination(CScriptID(redeemScript)); + CScript scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript)); CScript scriptSig = CScript() << OP_0 << OP_0 << ToByteVector(redeemScript); BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CScriptWitness()); assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2 * WITNESS_SCALE_FACTOR); - assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY); + assert(VerifyWithFlag(CTransaction(creationTx), spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY); } // P2WPKH witness program @@ -166,7 +166,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost) assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 1); // No signature operations if we don't verify the witness. assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags & ~SCRIPT_VERIFY_WITNESS) == 0); - assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_EQUALVERIFY); + assert(VerifyWithFlag(CTransaction(creationTx), spendingTx, flags) == SCRIPT_ERR_EQUALVERIFY); // The sig op cost for witness version != 0 is zero. assert(scriptPubKey[0] == 0x00); @@ -185,7 +185,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost) { CScript p2pk = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; CScript scriptSig = GetScriptForWitness(p2pk); - CScript scriptPubKey = GetScriptForDestination(CScriptID(scriptSig)); + CScript scriptPubKey = GetScriptForDestination(ScriptHash(scriptSig)); scriptSig = CScript() << ToByteVector(scriptSig); CScriptWitness scriptWitness; scriptWitness.stack.push_back(std::vector<unsigned char>(0)); @@ -193,7 +193,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost) BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness); assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 1); - assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_EQUALVERIFY); + assert(VerifyWithFlag(CTransaction(creationTx), spendingTx, flags) == SCRIPT_ERR_EQUALVERIFY); } // P2WSH witness program @@ -209,14 +209,14 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost) BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness); assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2); assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags & ~SCRIPT_VERIFY_WITNESS) == 0); - assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY); + assert(VerifyWithFlag(CTransaction(creationTx), spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY); } // P2WSH nested in P2SH { CScript witnessScript = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY; CScript redeemScript = GetScriptForWitness(witnessScript); - CScript scriptPubKey = GetScriptForDestination(CScriptID(redeemScript)); + CScript scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript)); CScript scriptSig = CScript() << ToByteVector(redeemScript); CScriptWitness scriptWitness; scriptWitness.stack.push_back(std::vector<unsigned char>(0)); @@ -225,7 +225,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost) BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness); assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2); - assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY); + assert(VerifyWithFlag(CTransaction(creationTx), spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY); } } diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp index 25c7e54808..3d39dfdb75 100644 --- a/src/test/skiplist_tests.cpp +++ b/src/test/skiplist_tests.cpp @@ -1,10 +1,10 @@ -// Copyright (c) 2014-2017 The Bitcoin Core developers +// Copyright (c) 2014-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <chain.h> -#include <util.h> -#include <test/test_bitcoin.h> +#include <util/system.h> +#include <test/setup_common.h> #include <vector> @@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_test) // Pick a random element in vBlocksMain. int r = InsecureRandRange(vBlocksMain.size()); int64_t test_time = vBlocksMain[r].nTime; - CBlockIndex *ret = chain.FindEarliestAtLeast(test_time); + CBlockIndex* ret = chain.FindEarliestAtLeast(test_time, 0); BOOST_CHECK(ret->nTimeMax >= test_time); BOOST_CHECK((ret->pprev==nullptr) || ret->pprev->nTimeMax < test_time); BOOST_CHECK(vBlocksMain[r].GetAncestor(ret->nHeight) == ret); @@ -146,7 +146,7 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_test) BOOST_AUTO_TEST_CASE(findearliestatleast_edge_test) { std::list<CBlockIndex> blocks; - for (unsigned int timeMax : {100, 100, 100, 200, 200, 200, 300, 300, 300}) { + for (const 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; @@ -158,23 +158,34 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_edge_test) 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_CHECK_EQUAL(chain.FindEarliestAtLeast(50, 0)->nHeight, 0); + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(100, 0)->nHeight, 0); + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(150, 0)->nHeight, 3); + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(200, 0)->nHeight, 3); + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(250, 0)->nHeight, 6); + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(300, 0)->nHeight, 6); + BOOST_CHECK(!chain.FindEarliestAtLeast(350, 0)); + + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, 0)->nHeight, 0); + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-1, 0)->nHeight, 0); + + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::min(), 0)->nHeight, 0); + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-int64_t(std::numeric_limits<unsigned int>::max()) - 1, 0)->nHeight, 0); + BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::max(), 0)); + BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<unsigned int>::max(), 0)); + BOOST_CHECK(!chain.FindEarliestAtLeast(int64_t(std::numeric_limits<unsigned int>::max()) + 1, 0)); + + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, -1)->nHeight, 0); + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, 0)->nHeight, 0); + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, 3)->nHeight, 3); + BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, 8)->nHeight, 8); + BOOST_CHECK(!chain.FindEarliestAtLeast(0, 9)); + + CBlockIndex* ret1 = chain.FindEarliestAtLeast(100, 2); + BOOST_CHECK(ret1->nTimeMax >= 100 && ret1->nHeight == 2); + BOOST_CHECK(!chain.FindEarliestAtLeast(300, 9)); + CBlockIndex* ret2 = chain.FindEarliestAtLeast(200, 4); + BOOST_CHECK(ret2->nTimeMax >= 200 && ret2->nHeight == 4); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp index 5d057108b1..4e37199c63 100644 --- a/src/test/streams_tests.cpp +++ b/src/test/streams_tests.cpp @@ -1,16 +1,13 @@ -// Copyright (c) 2012-2017 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <streams.h> #include <support/allocators/zeroafterfree.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> -#include <boost/assign/std/vector.hpp> // for 'operator+=()' #include <boost/test/unit_test.hpp> -using namespace boost::assign; // bring 'operator+=()' into scope - BOOST_FIXTURE_TEST_SUITE(streams_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(streams_vector_writer) @@ -71,6 +68,86 @@ BOOST_AUTO_TEST_CASE(streams_vector_writer) vch.clear(); } +BOOST_AUTO_TEST_CASE(streams_vector_reader) +{ + std::vector<unsigned char> vch = {1, 255, 3, 4, 5, 6}; + + VectorReader reader(SER_NETWORK, INIT_PROTO_VERSION, vch, 0); + BOOST_CHECK_EQUAL(reader.size(), 6); + BOOST_CHECK(!reader.empty()); + + // Read a single byte as an unsigned char. + unsigned char a; + reader >> a; + BOOST_CHECK_EQUAL(a, 1); + BOOST_CHECK_EQUAL(reader.size(), 5); + BOOST_CHECK(!reader.empty()); + + // Read a single byte as a signed char. + signed char b; + reader >> b; + BOOST_CHECK_EQUAL(b, -1); + BOOST_CHECK_EQUAL(reader.size(), 4); + BOOST_CHECK(!reader.empty()); + + // Read a 4 bytes as an unsigned int. + unsigned int c; + reader >> c; + BOOST_CHECK_EQUAL(c, 100992003); // 3,4,5,6 in little-endian base-256 + BOOST_CHECK_EQUAL(reader.size(), 0); + BOOST_CHECK(reader.empty()); + + // Reading after end of byte vector throws an error. + signed int d; + BOOST_CHECK_THROW(reader >> d, std::ios_base::failure); + + // Read a 4 bytes as a signed int from the beginning of the buffer. + VectorReader new_reader(SER_NETWORK, INIT_PROTO_VERSION, vch, 0); + new_reader >> d; + BOOST_CHECK_EQUAL(d, 67370753); // 1,255,3,4 in little-endian base-256 + BOOST_CHECK_EQUAL(new_reader.size(), 2); + BOOST_CHECK(!new_reader.empty()); + + // Reading after end of byte vector throws an error even if the reader is + // not totally empty. + BOOST_CHECK_THROW(new_reader >> d, std::ios_base::failure); +} + +BOOST_AUTO_TEST_CASE(bitstream_reader_writer) +{ + CDataStream data(SER_NETWORK, INIT_PROTO_VERSION); + + BitStreamWriter<CDataStream> bit_writer(data); + bit_writer.Write(0, 1); + bit_writer.Write(2, 2); + bit_writer.Write(6, 3); + bit_writer.Write(11, 4); + bit_writer.Write(1, 5); + bit_writer.Write(32, 6); + bit_writer.Write(7, 7); + bit_writer.Write(30497, 16); + bit_writer.Flush(); + + CDataStream data_copy(data); + uint32_t serialized_int1; + data >> serialized_int1; + BOOST_CHECK_EQUAL(serialized_int1, (uint32_t)0x7700C35A); // NOTE: Serialized as LE + uint16_t serialized_int2; + data >> serialized_int2; + BOOST_CHECK_EQUAL(serialized_int2, (uint16_t)0x1072); // NOTE: Serialized as LE + + BitStreamReader<CDataStream> bit_reader(data_copy); + BOOST_CHECK_EQUAL(bit_reader.Read(1), 0); + BOOST_CHECK_EQUAL(bit_reader.Read(2), 2); + BOOST_CHECK_EQUAL(bit_reader.Read(3), 6); + BOOST_CHECK_EQUAL(bit_reader.Read(4), 11); + BOOST_CHECK_EQUAL(bit_reader.Read(5), 1); + BOOST_CHECK_EQUAL(bit_reader.Read(6), 32); + BOOST_CHECK_EQUAL(bit_reader.Read(7), 7); + BOOST_CHECK_EQUAL(bit_reader.Read(16), 30497); + BOOST_CHECK_THROW(bit_reader.Read(8), std::ios_base::failure); +} + BOOST_AUTO_TEST_CASE(streams_serializedata_xor) { std::vector<char> in; @@ -79,45 +156,51 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor) CDataStream ds(in, 0, 0); // Degenerate case - - key += '\x00','\x00'; + + key.push_back('\x00'); + key.push_back('\x00'); ds.Xor(key); BOOST_CHECK_EQUAL( - std::string(expected_xor.begin(), expected_xor.end()), + std::string(expected_xor.begin(), expected_xor.end()), std::string(ds.begin(), ds.end())); - in += '\x0f','\xf0'; - expected_xor += '\xf0','\x0f'; - + in.push_back('\x0f'); + in.push_back('\xf0'); + expected_xor.push_back('\xf0'); + expected_xor.push_back('\x0f'); + // Single character key ds.clear(); ds.insert(ds.begin(), in.begin(), in.end()); key.clear(); - key += '\xff'; + key.push_back('\xff'); ds.Xor(key); BOOST_CHECK_EQUAL( - std::string(expected_xor.begin(), expected_xor.end()), - std::string(ds.begin(), ds.end())); - + std::string(expected_xor.begin(), expected_xor.end()), + std::string(ds.begin(), ds.end())); + // Multi character key in.clear(); expected_xor.clear(); - in += '\xf0','\x0f'; - expected_xor += '\x0f','\x00'; - + in.push_back('\xf0'); + in.push_back('\x0f'); + expected_xor.push_back('\x0f'); + expected_xor.push_back('\x00'); + ds.clear(); ds.insert(ds.begin(), in.begin(), in.end()); key.clear(); - key += '\xff','\x0f'; + key.push_back('\xff'); + key.push_back('\x0f'); ds.Xor(key); BOOST_CHECK_EQUAL( - std::string(expected_xor.begin(), expected_xor.end()), - std::string(ds.begin(), ds.end())); -} + std::string(expected_xor.begin(), expected_xor.end()), + std::string(ds.begin(), ds.end())); +} BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/sync_tests.cpp b/src/test/sync_tests.cpp new file mode 100644 index 0000000000..c1399d2dbe --- /dev/null +++ b/src/test/sync_tests.cpp @@ -0,0 +1,52 @@ +// Copyright (c) 2012-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <sync.h> +#include <test/setup_common.h> + +#include <boost/test/unit_test.hpp> + +namespace { +template <typename MutexType> +void TestPotentialDeadLockDetected(MutexType& mutex1, MutexType& mutex2) +{ + { + LOCK2(mutex1, mutex2); + } + bool error_thrown = false; + try { + LOCK2(mutex2, mutex1); + } catch (const std::logic_error& e) { + BOOST_CHECK_EQUAL(e.what(), "potential deadlock detected"); + error_thrown = true; + } + #ifdef DEBUG_LOCKORDER + BOOST_CHECK(error_thrown); + #else + BOOST_CHECK(!error_thrown); + #endif +} +} // namespace + +BOOST_FIXTURE_TEST_SUITE(sync_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(potential_deadlock_detected) +{ + #ifdef DEBUG_LOCKORDER + bool prev = g_debug_lockorder_abort; + g_debug_lockorder_abort = false; + #endif + + CCriticalSection rmutex1, rmutex2; + TestPotentialDeadLockDetected(rmutex1, rmutex2); + + Mutex mutex1, mutex2; + TestPotentialDeadLockDetected(mutex1, mutex2); + + #ifdef DEBUG_LOCKORDER + g_debug_lockorder_abort = prev; + #endif +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/test_bitcoin_fuzzy.cpp b/src/test/test_bitcoin_fuzzy.cpp deleted file mode 100644 index b2daa2adb5..0000000000 --- a/src/test/test_bitcoin_fuzzy.cpp +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright (c) 2009-2017 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#if defined(HAVE_CONFIG_H) -#include <config/bitcoin-config.h> -#endif - -#include <consensus/merkle.h> -#include <primitives/block.h> -#include <script/script.h> -#include <addrman.h> -#include <chain.h> -#include <coins.h> -#include <compressor.h> -#include <net.h> -#include <protocol.h> -#include <streams.h> -#include <undo.h> -#include <version.h> -#include <pubkey.h> -#include <blockencodings.h> - -#include <stdint.h> -#include <unistd.h> - -#include <algorithm> -#include <memory> -#include <vector> - -enum TEST_ID { - CBLOCK_DESERIALIZE=0, - CTRANSACTION_DESERIALIZE, - CBLOCKLOCATOR_DESERIALIZE, - CBLOCKMERKLEROOT, - CADDRMAN_DESERIALIZE, - CBLOCKHEADER_DESERIALIZE, - CBANENTRY_DESERIALIZE, - CTXUNDO_DESERIALIZE, - CBLOCKUNDO_DESERIALIZE, - CCOINS_DESERIALIZE, - CNETADDR_DESERIALIZE, - CSERVICE_DESERIALIZE, - CMESSAGEHEADER_DESERIALIZE, - CADDRESS_DESERIALIZE, - CINV_DESERIALIZE, - CBLOOMFILTER_DESERIALIZE, - CDISKBLOCKINDEX_DESERIALIZE, - CTXOUTCOMPRESSOR_DESERIALIZE, - BLOCKTRANSACTIONS_DESERIALIZE, - BLOCKTRANSACTIONSREQUEST_DESERIALIZE, - TEST_ID_END -}; - -static bool read_stdin(std::vector<uint8_t> &data) { - uint8_t buffer[1024]; - ssize_t length=0; - while((length = read(STDIN_FILENO, buffer, 1024)) > 0) { - data.insert(data.end(), buffer, buffer+length); - - if (data.size() > (1<<20)) return false; - } - return length==0; -} - -static int test_one_input(std::vector<uint8_t> buffer) { - if (buffer.size() < sizeof(uint32_t)) return 0; - - uint32_t test_id = 0xffffffff; - memcpy(&test_id, buffer.data(), sizeof(uint32_t)); - buffer.erase(buffer.begin(), buffer.begin() + sizeof(uint32_t)); - - if (test_id >= TEST_ID_END) return 0; - - CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); - try { - int nVersion; - ds >> nVersion; - ds.SetVersion(nVersion); - } catch (const std::ios_base::failure& e) { - return 0; - } - - switch(test_id) { - case CBLOCK_DESERIALIZE: - { - try - { - CBlock block; - ds >> block; - } catch (const std::ios_base::failure& e) {return 0;} - break; - } - case CTRANSACTION_DESERIALIZE: - { - try - { - CTransaction tx(deserialize, ds); - } catch (const std::ios_base::failure& e) {return 0;} - break; - } - case CBLOCKLOCATOR_DESERIALIZE: - { - try - { - CBlockLocator bl; - ds >> bl; - } catch (const std::ios_base::failure& e) {return 0;} - break; - } - case CBLOCKMERKLEROOT: - { - try - { - CBlock block; - ds >> block; - bool mutated; - BlockMerkleRoot(block, &mutated); - } catch (const std::ios_base::failure& e) {return 0;} - break; - } - case CADDRMAN_DESERIALIZE: - { - try - { - CAddrMan am; - ds >> am; - } catch (const std::ios_base::failure& e) {return 0;} - break; - } - case CBLOCKHEADER_DESERIALIZE: - { - try - { - CBlockHeader bh; - ds >> bh; - } catch (const std::ios_base::failure& e) {return 0;} - break; - } - case CBANENTRY_DESERIALIZE: - { - try - { - CBanEntry be; - ds >> be; - } catch (const std::ios_base::failure& e) {return 0;} - break; - } - case CTXUNDO_DESERIALIZE: - { - try - { - CTxUndo tu; - ds >> tu; - } catch (const std::ios_base::failure& e) {return 0;} - break; - } - case CBLOCKUNDO_DESERIALIZE: - { - try - { - CBlockUndo bu; - ds >> bu; - } catch (const std::ios_base::failure& e) {return 0;} - break; - } - case CCOINS_DESERIALIZE: - { - try - { - Coin coin; - ds >> coin; - } catch (const std::ios_base::failure& e) {return 0;} - break; - } - case CNETADDR_DESERIALIZE: - { - try - { - CNetAddr na; - ds >> na; - } catch (const std::ios_base::failure& e) {return 0;} - break; - } - case CSERVICE_DESERIALIZE: - { - try - { - CService s; - ds >> s; - } catch (const std::ios_base::failure& e) {return 0;} - break; - } - case CMESSAGEHEADER_DESERIALIZE: - { - CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00}; - try - { - CMessageHeader mh(pchMessageStart); - ds >> mh; - if (!mh.IsValid(pchMessageStart)) {return 0;} - } catch (const std::ios_base::failure& e) {return 0;} - break; - } - case CADDRESS_DESERIALIZE: - { - try - { - CAddress a; - ds >> a; - } catch (const std::ios_base::failure& e) {return 0;} - break; - } - case CINV_DESERIALIZE: - { - try - { - CInv i; - ds >> i; - } catch (const std::ios_base::failure& e) {return 0;} - break; - } - case CBLOOMFILTER_DESERIALIZE: - { - try - { - CBloomFilter bf; - ds >> bf; - } catch (const std::ios_base::failure& e) {return 0;} - break; - } - case CDISKBLOCKINDEX_DESERIALIZE: - { - try - { - CDiskBlockIndex dbi; - ds >> dbi; - } catch (const std::ios_base::failure& e) {return 0;} - break; - } - case CTXOUTCOMPRESSOR_DESERIALIZE: - { - CTxOut to; - CTxOutCompressor toc(to); - try - { - ds >> toc; - } catch (const std::ios_base::failure& e) {return 0;} - - break; - } - case BLOCKTRANSACTIONS_DESERIALIZE: - { - try - { - BlockTransactions bt; - ds >> bt; - } catch (const std::ios_base::failure& e) {return 0;} - - break; - } - case BLOCKTRANSACTIONSREQUEST_DESERIALIZE: - { - try - { - BlockTransactionsRequest btr; - ds >> btr; - } catch (const std::ios_base::failure& e) {return 0;} - - break; - } - default: - return 0; - } - return 0; -} - -static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle; -void initialize() { - globalVerifyHandle = std::unique_ptr<ECCVerifyHandle>(new ECCVerifyHandle()); -} - -// This function is used by libFuzzer -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - test_one_input(std::vector<uint8_t>(data, data + size)); - return 0; -} - -// This function is used by libFuzzer -extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) { - initialize(); - return 0; -} - -// Disabled under WIN32 due to clash with Cygwin's WinMain. -#ifndef WIN32 -// Declare main(...) "weak" to allow for libFuzzer linking. libFuzzer provides -// the main(...) function. -__attribute__((weak)) -#endif -int main(int argc, char **argv) -{ - initialize(); -#ifdef __AFL_INIT - // Enable AFL deferred forkserver mode. Requires compilation using - // afl-clang-fast++. See fuzzing.md for details. - __AFL_INIT(); -#endif - -#ifdef __AFL_LOOP - // Enable AFL persistent mode. Requires compilation using afl-clang-fast++. - // See fuzzing.md for details. - int ret = 0; - while (__AFL_LOOP(1000)) { - std::vector<uint8_t> buffer; - if (!read_stdin(buffer)) { - continue; - } - ret = test_one_input(buffer); - } - return ret; -#else - std::vector<uint8_t> buffer; - if (!read_stdin(buffer)) { - return 0; - } - return test_one_input(buffer); -#endif -} diff --git a/src/test/test_bitcoin_main.cpp b/src/test/test_bitcoin_main.cpp deleted file mode 100644 index e48c685b6b..0000000000 --- a/src/test/test_bitcoin_main.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2011-2017 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#define BOOST_TEST_MODULE Bitcoin Test Suite - -#include <net.h> - -#include <memory> - -#include <boost/test/unit_test.hpp> - -std::unique_ptr<CConnman> g_connman; - -[[noreturn]] void Shutdown(void* parg) -{ - std::exit(EXIT_SUCCESS); -} - -[[noreturn]] void StartShutdown() -{ - std::exit(EXIT_SUCCESS); -} - -bool ShutdownRequested() -{ - return false; -} diff --git a/src/test/timedata_tests.cpp b/src/test/timedata_tests.cpp index 5d93bc1efe..b4c0e6a0f4 100644 --- a/src/test/timedata_tests.cpp +++ b/src/test/timedata_tests.cpp @@ -1,9 +1,9 @@ -// Copyright (c) 2011-2017 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. // #include <timedata.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/torcontrol_tests.cpp b/src/test/torcontrol_tests.cpp index c7ceb2f1e9..6d8459f5b1 100644 --- a/src/test/torcontrol_tests.cpp +++ b/src/test/torcontrol_tests.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. // -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <torcontrol.h> #include <boost/test/unit_test.hpp> @@ -20,7 +20,6 @@ BOOST_FIXTURE_TEST_SUITE(torcontrol_tests, BasicTestingSetup) static void CheckSplitTorReplyLine(std::string input, std::string command, std::string args) { - BOOST_TEST_MESSAGE(std::string("CheckSplitTorReplyLine(") + input + ")"); auto ret = SplitTorReplyLine(input); BOOST_CHECK_EQUAL(ret.first, command); BOOST_CHECK_EQUAL(ret.second, args); @@ -61,7 +60,6 @@ BOOST_AUTO_TEST_CASE(util_SplitTorReplyLine) static void CheckParseTorReplyMapping(std::string input, std::map<std::string,std::string> expected) { - BOOST_TEST_MESSAGE(std::string("CheckParseTorReplyMapping(") + input + ")"); auto ret = ParseTorReplyMapping(input); BOOST_CHECK_EQUAL(ret.size(), expected.size()); auto r_it = ret.begin(); @@ -173,7 +171,6 @@ BOOST_AUTO_TEST_CASE(util_ParseTorReplyMapping) // Special handling for null case // (needed because string comparison reads the null as end-of-string) - BOOST_TEST_MESSAGE(std::string("CheckParseTorReplyMapping(Null=\"\\0\")")); auto ret = ParseTorReplyMapping("Null=\"\\0\""); BOOST_CHECK_EQUAL(ret.size(), 1U); auto r_it = ret.begin(); diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 65c5b8ea1d..f5ff18c055 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -1,25 +1,26 @@ -// Copyright (c) 2011-2017 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <test/data/tx_invalid.json.h> #include <test/data/tx_valid.json.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <clientversion.h> #include <checkqueue.h> -#include <consensus/tx_verify.h> +#include <consensus/tx_check.h> #include <consensus/validation.h> #include <core_io.h> #include <key.h> #include <keystore.h> #include <validation.h> #include <policy/policy.h> +#include <policy/settings.h> #include <script/script.h> #include <script/sign.h> #include <script/script_error.h> #include <script/standard.h> -#include <utilstrencodings.h> +#include <util/strencodings.h> #include <map> #include <string> @@ -65,7 +66,7 @@ unsigned int ParseScriptFlags(std::string strFlags) std::vector<std::string> words; boost::algorithm::split(words, strFlags, boost::algorithm::is_any_of(",")); - for (std::string word : words) + for (const std::string& word : words) { if (!mapFlagNames.count(word)) BOOST_ERROR("Bad test: unknown verification flag '" << word << "'"); @@ -273,11 +274,11 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests) CMutableTransaction tx; stream >> tx; CValidationState state; - BOOST_CHECK_MESSAGE(CheckTransaction(tx, state) && state.IsValid(), "Simple deserialized transaction should be valid."); + BOOST_CHECK_MESSAGE(CheckTransaction(CTransaction(tx), state) && state.IsValid(), "Simple deserialized transaction should be valid."); // Check that duplicate txins fail tx.vin.push_back(tx.vin[0]); - BOOST_CHECK_MESSAGE(!CheckTransaction(tx, state) || !state.IsValid(), "Transaction with duplicate txins should be invalid."); + BOOST_CHECK_MESSAGE(!CheckTransaction(CTransaction(tx), state) || !state.IsValid(), "Transaction with duplicate txins should be invalid."); } // @@ -306,14 +307,14 @@ SetupDummyInputs(CBasicKeyStore& keystoreRet, CCoinsViewCache& coinsRet) dummyTransactions[0].vout[0].scriptPubKey << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG; dummyTransactions[0].vout[1].nValue = 50*CENT; dummyTransactions[0].vout[1].scriptPubKey << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG; - AddCoins(coinsRet, dummyTransactions[0], 0); + AddCoins(coinsRet, CTransaction(dummyTransactions[0]), 0); dummyTransactions[1].vout.resize(2); dummyTransactions[1].vout[0].nValue = 21*CENT; - dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(key[2].GetPubKey().GetID()); + dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[2].GetPubKey())); dummyTransactions[1].vout[1].nValue = 22*CENT; - dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(key[3].GetPubKey().GetID()); - AddCoins(coinsRet, dummyTransactions[1], 0); + dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(PKHash(key[3].GetPubKey())); + AddCoins(coinsRet, CTransaction(dummyTransactions[1]), 0); return dummyTransactions; } @@ -340,8 +341,8 @@ BOOST_AUTO_TEST_CASE(test_Get) t1.vout[0].nValue = 90*CENT; t1.vout[0].scriptPubKey << OP_1; - BOOST_CHECK(AreInputsStandard(t1, coins)); - BOOST_CHECK_EQUAL(coins.GetValueIn(t1), (50+21+22)*CENT); + BOOST_CHECK(AreInputsStandard(CTransaction(t1), coins)); + BOOST_CHECK_EQUAL(coins.GetValueIn(CTransaction(t1)), (50+21+22)*CENT); } static void CreateCreditAndSpend(const CKeyStore& keystore, const CScript& outscript, CTransactionRef& output, CMutableTransaction& input, bool success = true) @@ -414,14 +415,15 @@ static void ReplaceRedeemScript(CScript& script, const CScript& redeemScript) script = PushAll(stack); } -BOOST_AUTO_TEST_CASE(test_big_witness_transaction) { +BOOST_AUTO_TEST_CASE(test_big_witness_transaction) +{ CMutableTransaction mtx; mtx.nVersion = 1; CKey key; key.MakeNewKey(true); // Need to use compressed keys in segwit or the signing will fail CBasicKeyStore keystore; - keystore.AddKeyPubKey(key, key.GetPubKey()); + BOOST_CHECK(keystore.AddKeyPubKey(key, key.GetPubKey())); CKeyID hash = key.GetPubKey().GetID(); CScript scriptPubKey = CScript() << OP_0 << std::vector<unsigned char>(hash.begin(), hash.end()); @@ -456,9 +458,8 @@ BOOST_AUTO_TEST_CASE(test_big_witness_transaction) { } CDataStream ssout(SER_NETWORK, PROTOCOL_VERSION); - auto vstream = WithOrVersion(&ssout, 0); - vstream << mtx; - CTransaction tx(deserialize, vstream); + ssout << mtx; + CTransaction tx(deserialize, ssout); // check all inputs concurrently, with the cache PrecomputedTransactionData txdata(tx); @@ -467,7 +468,7 @@ BOOST_AUTO_TEST_CASE(test_big_witness_transaction) { CCheckQueueControl<CScriptCheck> control(&scriptcheckqueue); for (int i=0; i<20; i++) - threadGroup.create_thread(boost::bind(&CCheckQueue<CScriptCheck>::Thread, boost::ref(scriptcheckqueue))); + threadGroup.create_thread(std::bind(&CCheckQueue<CScriptCheck>::Thread, std::ref(scriptcheckqueue))); std::vector<Coin> coins; for(uint32_t i = 0; i < mtx.vin.size(); i++) { @@ -494,6 +495,15 @@ BOOST_AUTO_TEST_CASE(test_big_witness_transaction) { threadGroup.join_all(); } +SignatureData CombineSignatures(const CMutableTransaction& input1, const CMutableTransaction& input2, const CTransactionRef tx) +{ + SignatureData sigdata; + sigdata = DataFromTransaction(input1, 0, tx->vout[0]); + sigdata.MergeSignatureData(DataFromTransaction(input2, 0, tx->vout[0])); + ProduceSignature(DUMMY_SIGNING_PROVIDER, MutableTransactionSignatureCreator(&input1, 0, tx->vout[0].nValue), tx->vout[0].scriptPubKey, sigdata); + return sigdata; +} + BOOST_AUTO_TEST_CASE(test_witness) { CBasicKeyStore keystore, keystore2; @@ -509,10 +519,10 @@ BOOST_AUTO_TEST_CASE(test_witness) pubkey3 = key3.GetPubKey(); pubkey1L = key1L.GetPubKey(); pubkey2L = key2L.GetPubKey(); - keystore.AddKeyPubKey(key1, pubkey1); - keystore.AddKeyPubKey(key2, pubkey2); - keystore.AddKeyPubKey(key1L, pubkey1L); - keystore.AddKeyPubKey(key2L, pubkey2L); + BOOST_CHECK(keystore.AddKeyPubKey(key1, pubkey1)); + BOOST_CHECK(keystore.AddKeyPubKey(key2, pubkey2)); + BOOST_CHECK(keystore.AddKeyPubKey(key1L, pubkey1L)); + BOOST_CHECK(keystore.AddKeyPubKey(key2L, pubkey2L)); CScript scriptPubkey1, scriptPubkey2, scriptPubkey1L, scriptPubkey2L, scriptMulti; scriptPubkey1 << ToByteVector(pubkey1) << OP_CHECKSIG; scriptPubkey2 << ToByteVector(pubkey2) << OP_CHECKSIG; @@ -522,23 +532,22 @@ BOOST_AUTO_TEST_CASE(test_witness) oneandthree.push_back(pubkey1); oneandthree.push_back(pubkey3); scriptMulti = GetScriptForMultisig(2, oneandthree); - keystore.AddCScript(scriptPubkey1); - keystore.AddCScript(scriptPubkey2); - keystore.AddCScript(scriptPubkey1L); - keystore.AddCScript(scriptPubkey2L); - keystore.AddCScript(scriptMulti); - keystore.AddCScript(GetScriptForWitness(scriptPubkey1)); - keystore.AddCScript(GetScriptForWitness(scriptPubkey2)); - keystore.AddCScript(GetScriptForWitness(scriptPubkey1L)); - keystore.AddCScript(GetScriptForWitness(scriptPubkey2L)); - keystore.AddCScript(GetScriptForWitness(scriptMulti)); - keystore2.AddCScript(scriptMulti); - keystore2.AddCScript(GetScriptForWitness(scriptMulti)); - keystore2.AddKeyPubKey(key3, pubkey3); + BOOST_CHECK(keystore.AddCScript(scriptPubkey1)); + BOOST_CHECK(keystore.AddCScript(scriptPubkey2)); + BOOST_CHECK(keystore.AddCScript(scriptPubkey1L)); + BOOST_CHECK(keystore.AddCScript(scriptPubkey2L)); + BOOST_CHECK(keystore.AddCScript(scriptMulti)); + BOOST_CHECK(keystore.AddCScript(GetScriptForWitness(scriptPubkey1))); + BOOST_CHECK(keystore.AddCScript(GetScriptForWitness(scriptPubkey2))); + BOOST_CHECK(keystore.AddCScript(GetScriptForWitness(scriptPubkey1L))); + BOOST_CHECK(keystore.AddCScript(GetScriptForWitness(scriptPubkey2L))); + BOOST_CHECK(keystore.AddCScript(GetScriptForWitness(scriptMulti))); + BOOST_CHECK(keystore2.AddCScript(scriptMulti)); + BOOST_CHECK(keystore2.AddCScript(GetScriptForWitness(scriptMulti))); + BOOST_CHECK(keystore2.AddKeyPubKey(key3, pubkey3)); CTransactionRef output1, output2; CMutableTransaction input1, input2; - SignatureData sigdata; // Normal pay-to-compressed-pubkey. CreateCreditAndSpend(keystore, scriptPubkey1, output1, input1); @@ -553,8 +562,8 @@ BOOST_AUTO_TEST_CASE(test_witness) CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false); // P2SH pay-to-compressed-pubkey. - CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey1)), output1, input1); - CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey2)), output2, input2); + CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(scriptPubkey1)), output1, input1); + CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(scriptPubkey2)), output2, input2); ReplaceRedeemScript(input2.vin[0].scriptSig, scriptPubkey1); CheckWithFlag(output1, input1, 0, true); CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true); @@ -578,8 +587,8 @@ BOOST_AUTO_TEST_CASE(test_witness) CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false); // P2SH witness pay-to-compressed-pubkey (v0). - CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey1))), output1, input1); - CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey2))), output2, input2); + CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(GetScriptForWitness(scriptPubkey1))), output1, input1); + CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(GetScriptForWitness(scriptPubkey2))), output2, input2); ReplaceRedeemScript(input2.vin[0].scriptSig, GetScriptForWitness(scriptPubkey1)); CheckWithFlag(output1, input1, 0, true); CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true); @@ -603,8 +612,8 @@ BOOST_AUTO_TEST_CASE(test_witness) CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false); // P2SH pay-to-uncompressed-pubkey. - CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey1L)), output1, input1); - CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey2L)), output2, input2); + CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(scriptPubkey1L)), output1, input1); + CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(scriptPubkey2L)), output2, input2); ReplaceRedeemScript(input2.vin[0].scriptSig, scriptPubkey1L); CheckWithFlag(output1, input1, 0, true); CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true); @@ -620,8 +629,8 @@ BOOST_AUTO_TEST_CASE(test_witness) CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey2L), output2, input2, false); // Signing disabled for P2SH witness pay-to-uncompressed-pubkey (v1). - CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey1L))), output1, input1, false); - CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey2L))), output2, input2, false); + CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(GetScriptForWitness(scriptPubkey1L))), output1, input1, false); + CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(GetScriptForWitness(scriptPubkey2L))), output2, input2, false); // Normal 2-of-2 multisig CreateCreditAndSpend(keystore, scriptMulti, output1, input1, false); @@ -629,18 +638,18 @@ BOOST_AUTO_TEST_CASE(test_witness) CreateCreditAndSpend(keystore2, scriptMulti, output2, input2, false); CheckWithFlag(output2, input2, 0, false); BOOST_CHECK(*output1 == *output2); - UpdateInput(input1.vin[0], CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0))); + UpdateInput(input1.vin[0], CombineSignatures(input1, input2, output1)); CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); // P2SH 2-of-2 multisig - CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptMulti)), output1, input1, false); + CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(scriptMulti)), output1, input1, false); CheckWithFlag(output1, input1, 0, true); CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, false); - CreateCreditAndSpend(keystore2, GetScriptForDestination(CScriptID(scriptMulti)), output2, input2, false); + CreateCreditAndSpend(keystore2, GetScriptForDestination(ScriptHash(scriptMulti)), output2, input2, false); CheckWithFlag(output2, input2, 0, true); CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH, false); BOOST_CHECK(*output1 == *output2); - UpdateInput(input1.vin[0], CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0))); + UpdateInput(input1.vin[0], CombineSignatures(input1, input2, output1)); CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true); CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); @@ -652,19 +661,19 @@ BOOST_AUTO_TEST_CASE(test_witness) CheckWithFlag(output2, input2, 0, true); CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false); BOOST_CHECK(*output1 == *output2); - UpdateInput(input1.vin[0], CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0))); + UpdateInput(input1.vin[0], CombineSignatures(input1, input2, output1)); CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true); CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); // P2SH witness 2-of-2 multisig - CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptMulti))), output1, input1, false); + CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(GetScriptForWitness(scriptMulti))), output1, input1, false); CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true); CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false); - CreateCreditAndSpend(keystore2, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptMulti))), output2, input2, false); + CreateCreditAndSpend(keystore2, GetScriptForDestination(ScriptHash(GetScriptForWitness(scriptMulti))), output2, input2, false); CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH, true); CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false); BOOST_CHECK(*output1 == *output2); - UpdateInput(input1.vin[0], CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0))); + UpdateInput(input1.vin[0], CombineSignatures(input1, input2, output1)); CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true); CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); } @@ -686,78 +695,78 @@ BOOST_AUTO_TEST_CASE(test_IsStandard) t.vout[0].nValue = 90*CENT; CKey key; key.MakeNewKey(true); - t.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID()); + t.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey())); std::string reason; - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); // Check dust with default relay fee: CAmount nDustThreshold = 182 * dustRelayFee.GetFeePerK()/1000; BOOST_CHECK_EQUAL(nDustThreshold, 546); // dust: t.vout[0].nValue = nDustThreshold - 1; - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); // not dust: t.vout[0].nValue = nDustThreshold; - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); // Check dust with odd relay fee to verify rounding: // nDustThreshold = 182 * 3702 / 1000 dustRelayFee = CFeeRate(3702); // dust: t.vout[0].nValue = 673 - 1; - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); // not dust: t.vout[0].nValue = 673; - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE); t.vout[0].scriptPubKey = CScript() << OP_1; - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); // MAX_OP_RETURN_RELAY-byte TX_NULL_DATA (standard) t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"); BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY, t.vout[0].scriptPubKey.size()); - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); // MAX_OP_RETURN_RELAY+1-byte TX_NULL_DATA (non-standard) t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3800"); BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY + 1, t.vout[0].scriptPubKey.size()); - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); // Data payload can be encoded in any way... t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex(""); - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("00") << ParseHex("01"); - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); // OP_RESERVED *is* considered to be a PUSHDATA type opcode by IsPushOnly()! t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_RESERVED << -1 << 0 << ParseHex("01") << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << 10 << 11 << 12 << 13 << 14 << 15 << 16; - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); t.vout[0].scriptPubKey = CScript() << OP_RETURN << 0 << ParseHex("01") << 2 << ParseHex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); // ...so long as it only contains PUSHDATA's t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_RETURN; - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); // TX_NULL_DATA w/o PUSHDATA t.vout.resize(1); t.vout[0].scriptPubKey = CScript() << OP_RETURN; - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); // Only one TX_NULL_DATA permitted in all cases t.vout.resize(2); t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"); t.vout[1].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"); - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"); t.vout[1].scriptPubKey = CScript() << OP_RETURN; - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); t.vout[0].scriptPubKey = CScript() << OP_RETURN; t.vout[1].scriptPubKey = CScript() << OP_RETURN; - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/txindex_tests.cpp b/src/test/txindex_tests.cpp index be7ee2428b..19561d4f67 100644 --- a/src/test/txindex_tests.cpp +++ b/src/test/txindex_tests.cpp @@ -1,12 +1,13 @@ -// Copyright (c) 2017-2018 The Bitcoin Core developers +// Copyright (c) 2017-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include <chainparams.h> #include <index/txindex.h> #include <script/standard.h> -#include <test/test_bitcoin.h> -#include <util.h> -#include <utiltime.h> +#include <test/setup_common.h> +#include <util/system.h> +#include <util/time.h> #include <validation.h> #include <boost/test/unit_test.hpp> @@ -38,6 +39,12 @@ BOOST_FIXTURE_TEST_CASE(txindex_initial_sync, TestChain100Setup) MilliSleep(100); } + // Check that txindex excludes genesis block transactions. + const CBlock& genesis_block = Params().GenesisBlock(); + for (const auto& txn : genesis_block.vtx) { + BOOST_CHECK(!txindex.FindTx(txn->GetHash(), block_hash, tx_disk)); + } + // Check that txindex has all txs that were in the chain before it started. for (const auto& txn : m_coinbase_txns) { if (!txindex.FindTx(txn->GetHash(), block_hash, tx_disk)) { @@ -49,7 +56,7 @@ BOOST_FIXTURE_TEST_CASE(txindex_initial_sync, TestChain100Setup) // Check that new transactions in new blocks make it into the index. for (int i = 0; i < 10; i++) { - CScript coinbase_script_pub_key = GetScriptForDestination(coinbaseKey.GetPubKey().GetID()); + CScript coinbase_script_pub_key = GetScriptForDestination(PKHash(coinbaseKey.GetPubKey())); std::vector<CMutableTransaction> no_txns; const CBlock& block = CreateAndProcessBlock(no_txns, coinbase_script_pub_key); const CTransaction& txn = *block.vtx[0]; @@ -61,6 +68,14 @@ BOOST_FIXTURE_TEST_CASE(txindex_initial_sync, TestChain100Setup) BOOST_ERROR("Read incorrect tx"); } } + + // shutdown sequence (c.f. Shutdown() in init.cpp) + txindex.Stop(); + + threadGroup.interrupt_all(); + threadGroup.join_all(); + + // Rest of shutdown sequence and destructors happen in ~TestingSetup() } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/txvalidation_tests.cpp b/src/test/txvalidation_tests.cpp index 2d1eb7b772..26ae7be202 100644 --- a/src/test/txvalidation_tests.cpp +++ b/src/test/txvalidation_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017 The Bitcoin Core developers +// Copyright (c) 2017-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -8,7 +8,7 @@ #include <consensus/validation.h> #include <primitives/transaction.h> #include <script/script.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> @@ -30,7 +30,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup) coinbaseTx.vout[0].nValue = 1 * CENT; coinbaseTx.vout[0].scriptPubKey = scriptPubKey; - assert(CTransaction(coinbaseTx).IsCoinBase()); + BOOST_CHECK(CTransaction(coinbaseTx).IsCoinBase()); CValidationState state; @@ -52,10 +52,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup) // Check that the validation state reflects the unsuccessful attempt. BOOST_CHECK(state.IsInvalid()); BOOST_CHECK_EQUAL(state.GetRejectReason(), "coinbase"); - - int nDoS; - BOOST_CHECK_EQUAL(state.IsInvalid(nDoS), true); - BOOST_CHECK_EQUAL(nDoS, 100); + BOOST_CHECK(state.GetReason() == ValidationInvalidReason::CONSENSUS); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp index d32d4b267c..fe30d5f3a7 100644 --- a/src/test/txvalidationcache_tests.cpp +++ b/src/test/txvalidationcache_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2017 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -11,8 +11,8 @@ #include <random.h> #include <script/standard.h> #include <script/sign.h> -#include <test/test_bitcoin.h> -#include <utiltime.h> +#include <test/setup_common.h> +#include <util/time.h> #include <core_io.h> #include <keystore.h> #include <policy/policy.h> @@ -66,18 +66,27 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) // Test 1: block with both of those transactions should be rejected. block = CreateAndProcessBlock(spends, scriptPubKey); - BOOST_CHECK(chainActive.Tip()->GetBlockHash() != block.GetHash()); + { + LOCK(cs_main); + BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() != block.GetHash()); + } // Test 2: ... and should be rejected if spend1 is in the memory pool BOOST_CHECK(ToMemPool(spends[0])); block = CreateAndProcessBlock(spends, scriptPubKey); - BOOST_CHECK(chainActive.Tip()->GetBlockHash() != block.GetHash()); + { + LOCK(cs_main); + BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() != block.GetHash()); + } mempool.clear(); // Test 3: ... and should be rejected if spend2 is in the memory pool BOOST_CHECK(ToMemPool(spends[1])); block = CreateAndProcessBlock(spends, scriptPubKey); - BOOST_CHECK(chainActive.Tip()->GetBlockHash() != block.GetHash()); + { + LOCK(cs_main); + BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() != block.GetHash()); + } mempool.clear(); // Final sanity test: first spend in mempool, second in block, that's OK: @@ -85,7 +94,10 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) oneSpend.push_back(spends[0]); BOOST_CHECK(ToMemPool(spends[1])); block = CreateAndProcessBlock(oneSpend, scriptPubKey); - BOOST_CHECK(chainActive.Tip()->GetBlockHash() == block.GetHash()); + { + LOCK(cs_main); + BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() == block.GetHash()); + } // spends[1] should have been removed from the mempool when the // block with spends[0] is accepted: BOOST_CHECK_EQUAL(mempool.size(), 0U); @@ -102,7 +114,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) // 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. -static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t failing_flags, bool add_to_cache) +static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t failing_flags, bool add_to_cache) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { PrecomputedTransactionData txdata(tx); // If we add many more flags, this loop can get too expensive, but we can @@ -151,13 +163,13 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) } CScript p2pk_scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG; - CScript p2sh_scriptPubKey = GetScriptForDestination(CScriptID(p2pk_scriptPubKey)); - CScript p2pkh_scriptPubKey = GetScriptForDestination(coinbaseKey.GetPubKey().GetID()); + CScript p2sh_scriptPubKey = GetScriptForDestination(ScriptHash(p2pk_scriptPubKey)); + CScript p2pkh_scriptPubKey = GetScriptForDestination(PKHash(coinbaseKey.GetPubKey())); CScript p2wpkh_scriptPubKey = GetScriptForWitness(p2pkh_scriptPubKey); CBasicKeyStore keystore; - keystore.AddKey(coinbaseKey); - keystore.AddCScript(p2pk_scriptPubKey); + BOOST_CHECK(keystore.AddKey(coinbaseKey)); + BOOST_CHECK(keystore.AddCScript(p2pk_scriptPubKey)); // flags to test: SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, SCRIPT_VERIFY_CHECKSEQUENCE_VERIFY, SCRIPT_VERIFY_NULLDUMMY, uncompressed pubkey thing @@ -198,20 +210,20 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) CValidationState state; PrecomputedTransactionData ptd_spend_tx(spend_tx); - BOOST_CHECK(!CheckInputs(spend_tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, nullptr)); + BOOST_CHECK(!CheckInputs(CTransaction(spend_tx), state, pcoinsTip.get(), 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.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, &scriptchecks)); + BOOST_CHECK(CheckInputs(CTransaction(spend_tx), state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, &scriptchecks)); BOOST_CHECK_EQUAL(scriptchecks.size(), 1U); // 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); + ValidateCheckInputsForAllFlags(CTransaction(spend_tx), SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC, false); } // And if we produce a block with this tx, it should be valid (DERSIG not @@ -219,10 +231,9 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) CBlock block; block = CreateAndProcessBlock({spend_tx}, p2pk_scriptPubKey); - BOOST_CHECK(chainActive.Tip()->GetBlockHash() == block.GetHash()); - BOOST_CHECK(pcoinsTip->GetBestBlock() == block.GetHash()); - LOCK(cs_main); + 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. @@ -238,7 +249,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) 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); + ValidateCheckInputsForAllFlags(CTransaction(invalid_under_p2sh_tx), SCRIPT_VERIFY_P2SH, true); } // Test CHECKLOCKTIMEVERIFY @@ -261,13 +272,13 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) 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); + ValidateCheckInputsForAllFlags(CTransaction(invalid_with_cltv_tx), SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, 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.get(), true, SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true, txdata, nullptr)); + BOOST_CHECK(CheckInputs(CTransaction(invalid_with_cltv_tx), state, pcoinsTip.get(), true, SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true, txdata, nullptr)); } // TEST CHECKSEQUENCEVERIFY @@ -289,13 +300,13 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) 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); + ValidateCheckInputsForAllFlags(CTransaction(invalid_with_csv_tx), SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, 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.get(), true, SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true, txdata, nullptr)); + BOOST_CHECK(CheckInputs(CTransaction(invalid_with_csv_tx), state, pcoinsTip.get(), true, SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true, txdata, nullptr)); } // TODO: add tests for remaining script flags @@ -314,15 +325,15 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) // Sign SignatureData sigdata; - ProduceSignature(keystore, MutableTransactionSignatureCreator(&valid_with_witness_tx, 0, 11*CENT, SIGHASH_ALL), spend_tx.vout[1].scriptPubKey, sigdata); + BOOST_CHECK(ProduceSignature(keystore, MutableTransactionSignatureCreator(&valid_with_witness_tx, 0, 11*CENT, SIGHASH_ALL), spend_tx.vout[1].scriptPubKey, sigdata)); UpdateInput(valid_with_witness_tx.vin[0], sigdata); // This should be valid under all script flags. - ValidateCheckInputsForAllFlags(valid_with_witness_tx, 0, true); + ValidateCheckInputsForAllFlags(CTransaction(valid_with_witness_tx), 0, true); // 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); + ValidateCheckInputsForAllFlags(CTransaction(valid_with_witness_tx), SCRIPT_VERIFY_WITNESS, true); } { @@ -342,12 +353,12 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) // Sign for (int i=0; i<2; ++i) { SignatureData sigdata; - ProduceSignature(keystore, MutableTransactionSignatureCreator(&tx, i, 11*CENT, SIGHASH_ALL), spend_tx.vout[i].scriptPubKey, sigdata); + BOOST_CHECK(ProduceSignature(keystore, MutableTransactionSignatureCreator(&tx, i, 11*CENT, SIGHASH_ALL), spend_tx.vout[i].scriptPubKey, sigdata)); UpdateInput(tx.vin[i], sigdata); } // This should be valid under all script flags - ValidateCheckInputsForAllFlags(tx, 0, true); + ValidateCheckInputsForAllFlags(CTransaction(tx), 0, true); // Check that if the second input is invalid, but the first input is // valid, the transaction is not cached. @@ -357,12 +368,12 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) CValidationState state; PrecomputedTransactionData txdata(tx); // This transaction is now invalid under segwit, because of the second input. - BOOST_CHECK(!CheckInputs(tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, nullptr)); + BOOST_CHECK(!CheckInputs(CTransaction(tx), state, pcoinsTip.get(), 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.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, &scriptchecks)); + BOOST_CHECK(CheckInputs(CTransaction(tx), state, pcoinsTip.get(), 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(), 2U); } diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp index 79217fa430..c1749fb856 100644 --- a/src/test/uint256_tests.cpp +++ b/src/test/uint256_tests.cpp @@ -1,10 +1,10 @@ -// Copyright (c) 2011-2017 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <arith_uint256.h> #include <uint256.h> #include <version.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/test/unit_test.hpp> #include <stdint.h> @@ -184,8 +184,8 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G BOOST_CHECK(OneL.begin() + 32 == OneL.end()); BOOST_CHECK(MaxL.begin() + 32 == MaxL.end()); BOOST_CHECK(TmpL.begin() + 32 == TmpL.end()); - BOOST_CHECK(GetSerializeSize(R1L, 0, PROTOCOL_VERSION) == 32); - BOOST_CHECK(GetSerializeSize(ZeroL, 0, PROTOCOL_VERSION) == 32); + BOOST_CHECK(GetSerializeSize(R1L, PROTOCOL_VERSION) == 32); + BOOST_CHECK(GetSerializeSize(ZeroL, PROTOCOL_VERSION) == 32); CDataStream ss(0, PROTOCOL_VERSION); ss << R1L; @@ -230,8 +230,8 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G BOOST_CHECK(OneS.begin() + 20 == OneS.end()); BOOST_CHECK(MaxS.begin() + 20 == MaxS.end()); BOOST_CHECK(TmpS.begin() + 20 == TmpS.end()); - BOOST_CHECK(GetSerializeSize(R1S, 0, PROTOCOL_VERSION) == 20); - BOOST_CHECK(GetSerializeSize(ZeroS, 0, PROTOCOL_VERSION) == 20); + BOOST_CHECK(GetSerializeSize(R1S, PROTOCOL_VERSION) == 20); + BOOST_CHECK(GetSerializeSize(ZeroS, PROTOCOL_VERSION) == 20); ss << R1S; BOOST_CHECK(ss.str() == std::string(R1Array,R1Array+20)); diff --git a/src/test/util.cpp b/src/test/util.cpp new file mode 100644 index 0000000000..64ecc6623a --- /dev/null +++ b/src/test/util.cpp @@ -0,0 +1,92 @@ +// Copyright (c) 2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <test/util.h> + +#include <chainparams.h> +#include <consensus/merkle.h> +#include <consensus/validation.h> +#include <key_io.h> +#include <miner.h> +#include <outputtype.h> +#include <pow.h> +#include <scheduler.h> +#include <script/standard.h> +#include <txdb.h> +#include <validation.h> +#include <validationinterface.h> +#ifdef ENABLE_WALLET +#include <wallet/wallet.h> +#endif + +#include <boost/thread.hpp> + +const std::string ADDRESS_BCRT1_UNSPENDABLE = "bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj"; + +#ifdef ENABLE_WALLET +std::string getnewaddress(CWallet& w) +{ + constexpr auto output_type = OutputType::BECH32; + + CPubKey new_key; + if (!w.GetKeyFromPool(new_key)) assert(false); + + w.LearnRelatedScripts(new_key, output_type); + const auto dest = GetDestinationForKey(new_key, output_type); + + w.SetAddressBook(dest, /* label */ "", "receive"); + + return EncodeDestination(dest); +} + +void importaddress(CWallet& wallet, const std::string& address) +{ + LOCK(wallet.cs_wallet); + const auto dest = DecodeDestination(address); + assert(IsValidDestination(dest)); + const auto script = GetScriptForDestination(dest); + wallet.MarkDirty(); + assert(!wallet.HaveWatchOnly(script)); + if (!wallet.AddWatchOnly(script, 0 /* nCreateTime */)) assert(false); + wallet.SetAddressBook(dest, /* label */ "", "receive"); +} +#endif // ENABLE_WALLET + +CTxIn generatetoaddress(const std::string& address) +{ + const auto dest = DecodeDestination(address); + assert(IsValidDestination(dest)); + const auto coinbase_script = GetScriptForDestination(dest); + + return MineBlock(coinbase_script); +} + +CTxIn MineBlock(const CScript& coinbase_scriptPubKey) +{ + auto block = PrepareBlock(coinbase_scriptPubKey); + + while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) { + ++block->nNonce; + assert(block->nNonce); + } + + bool processed{ProcessNewBlock(Params(), block, true, nullptr)}; + assert(processed); + + return CTxIn{block->vtx[0]->GetHash(), 0}; +} + +std::shared_ptr<CBlock> PrepareBlock(const CScript& coinbase_scriptPubKey) +{ + auto block = std::make_shared<CBlock>( + BlockAssembler{Params()} + .CreateNewBlock(coinbase_scriptPubKey) + ->block); + + LOCK(cs_main); + block->nTime = ::ChainActive().Tip()->GetMedianTimePast() + 1; + block->hashMerkleRoot = BlockMerkleRoot(*block); + + return block; +} diff --git a/src/test/util.h b/src/test/util.h new file mode 100644 index 0000000000..f90cb0d623 --- /dev/null +++ b/src/test/util.h @@ -0,0 +1,70 @@ +// Copyright (c) 2019 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_UTIL_H +#define BITCOIN_TEST_UTIL_H + +#include <memory> +#include <string> + +class CBlock; +class CScript; +class CTxIn; +class CWallet; + +// Constants // + +extern const std::string ADDRESS_BCRT1_UNSPENDABLE; + +// Lower-level utils // + +/** Returns the generated coin */ +CTxIn MineBlock(const CScript& coinbase_scriptPubKey); +/** Prepare a block to be mined */ +std::shared_ptr<CBlock> PrepareBlock(const CScript& coinbase_scriptPubKey); + + +// RPC-like // + +/** Import the address to the wallet */ +void importaddress(CWallet& wallet, const std::string& address); +/** Returns a new address from the wallet */ +std::string getnewaddress(CWallet& w); +/** Returns the generated coin */ +CTxIn generatetoaddress(const std::string& address); + +/** + * Increment a string. Useful to enumerate all fixed length strings with + * characters in [min_char, max_char]. + */ +template <typename CharType, size_t StringLength> +bool NextString(CharType (&string)[StringLength], CharType min_char, CharType max_char) +{ + for (CharType& elem : string) { + bool has_next = elem != max_char; + elem = elem < min_char || elem >= max_char ? min_char : CharType(elem + 1); + if (has_next) return true; + } + return false; +} + +/** + * Iterate over string values and call function for each string without + * successive duplicate characters. + */ +template <typename CharType, size_t StringLength, typename Fn> +void ForEachNoDup(CharType (&string)[StringLength], CharType min_char, CharType max_char, Fn&& fn) { + for (bool has_next = true; has_next; has_next = NextString(string, min_char, max_char)) { + int prev = -1; + bool skip_string = false; + for (CharType c : string) { + if (c == prev) skip_string = true; + if (skip_string || c < min_char || c > max_char) break; + prev = c; + } + if (!skip_string) fn(); + } +} + +#endif // BITCOIN_TEST_UTIL_H diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 611ccc9b77..51dd25ed1c 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -1,15 +1,16 @@ -// Copyright (c) 2011-2017 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <util.h> +#include <util/system.h> #include <clientversion.h> #include <primitives/transaction.h> #include <sync.h> -#include <utilstrencodings.h> -#include <utilmoneystr.h> -#include <test/test_bitcoin.h> +#include <test/util.h> +#include <util/strencodings.h> +#include <util/moneystr.h> +#include <test/setup_common.h> #include <stdint.h> #include <vector> @@ -36,8 +37,10 @@ BOOST_AUTO_TEST_CASE(util_criticalsection) do { TRY_LOCK(cs, lockTest); - if (lockTest) + if (lockTest) { + BOOST_CHECK(true); // Needed to suppress "Test case [...] did not check any assertions" break; + } BOOST_ERROR("break was swallowed!"); } while(0); @@ -78,80 +81,40 @@ BOOST_AUTO_TEST_CASE(util_HexStr) "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"); BOOST_CHECK_EQUAL( - HexStr(ParseHex_expected, ParseHex_expected + 5, true), - "04 67 8a fd b0"); - - BOOST_CHECK_EQUAL( HexStr(ParseHex_expected + sizeof(ParseHex_expected), ParseHex_expected + sizeof(ParseHex_expected)), ""); BOOST_CHECK_EQUAL( - HexStr(ParseHex_expected + sizeof(ParseHex_expected), - ParseHex_expected + sizeof(ParseHex_expected), true), - ""); - - BOOST_CHECK_EQUAL( HexStr(ParseHex_expected, ParseHex_expected), ""); - BOOST_CHECK_EQUAL( - HexStr(ParseHex_expected, ParseHex_expected, true), - ""); - std::vector<unsigned char> ParseHex_vec(ParseHex_expected, ParseHex_expected + 5); BOOST_CHECK_EQUAL( - HexStr(ParseHex_vec, true), - "04 67 8a fd b0"); - - BOOST_CHECK_EQUAL( HexStr(ParseHex_vec.rbegin(), ParseHex_vec.rend()), "b0fd8a6704" ); BOOST_CHECK_EQUAL( - HexStr(ParseHex_vec.rbegin(), ParseHex_vec.rend(), true), - "b0 fd 8a 67 04" - ); - - BOOST_CHECK_EQUAL( HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected), std::reverse_iterator<const uint8_t *>(ParseHex_expected)), "" ); BOOST_CHECK_EQUAL( - HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected), - std::reverse_iterator<const uint8_t *>(ParseHex_expected), true), - "" - ); - - BOOST_CHECK_EQUAL( HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected + 1), std::reverse_iterator<const uint8_t *>(ParseHex_expected)), "04" ); BOOST_CHECK_EQUAL( - HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected + 1), - std::reverse_iterator<const uint8_t *>(ParseHex_expected), true), - "04" - ); - - BOOST_CHECK_EQUAL( HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected + 5), std::reverse_iterator<const uint8_t *>(ParseHex_expected)), "b0fd8a6704" ); BOOST_CHECK_EQUAL( - HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected + 5), - std::reverse_iterator<const uint8_t *>(ParseHex_expected), true), - "b0 fd 8a 67 04" - ); - - BOOST_CHECK_EQUAL( HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected + 65), std::reverse_iterator<const uint8_t *>(ParseHex_expected)), "5f1df16b2b704c8a578d0bbaf74d385cde12c11ee50455f3c438ef4c3fbcf649b6de611feae06279a60939e028a8d65c10b73071a6f16719274855feb0fd8a6704" @@ -169,11 +132,6 @@ BOOST_AUTO_TEST_CASE(util_FormatISO8601Date) BOOST_CHECK_EQUAL(FormatISO8601Date(1317425777), "2011-09-30"); } -BOOST_AUTO_TEST_CASE(util_FormatISO8601Time) -{ - BOOST_CHECK_EQUAL(FormatISO8601Time(1317425777), "23:36:17Z"); -} - struct TestArgsManager : public ArgsManager { TestArgsManager() { m_network_only_args.clear(); } @@ -185,9 +143,10 @@ struct TestArgsManager : public ArgsManager { LOCK(cs_args); m_config_args.clear(); + m_config_sections.clear(); } std::string error; - ReadConfigStream(streamConfig, error); + BOOST_REQUIRE(ReadConfigStream(streamConfig, "", error)); } void SetNetworkOnlyArg(const std::string arg) { @@ -200,6 +159,9 @@ struct TestArgsManager : public ArgsManager AddArg(args[i], "", false, OptionsCategory::OPTIONS); } } + using ArgsManager::ReadConfigStream; + using ArgsManager::cs_args; + using ArgsManager::m_network; }; BOOST_AUTO_TEST_CASE(util_ParseParameters) @@ -210,13 +172,13 @@ BOOST_AUTO_TEST_CASE(util_ParseParameters) std::string error; testArgs.SetupArgs(4, avail_args); - testArgs.ParseParameters(0, (char**)argv_test, error); + BOOST_CHECK(testArgs.ParseParameters(0, (char**)argv_test, error)); BOOST_CHECK(testArgs.GetOverrideArgs().empty() && testArgs.GetConfigArgs().empty()); - testArgs.ParseParameters(1, (char**)argv_test, error); + BOOST_CHECK(testArgs.ParseParameters(1, (char**)argv_test, error)); BOOST_CHECK(testArgs.GetOverrideArgs().empty() && testArgs.GetConfigArgs().empty()); - testArgs.ParseParameters(7, (char**)argv_test, error); + BOOST_CHECK(testArgs.ParseParameters(7, (char**)argv_test, error)); // expectation: -ignored is ignored (program name argument), // -a, -b and -ccc end up in map, -d ignored because it is after // a non-option argument (non-GNU option parsing) @@ -242,10 +204,10 @@ BOOST_AUTO_TEST_CASE(util_GetBoolArg) "ignored", "-a", "-nob", "-c=0", "-d=1", "-e=false", "-f=true"}; std::string error; testArgs.SetupArgs(6, avail_args); - testArgs.ParseParameters(7, (char**)argv_test, error); + BOOST_CHECK(testArgs.ParseParameters(7, (char**)argv_test, error)); // Each letter should be set. - for (char opt : "abcdef") + for (const char opt : "abcdef") BOOST_CHECK(testArgs.IsArgSet({'-', opt}) || !opt); // Nothing else should be in the map @@ -278,7 +240,7 @@ BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases) const char *argv_test[] = {"ignored", "-nofoo", "-foo", "-nobar=0"}; testArgs.SetupArgs(2, avail_args); std::string error; - testArgs.ParseParameters(4, (char**)argv_test, error); + BOOST_CHECK(testArgs.ParseParameters(4, (char**)argv_test, error)); // This was passed twice, second one overrides the negative setting. BOOST_CHECK(!testArgs.IsArgNegated("-foo")); @@ -290,7 +252,7 @@ BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases) // Config test const char *conf_test = "nofoo=1\nfoo=1\nnobar=0\n"; - testArgs.ParseParameters(1, (char**)argv_test, error); + BOOST_CHECK(testArgs.ParseParameters(1, (char**)argv_test, error)); testArgs.ReadConfigString(conf_test); // This was passed twice, second one overrides the negative setting, @@ -305,7 +267,7 @@ BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases) // Combined test const char *combo_test_args[] = {"ignored", "-nofoo", "-bar"}; const char *combo_test_conf = "foo=1\nnobar=1\n"; - testArgs.ParseParameters(3, (char**)combo_test_args, error); + BOOST_CHECK(testArgs.ParseParameters(3, (char**)combo_test_args, error)); testArgs.ReadConfigString(combo_test_conf); // Command line overrides, but doesn't erase old setting @@ -394,7 +356,7 @@ BOOST_AUTO_TEST_CASE(util_ReadConfigStream) && test_args.GetArg("-iii", "xxx") == "xxx" ); - for (bool def : {false, true}) { + for (const bool def : {false, true}) { BOOST_CHECK(test_args.GetBoolArg("-a", def) && test_args.GetBoolArg("-b", def) && !test_args.GetBoolArg("-ccc", def) @@ -557,38 +519,38 @@ BOOST_AUTO_TEST_CASE(util_GetChainName) const char* testnetconf = "testnet=1\nregtest=0\n[test]\nregtest=1"; std::string error; - test_args.ParseParameters(0, (char**)argv_testnet, error); + BOOST_CHECK(test_args.ParseParameters(0, (char**)argv_testnet, error)); BOOST_CHECK_EQUAL(test_args.GetChainName(), "main"); - test_args.ParseParameters(2, (char**)argv_testnet, error); + BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_testnet, error)); BOOST_CHECK_EQUAL(test_args.GetChainName(), "test"); - test_args.ParseParameters(2, (char**)argv_regtest, error); + BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_regtest, error)); BOOST_CHECK_EQUAL(test_args.GetChainName(), "regtest"); - test_args.ParseParameters(3, (char**)argv_test_no_reg, error); + BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_test_no_reg, error)); BOOST_CHECK_EQUAL(test_args.GetChainName(), "test"); - test_args.ParseParameters(3, (char**)argv_both, error); + BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_both, error)); BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error); - test_args.ParseParameters(0, (char**)argv_testnet, error); + BOOST_CHECK(test_args.ParseParameters(0, (char**)argv_testnet, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_EQUAL(test_args.GetChainName(), "test"); - test_args.ParseParameters(2, (char**)argv_testnet, error); + BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_testnet, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_EQUAL(test_args.GetChainName(), "test"); - test_args.ParseParameters(2, (char**)argv_regtest, error); + BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_regtest, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error); - test_args.ParseParameters(3, (char**)argv_test_no_reg, error); + BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_test_no_reg, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_EQUAL(test_args.GetChainName(), "test"); - test_args.ParseParameters(3, (char**)argv_both, error); + BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_both, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error); @@ -596,27 +558,327 @@ BOOST_AUTO_TEST_CASE(util_GetChainName) // [test] regtest=1 potentially relevant) doesn't break things test_args.SelectConfigNetwork("test"); - test_args.ParseParameters(0, (char**)argv_testnet, error); + BOOST_CHECK(test_args.ParseParameters(0, (char**)argv_testnet, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_EQUAL(test_args.GetChainName(), "test"); - test_args.ParseParameters(2, (char**)argv_testnet, error); + BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_testnet, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_EQUAL(test_args.GetChainName(), "test"); - test_args.ParseParameters(2, (char**)argv_regtest, error); + BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_regtest, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error); - test_args.ParseParameters(2, (char**)argv_test_no_reg, error); + BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_test_no_reg, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_EQUAL(test_args.GetChainName(), "test"); - test_args.ParseParameters(3, (char**)argv_both, error); + BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_both, error)); test_args.ReadConfigString(testnetconf); BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error); } +// Test different ways settings can be merged, and verify results. This test can +// be used to confirm that updates to settings code don't change behavior +// unintentionally. +// +// The test covers: +// +// - Combining different setting actions. Possible actions are: configuring a +// setting, negating a setting (adding "-no" prefix), and configuring/negating +// settings in a network section (adding "main." or "test." prefixes). +// +// - Combining settings from command line arguments and a config file. +// +// - Combining SoftSet and ForceSet calls. +// +// - Testing "main" and "test" network values to make sure settings from network +// sections are applied and to check for mainnet-specific behaviors like +// inheriting settings from the default section. +// +// - Testing network-specific settings like "-wallet", that may be ignored +// outside a network section, and non-network specific settings like "-server" +// that aren't sensitive to the network. +// +struct ArgsMergeTestingSetup : public BasicTestingSetup { + //! Max number of actions to sequence together. Can decrease this when + //! debugging to make test results easier to understand. + static constexpr int MAX_ACTIONS = 3; + + enum Action { NONE, SET, NEGATE, SECTION_SET, SECTION_NEGATE }; + using ActionList = Action[MAX_ACTIONS]; + + //! Enumerate all possible test configurations. + template <typename Fn> + void ForEachMergeSetup(Fn&& fn) + { + ActionList arg_actions = {}; + ForEachNoDup(arg_actions, SET, SECTION_NEGATE, [&] { + ActionList conf_actions = {}; + ForEachNoDup(conf_actions, SET, SECTION_NEGATE, [&] { + for (bool soft_set : {false, true}) { + for (bool force_set : {false, true}) { + for (const std::string& section : {CBaseChainParams::MAIN, CBaseChainParams::TESTNET}) { + for (const std::string& network : {CBaseChainParams::MAIN, CBaseChainParams::TESTNET}) { + for (bool net_specific : {false, true}) { + fn(arg_actions, conf_actions, soft_set, force_set, section, network, net_specific); + } + } + } + } + } + }); + }); + } + + //! Translate actions into a list of <key>=<value> setting strings. + std::vector<std::string> GetValues(const ActionList& actions, + const std::string& section, + const std::string& name, + const std::string& value_prefix) + { + std::vector<std::string> values; + int suffix = 0; + for (Action action : actions) { + if (action == NONE) break; + std::string prefix; + if (action == SECTION_SET || action == SECTION_NEGATE) prefix = section + "."; + if (action == SET || action == SECTION_SET) { + for (int i = 0; i < 2; ++i) { + values.push_back(prefix + name + "=" + value_prefix + std::to_string(++suffix)); + } + } + if (action == NEGATE || action == SECTION_NEGATE) { + values.push_back(prefix + "no" + name + "=1"); + } + } + return values; + } +}; + +// Regression test covering different ways config settings can be merged. The +// test parses and merges settings, representing the results as strings that get +// compared against an expected hash. To debug, the result strings can be dumped +// to a file (see comments below). +BOOST_FIXTURE_TEST_CASE(util_ArgsMerge, ArgsMergeTestingSetup) +{ + CHash256 out_sha; + FILE* out_file = nullptr; + if (const char* out_path = getenv("ARGS_MERGE_TEST_OUT")) { + out_file = fsbridge::fopen(out_path, "w"); + if (!out_file) throw std::system_error(errno, std::generic_category(), "fopen failed"); + } + + ForEachMergeSetup([&](const ActionList& arg_actions, const ActionList& conf_actions, bool soft_set, bool force_set, + const std::string& section, const std::string& network, bool net_specific) { + TestArgsManager parser; + LOCK(parser.cs_args); + + std::string desc = "net="; + desc += network; + parser.m_network = network; + + const std::string& name = net_specific ? "wallet" : "server"; + const std::string key = "-" + name; + parser.AddArg(key, name, false, OptionsCategory::OPTIONS); + if (net_specific) parser.SetNetworkOnlyArg(key); + + auto args = GetValues(arg_actions, section, name, "a"); + std::vector<const char*> argv = {"ignored"}; + for (auto& arg : args) { + arg.insert(0, "-"); + desc += " "; + desc += arg; + argv.push_back(arg.c_str()); + } + std::string error; + BOOST_CHECK(parser.ParseParameters(argv.size(), argv.data(), error)); + BOOST_CHECK_EQUAL(error, ""); + + std::string conf; + for (auto& conf_val : GetValues(conf_actions, section, name, "c")) { + desc += " "; + desc += conf_val; + conf += conf_val; + conf += "\n"; + } + std::istringstream conf_stream(conf); + BOOST_CHECK(parser.ReadConfigStream(conf_stream, "filepath", error)); + BOOST_CHECK_EQUAL(error, ""); + + if (soft_set) { + desc += " soft"; + parser.SoftSetArg(key, "soft1"); + parser.SoftSetArg(key, "soft2"); + } + + if (force_set) { + desc += " force"; + parser.ForceSetArg(key, "force1"); + parser.ForceSetArg(key, "force2"); + } + + desc += " || "; + + if (!parser.IsArgSet(key)) { + desc += "unset"; + BOOST_CHECK(!parser.IsArgNegated(key)); + BOOST_CHECK_EQUAL(parser.GetArg(key, "default"), "default"); + BOOST_CHECK(parser.GetArgs(key).empty()); + } else if (parser.IsArgNegated(key)) { + desc += "negated"; + BOOST_CHECK_EQUAL(parser.GetArg(key, "default"), "0"); + BOOST_CHECK(parser.GetArgs(key).empty()); + } else { + desc += parser.GetArg(key, "default"); + desc += " |"; + for (const auto& arg : parser.GetArgs(key)) { + desc += " "; + desc += arg; + } + } + + std::set<std::string> ignored = parser.GetUnsuitableSectionOnlyArgs(); + if (!ignored.empty()) { + desc += " | ignored"; + for (const auto& arg : ignored) { + desc += " "; + desc += arg; + } + } + + desc += "\n"; + + out_sha.Write((const unsigned char*)desc.data(), desc.size()); + if (out_file) { + BOOST_REQUIRE(fwrite(desc.data(), 1, desc.size(), out_file) == desc.size()); + } + }); + + if (out_file) { + if (fclose(out_file)) throw std::system_error(errno, std::generic_category(), "fclose failed"); + out_file = nullptr; + } + + unsigned char out_sha_bytes[CSHA256::OUTPUT_SIZE]; + out_sha.Finalize(out_sha_bytes); + std::string out_sha_hex = HexStr(std::begin(out_sha_bytes), std::end(out_sha_bytes)); + + // If check below fails, should manually dump the results with: + // + // ARGS_MERGE_TEST_OUT=results.txt ./test_bitcoin --run_test=util_tests/util_ArgsMerge + // + // And verify diff against previous results to make sure the changes are expected. + // + // Results file is formatted like: + // + // <input> || <IsArgSet/IsArgNegated/GetArg output> | <GetArgs output> | <GetUnsuitable output> + BOOST_CHECK_EQUAL(out_sha_hex, "b835eef5977d69114eb039a976201f8c7121f34fe2b7ea2b73cafb516e5c9dc8"); +} + +// Similar test as above, but for ArgsManager::GetChainName function. +struct ChainMergeTestingSetup : public BasicTestingSetup { + static constexpr int MAX_ACTIONS = 2; + + enum Action { NONE, ENABLE_TEST, DISABLE_TEST, NEGATE_TEST, ENABLE_REG, DISABLE_REG, NEGATE_REG }; + using ActionList = Action[MAX_ACTIONS]; + + //! Enumerate all possible test configurations. + template <typename Fn> + void ForEachMergeSetup(Fn&& fn) + { + ActionList arg_actions = {}; + ForEachNoDup(arg_actions, ENABLE_TEST, NEGATE_REG, [&] { + ActionList conf_actions = {}; + ForEachNoDup(conf_actions, ENABLE_TEST, NEGATE_REG, [&] { fn(arg_actions, conf_actions); }); + }); + } +}; + +BOOST_FIXTURE_TEST_CASE(util_ChainMerge, ChainMergeTestingSetup) +{ + CHash256 out_sha; + FILE* out_file = nullptr; + if (const char* out_path = getenv("CHAIN_MERGE_TEST_OUT")) { + out_file = fsbridge::fopen(out_path, "w"); + if (!out_file) throw std::system_error(errno, std::generic_category(), "fopen failed"); + } + + ForEachMergeSetup([&](const ActionList& arg_actions, const ActionList& conf_actions) { + TestArgsManager parser; + LOCK(parser.cs_args); + parser.AddArg("-regtest", "regtest", false, OptionsCategory::OPTIONS); + parser.AddArg("-testnet", "testnet", false, OptionsCategory::OPTIONS); + + auto arg = [](Action action) { return action == ENABLE_TEST ? "-testnet=1" : + action == DISABLE_TEST ? "-testnet=0" : + action == NEGATE_TEST ? "-notestnet=1" : + action == ENABLE_REG ? "-regtest=1" : + action == DISABLE_REG ? "-regtest=0" : + action == NEGATE_REG ? "-noregtest=1" : nullptr; }; + + std::string desc; + std::vector<const char*> argv = {"ignored"}; + for (Action action : arg_actions) { + const char* argstr = arg(action); + if (!argstr) break; + argv.push_back(argstr); + desc += " "; + desc += argv.back(); + } + std::string error; + BOOST_CHECK(parser.ParseParameters(argv.size(), argv.data(), error)); + BOOST_CHECK_EQUAL(error, ""); + + std::string conf; + for (Action action : conf_actions) { + const char* argstr = arg(action); + if (!argstr) break; + desc += " "; + desc += argstr + 1; + conf += argstr + 1; + } + std::istringstream conf_stream(conf); + BOOST_CHECK(parser.ReadConfigStream(conf_stream, "filepath", error)); + BOOST_CHECK_EQUAL(error, ""); + + desc += " || "; + try { + desc += parser.GetChainName(); + } catch (const std::runtime_error& e) { + desc += "error: "; + desc += e.what(); + } + desc += "\n"; + + out_sha.Write((const unsigned char*)desc.data(), desc.size()); + if (out_file) { + BOOST_REQUIRE(fwrite(desc.data(), 1, desc.size(), out_file) == desc.size()); + } + }); + + if (out_file) { + if (fclose(out_file)) throw std::system_error(errno, std::generic_category(), "fclose failed"); + out_file = nullptr; + } + + unsigned char out_sha_bytes[CSHA256::OUTPUT_SIZE]; + out_sha.Finalize(out_sha_bytes); + std::string out_sha_hex = HexStr(std::begin(out_sha_bytes), std::end(out_sha_bytes)); + + // If check below fails, should manually dump the results with: + // + // CHAIN_MERGE_TEST_OUT=results.txt ./test_bitcoin --run_test=util_tests/util_ChainMerge + // + // And verify diff against previous results to make sure the changes are expected. + // + // Results file is formatted like: + // + // <input> || <output> + BOOST_CHECK_EQUAL(out_sha_hex, "b284f4b4a15dd6bf8c06213a69a004b1960388e1d9917173927db52ac220927f"); +} + BOOST_AUTO_TEST_CASE(util_FormatMoney) { BOOST_CHECK_EQUAL(FormatMoney(0), "0.00"); @@ -806,6 +1068,21 @@ BOOST_AUTO_TEST_CASE(gettime) BOOST_CHECK((GetTime() & ~0xFFFFFFFFLL) == 0); } +BOOST_AUTO_TEST_CASE(test_IsDigit) +{ + BOOST_CHECK_EQUAL(IsDigit('0'), true); + BOOST_CHECK_EQUAL(IsDigit('1'), true); + BOOST_CHECK_EQUAL(IsDigit('8'), true); + BOOST_CHECK_EQUAL(IsDigit('9'), true); + + BOOST_CHECK_EQUAL(IsDigit('0' - 1), false); + BOOST_CHECK_EQUAL(IsDigit('9' + 1), false); + BOOST_CHECK_EQUAL(IsDigit(0), false); + BOOST_CHECK_EQUAL(IsDigit(1), false); + BOOST_CHECK_EQUAL(IsDigit(8), false); + BOOST_CHECK_EQUAL(IsDigit(9), false); +} + BOOST_AUTO_TEST_CASE(test_ParseInt32) { int32_t n; @@ -1100,7 +1377,7 @@ static void TestOtherProcess(fs::path dirname, std::string lockname, int fd) BOOST_AUTO_TEST_CASE(test_LockDirectory) { - fs::path dirname = fs::temp_directory_path() / fs::unique_path(); + fs::path dirname = SetDataDir("test_LockDirectory") / fs::unique_path(); const std::string lockname = ".lock"; #ifndef WIN32 // Revert SIGCHLD to default, otherwise boost.test will catch and fail on @@ -1188,12 +1465,12 @@ BOOST_AUTO_TEST_CASE(test_LockDirectory) BOOST_AUTO_TEST_CASE(test_DirIsWritable) { - // Should be able to write to the system tmp dir. - fs::path tmpdirname = fs::temp_directory_path(); + // Should be able to write to the data dir. + fs::path tmpdirname = SetDataDir("test_DirIsWritable"); BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true); // Should not be able to write to a non-existent dir. - tmpdirname = fs::temp_directory_path() / fs::unique_path(); + tmpdirname = tmpdirname / fs::unique_path(); BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), false); fs::create_directory(tmpdirname); @@ -1202,4 +1479,43 @@ BOOST_AUTO_TEST_CASE(test_DirIsWritable) fs::remove(tmpdirname); } +BOOST_AUTO_TEST_CASE(test_ToLower) +{ + BOOST_CHECK_EQUAL(ToLower('@'), '@'); + BOOST_CHECK_EQUAL(ToLower('A'), 'a'); + BOOST_CHECK_EQUAL(ToLower('Z'), 'z'); + BOOST_CHECK_EQUAL(ToLower('['), '['); + BOOST_CHECK_EQUAL(ToLower(0), 0); + BOOST_CHECK_EQUAL(ToLower('\xff'), '\xff'); + + std::string testVector; + Downcase(testVector); + BOOST_CHECK_EQUAL(testVector, ""); + + testVector = "#HODL"; + Downcase(testVector); + BOOST_CHECK_EQUAL(testVector, "#hodl"); + + testVector = "\x00\xfe\xff"; + Downcase(testVector); + BOOST_CHECK_EQUAL(testVector, "\x00\xfe\xff"); +} + +BOOST_AUTO_TEST_CASE(test_ToUpper) +{ + BOOST_CHECK_EQUAL(ToUpper('`'), '`'); + BOOST_CHECK_EQUAL(ToUpper('a'), 'A'); + BOOST_CHECK_EQUAL(ToUpper('z'), 'Z'); + BOOST_CHECK_EQUAL(ToUpper('{'), '{'); + BOOST_CHECK_EQUAL(ToUpper(0), 0); + BOOST_CHECK_EQUAL(ToUpper('\xff'), '\xff'); +} + +BOOST_AUTO_TEST_CASE(test_Capitalize) +{ + BOOST_CHECK_EQUAL(Capitalize(""), ""); + BOOST_CHECK_EQUAL(Capitalize("bitcoin"), "Bitcoin"); + BOOST_CHECK_EQUAL(Capitalize("\x00\xfe\xff"), "\x00\xfe\xff"); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/util_threadnames_tests.cpp b/src/test/util_threadnames_tests.cpp new file mode 100644 index 0000000000..71c0168ca3 --- /dev/null +++ b/src/test/util_threadnames_tests.cpp @@ -0,0 +1,73 @@ +// Copyright (c) 2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <util/threadnames.h> +#include <test/setup_common.h> + +#include <thread> +#include <vector> +#include <set> +#include <mutex> + +#if defined(HAVE_CONFIG_H) +#include <config/bitcoin-config.h> +#endif + +#include <boost/test/unit_test.hpp> + +BOOST_FIXTURE_TEST_SUITE(util_threadnames_tests, BasicTestingSetup) + +const std::string TEST_THREAD_NAME_BASE = "test_thread."; + +/** + * Run a bunch of threads to all call util::ThreadRename. + * + * @return the set of name each thread has after attempted renaming. + */ +std::set<std::string> RenameEnMasse(int num_threads) +{ + std::vector<std::thread> threads; + std::set<std::string> names; + std::mutex lock; + + auto RenameThisThread = [&](int i) { + util::ThreadRename(TEST_THREAD_NAME_BASE + std::to_string(i)); + std::lock_guard<std::mutex> guard(lock); + names.insert(util::ThreadGetInternalName()); + }; + + for (int i = 0; i < num_threads; ++i) { + threads.push_back(std::thread(RenameThisThread, i)); + } + + for (std::thread& thread : threads) thread.join(); + + return names; +} + +/** + * Rename a bunch of threads with the same basename (expect_multiple=true), ensuring suffixes are + * applied properly. + */ +BOOST_AUTO_TEST_CASE(util_threadnames_test_rename_threaded) +{ + BOOST_CHECK_EQUAL(util::ThreadGetInternalName(), ""); + +#if !defined(HAVE_THREAD_LOCAL) + // This test doesn't apply to platforms where we don't have thread_local. + return; +#endif + + std::set<std::string> names = RenameEnMasse(100); + + BOOST_CHECK_EQUAL(names.size(), 100); + + // Names "test_thread.[n]" should exist for n = [0, 99] + for (int i = 0; i < 100; ++i) { + BOOST_CHECK(names.find(TEST_THREAD_NAME_BASE + std::to_string(i)) != names.end()); + } + +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp index 37c4f79133..5dee034b20 100644 --- a/src/test/validation_block_tests.cpp +++ b/src/test/validation_block_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 The Bitcoin Core developers +// Copyright (c) 2018-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -10,7 +10,7 @@ #include <miner.h> #include <pow.h> #include <random.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <validation.h> #include <validationinterface.h> @@ -23,7 +23,7 @@ BOOST_FIXTURE_TEST_SUITE(validation_block_tests, RegtestingSetup) struct TestSubscriber : public CValidationInterface { uint256 m_expected_tip; - TestSubscriber(uint256 tip) : m_expected_tip(tip) {} + explicit TestSubscriber(uint256 tip) : m_expected_tip(tip) {} void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) override { @@ -54,7 +54,7 @@ std::shared_ptr<CBlock> Block(const uint256& prev_hash) CScript pubKey; pubKey << i++ << OP_TRUE; - auto ptemplate = BlockAssembler(Params()).CreateNewBlock(pubKey, false); + auto ptemplate = BlockAssembler(Params()).CreateNewBlock(pubKey); auto pblock = std::make_shared<CBlock>(ptemplate->block); pblock->hashPrevBlock = prev_hash; pblock->nTime = ++time; @@ -104,8 +104,8 @@ void BuildChain(const uint256& root, int height, const unsigned int invalid_rate { if (height <= 0 || blocks.size() >= max_size) return; - bool gen_invalid = GetRand(100) < invalid_rate; - bool gen_fork = GetRand(100) < branch_rate; + bool gen_invalid = InsecureRandRange(100) < invalid_rate; + bool gen_fork = InsecureRandRange(100) < branch_rate; const std::shared_ptr<const CBlock> pblock = gen_invalid ? BadBlock(root) : GoodBlock(root); blocks.push_back(pblock); @@ -137,14 +137,14 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering) BOOST_CHECK(ProcessNewBlockHeaders(headers, state, Params())); // Connect the genesis block and drain any outstanding events - ProcessNewBlock(Params(), std::make_shared<CBlock>(Params().GenesisBlock()), true, &ignored); + BOOST_CHECK(ProcessNewBlock(Params(), std::make_shared<CBlock>(Params().GenesisBlock()), true, &ignored)); SyncWithValidationInterfaceQueue(); // subscribe to events (this subscriber will validate event ordering) const CBlockIndex* initial_tip = nullptr; { LOCK(cs_main); - initial_tip = chainActive.Tip(); + initial_tip = ::ChainActive().Tip(); } TestSubscriber sub(initial_tip->GetBlockHash()); RegisterValidationInterface(&sub); @@ -152,12 +152,13 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering) // create a bunch of threads that repeatedly process a block generated above at random // this will create parallelism and randomness inside validation - the ValidationInterface // will subscribe to events generated during block validation and assert on ordering invariance - boost::thread_group threads; + std::vector<std::thread> threads; for (int i = 0; i < 10; i++) { - threads.create_thread([&blocks]() { + threads.emplace_back([&blocks]() { bool ignored; + FastRandomContext insecure; for (int i = 0; i < 1000; i++) { - auto block = blocks[GetRand(blocks.size() - 1)]; + auto block = blocks[insecure.randrange(blocks.size() - 1)]; ProcessNewBlock(Params(), block, true, &ignored); } @@ -171,14 +172,17 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering) }); } - threads.join_all(); + for (auto& t : threads) { + t.join(); + } while (GetMainSignals().CallbacksPending() > 0) { MilliSleep(100); } UnregisterValidationInterface(&sub); - BOOST_CHECK_EQUAL(sub.m_expected_tip, chainActive.Tip()->GetBlockHash()); + LOCK(cs_main); + BOOST_CHECK_EQUAL(sub.m_expected_tip, ::ChainActive().Tip()->GetBlockHash()); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/main_tests.cpp b/src/test/validation_tests.cpp index 8676a099da..101025d31e 100644 --- a/src/test/main_tests.cpp +++ b/src/test/validation_tests.cpp @@ -1,17 +1,17 @@ -// Copyright (c) 2014-2017 The Bitcoin Core developers +// Copyright (c) 2014-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <chainparams.h> -#include <validation.h> #include <net.h> +#include <validation.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <boost/signals2/signal.hpp> #include <boost/test/unit_test.hpp> -BOOST_FIXTURE_TEST_SUITE(main_tests, TestingSetup) +BOOST_FIXTURE_TEST_SUITE(validation_tests, TestingSetup) static void TestBlockSubsidyHalvings(const Consensus::Params& consensusParams) { diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp index 692247ea88..0ca3a17974 100644 --- a/src/test/versionbits_tests.cpp +++ b/src/test/versionbits_tests.cpp @@ -1,10 +1,10 @@ -// Copyright (c) 2014-2017 The Bitcoin Core developers +// Copyright (c) 2014-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <chain.h> #include <versionbits.h> -#include <test/test_bitcoin.h> +#include <test/setup_common.h> #include <chainparams.h> #include <validation.h> #include <consensus/params.h> |